kubernetes
kustomize

kustomize の overlayes の使用例

https://github.com/kubernetes-sigs/kustomize

kustomize についての概括的な記事は他にもあると思うので、個人的な備忘録として、普段どのように使用しているかを記述しておきます。

前提として、ここでは以下のような条件下での例になります。


  • base となる kubernetes ファイルが存在している。

  • それらに対して overlays の機能を用いて設定を変更して、環境に応じた kubernetes ファイルを生成する。


base

以下のような kubernetes ファイルが base ディレクトリに yaml ファイルとして置かれているとします。


  • base/configmap.yaml

  • base/service.yaml

  • base/deployment.yaml

例としてあげているのは、これらの要素を組み合わせて動作させる、nginx で動作する Web アプリケーションです。設定内容はかなり実際のものから端折ってます。


base/configmap.yaml

apiVersion: v1

kind: ConfigMap
metadata:
name: sada4j-configmap-nginx
data:
nginx.conf: |-
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 512;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

upstream sada4j {
server 127.0.0.1:8080;
}

server {
listen 80;
location / {
proxy_pass http://webapp;
proxy_redirect off;
}
}
}



base/service.yaml

apiVersion: v1

kind: Service
metadata:
name: sada4j-service
internal: "true"
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 80


base/deployment.yaml

apiVersion: apps/v1

kind: Deployment
metadata:
name: sada4j-deployment
spec:
replicas: 2
template:
metadata:
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
volumes:
- name: nginx-config
configMap:
name: sada4j-configmap-nginx


base/kustomization.yaml

resources:

- configmap.yaml
- service.yaml
- deployment.yaml

上述の kustomization.yaml に対して kustomize build base コマンドを実行すると、複数の yaml ファイルが一つのファイルに統合されます。

以下のように実行すると、統合されたファイルがひとまとめに kubernetes に apply されます。

$ kustomize build base | kubectl apply -f -

こういう形で、肥大化しがちな yaml ファイルを適切な粒度に分解し、実行時に Aggregation するというのが kustomize の初歩の使い方になります。


overlays


ケース1: deployment で動作するイメージを変更する


overlayes/kustomization.yaml

bases:

- ../base
patches:
- deployment.yaml


overlayes/deployment.yaml

apiVersion: apps/v1

kind: Deployment
metadata:
name: sada4j-deployment
spec:
template:
spec:
containers:
- name: nginx
image: custom.image.io/nginx:v1.0.5

kustomize では overlayes という機構を用いて、もととなるテンプレートファイルの一部の設定の上書きを行うことができます。

上記では、動作させる Image の定義のみを抜き出した patch ファイルを用意しています。こうすることで kustomize build 時に生成されるファイルの定義を上書くことができます。

$ kustomize build overlayes | kubectl apply -f -

と実行すると、もともと動作していた image が apply したものに差し替わります。

overlays 側でフレキシブルに使用する docker image を切り替える事ができますし、patch 用の yaml ファイルのみを編集すれば良いので作業範囲を局地化することができるため、非常にアプリケーション更新の運用がしやすくなります。


ケース2: replica 数と RollingUpdate Storategy を変更する


overlayes/kustomization.yaml

bases:

- ../base
patches:
- deployment.yaml


overlayes/deployment.yaml

apiVersion: apps/v1

kind: Deployment
metadata:
name: sada4j-deployment
spec:
replicas: 5
strategy:
rollingUpdate:
maxSurge: 2
maxUnavailable: 2
type: RollingUpdate

開発環境や本番環境など、環境に応じて pod の数や RollingUpdate 時の方式を変更したくなる時があります。

上記では、replica の数を 5 に変更し、明示的に設定していなかった RollingUpdate の定義を追記して上書く記述になっています。

他にも、deployment の記述内容について overlays で差し替える、というアイデアはいくつか思い浮かぶと思うので、以降では違う方面の例を記述します。


ケース3:namespace を変更する


overlayes/kustomization.yaml

namespace: sada4j-ng

bases:
- ../base
resources:
- namespace.yaml


overlayes/namespace.yaml

apiVersion: v1

kind: Namespace
metadata:
name: sada4j-ng

たとえば同一の構成の deployment を多数横並べにしたい時などに、個々の kubernetes の namespace を変更したいケースがあります。

overlays の kustomization.yaml で namespace を定義すると、kustomize コマンドで生成された kuberentes ファイルの中のすべての要素に対して設定された namespace が自動挿入されます。

基本的には kustomization.yaml 一箇所に記述するだけで該当リソースにあまねく反映されるので、便利ですね。

ただし、設定した namespace があらかじめ存在しない場合は、事前に namespace を作成する必要があります。

Namespace の記述では name に namespace として適用したい値を設定する必要があるため、kustomization.yaml で記述した内容をそのまま適用することが出来ません。なので、個別に namespace を定義した yaml を kustomization.yaml に関連付ける必要があります。

このやり方だと namespace の記述が散逸化するのでイケてないなと思いますが、今のところ他のやり方を見つけられていません。


ケース4:service の selector を変更する


overlays/kustomization.yaml

commonLabels:

env: prd
project: sada4j
cluster_id: 001
bases:
- ../base

kustomize 経由で service と deployment などを連携したファイルを統合すると、labels に設定されている値を自動的に selector の値として使用します。

上記を基に kustomize build を実行すると、selector の部分の記述は以下のようになります。

apiVersion: v1

kind: Service
metadata:
labels:
cluster_id: 001
env: prd
project: sada4j
name: sada4j-service
spec:
ports:
- port: 80
targetPort: 80
selector:
cluster_id: 001
env: prd
project: sada4j
type: LoadBalancer

このように kustomize build をすることが前提の環境の場合、base にあたるファイル内では selector の定義を書いていなくても自動的に label の値が挿入され、適切に service と deployment の結びつけが行われます。


ケース5:vars を用いてプレースホルダーに書かれた値の差し替えを行う

https://github.com/kubernetes-sigs/kustomize/blob/98a38eb290231dc8b8e4036a1548d375d6941d67/docs/kustomization.yaml


Vars are used to insert values from resources that cannot be referenced otherwise. For example if you need to pass a Service's name to the arguments or environment variables of a program but without hard coding the actual name of the Service you'd insert $(MY_SERVICE_NAME) into the value field of the env var or into the command or args of the container as shown here:


vars について、 kustomization.yaml のサンプルファイルなどにはこういう機能がある、と書かれていますが、意外と適用箇所が限られます。

以下のソース箇所が、vars で指定された値の差し替えを行っている箇所のようで、どの箇所に書かれたプレースホルダーが差し替え対象になっているかソースを通じて確認ができます。

https://github.com/kubernetes-sigs/kustomize/blob/c25ed7f7bc6ed2b940cce28ba82a5467da635206/pkg/transformers/refvars.go#L21-L104

逆にいうとここに書かれてない箇所にプレースホルダー定義を書いても差し替えは行われません。

そもそもプレースホルダー記述がある kubernetes の設定ファイルは、単体で動作させるのが難しくなるため、個人的には不便に感じあまり使用していません。

個人的には、overlays で値の差し替えを行いたい時は、 configmap や secret を generator やpatch / resource 経由で読み込み、そちらを用いて値を上書くこと方式を用いることが多いです。


まとめにかえて

まとまりが無いですが、思いつき次第追記していきます。