kustomizeの概要と使い方
こんにちは。インフラエンジニアの北野です。
kustomizeを使用する機会がありましたので、そこで得た知見を紹介したいと思います。 kustomizeについて知りたいかたの一助になれば幸いです。
kustomizeとは
Kustomizeは、複数のKubernetesクラスターを管理する状況において、リソースの構成や設定などをYAML形式で記述したマニフェストファイルをシンプルに管理できる便利なツールです。
Kubernetesではリソースの構成や設定などをYAML形式で記述したマニフェストで管理を行います。 マニフェストに定義した構成や設定を、マスターノードに登録することで、「Infrastructure as Code」を実現しています。 インフラの設計や設定がCode化されていると、構築が大変捗りますよね。
しかし、実務において、使用するクラスターは一つだけではなく、開発環境、本番環境など、複数あると思います。そういった場合、各環境毎にマニフェストファイルを作成すると、全環境共通のパラメータを変更したいと思ったとき 各環境のマニフェストファイルを新規作成する場合は、1から作成する必要がありますし、更新する場合は全てのファイルを更新する必要があります。 それでは、作成/修正する側も確認する側も大きな手間となり、修正漏れからの障害などのリスクが高まります。
そのような運用の問題をKustomizeは解決してくれます。
環境差異が無い箇所を定義したマニフェストファイル(kustomize用語でbase)と、 環境差異がある箇所だけを定義したマニフェストファイル(kustomize用語でoverlays)を作成すれば Kustomizeはその情報を用いて、各環境のマニフェストファイルを生成してくれます。
baseを作成すれば、そのbaseを全環境が使用でき、baseへの修正は全環境の定義に反映させることできます。
Kustomizeの機能の概念図
通常、マニフェストファイルを作成するときは、1つのファイルに作成したいリソースの定義を記述します。 しかし、Kustomizeを使用するときは、baseとoverlaysの2つのファイルにそのリソース定義を分けて記述します。 それぞの役割は分かれており、base側には全環境共通の定義を記述し、overlays側には各環境の固有の定義を記述するルールとなっています。 そして、kustomizeの機能でbaseの定義を基に、overlaysの定義を上書きし1つの定義を作成し、kubernetesに適用することができます。
Kustomizeの使い方
次にKustomizeを使い方を説明します。 Kustomizeを使うには、以下を準備する必要があります。
Kustomizeのコマンド
baseとoverlaysディレクトリとその配下のディレクトリ
全環境共通のマニフェスト
上書きする各環境固有のマニフェスト
kustomization.yamlファイル
Kustomizeのコマンド
Kustomizeのコマンドは、v1.14以上のkubectlコマンドに含まれており、オプションで指定することで使用することが出来ます。
kustomizeのコマンド自体をインストールすることで使用することもできますが、kubectlコマンドから使用すると導入や保守のコストを抑えれますね。 ただし、kubectlのバージョンが1.20と1.21では、kustomizeのバージョンはv2.0.3とv4.0.5で大きく違うので、kubectlは1.21以上で使用することをお勧めします。 また、kubectlのバージョンアップをしたとき、kustomizeのバージョンも変更される場合があるので、念のため作成されるマニフェストに想定外の差異が確認しておくと安心ですね。
よく使うコマンド
以下によく使うコマンドを記載します。
環境に適用せず、buildだけしてbaseとoverlaysの合成結果を確認したいとき
kubectl kustomize [overlaysのdirpath]
環境に適用せず、環境に適用済の定義と、kusomizeで作成した定義の比較をしたいとき
kubectl diff -k [overlaysのdirpath]
kusomizeで作成した定義を環境に適用するとき
kubectl apply -k [overlaysのdirpath]
baseとoverlaysディレクトリとその配下のディレクトリ
次にbaseディレクトリとoverlaysディレクトリを作成します。
ここでのディレクトリ構成は任意となりますが、誰にでもわかりやすいよう構成とするよう心がけましょう。
例えば、以下に示した環境を運用している場合はこのようなディレクトリ構成が良いかと思います。
本番環境と開発環境が存在する
それぞれの環境に1つのアプリの為に用意したnamespace(以下の例ではportal)が存在する
base
│ └─portal
overlays
├─prod
│ └─portal
└─dev
└─portal
作るディレクトリがたくさんありますが、以下のコマンドで簡単に作成できます。
mkdir -p base/portal
mkdir -p overlays/{prod,dev}/portal
以降は、作成したディレクトリにkustomizeを動作させる上で必要なファイルを配置していきます。
全環境共通のマニフェスト
まずは全環境共通のマニフェスト定義が記述されたファイルを配置します。
前提として、例として運用している環境が以下の構成とします。
開発環境と本番環境の2環境がある
Pod内のWebServerとして起動しているContainerがあり、開発環境は1台、本番環境は2台の構成
ServiceでContainerを公開する
ファイル名の制約
ファイル名に制約はありません。 作成例では、環境共通の定義ファイルは、deployment.yaml及びservice.yamlとし、 環境固有の設定を記載するファイルはdeployment-patch.yamlとservice-patch.yamlとしています。
配置場所
作成例では、deployment.yamlとservice.yamlを以下に配置します。
base
└─portal
├─deployment.yaml
└─service.yaml
記述内容
./base/portal/deployment.yaml
baseではdeploymentの共通の定義を記述します。 環境間の差異である、spec.replicasの定義を記述する必要はありません。
// ./base/portal/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: portal-nginx
spec:
selector:
matchLabels:
run: portal-nginx
template:
metadata:
labels:
run: portal-nginx
spec:
containers:
- name: portal-nginx
image: nginx
./base/portal/service.yaml
ここでもServiceの共通の定義を記述します。 今回の例ではServiceの設定に環境間の差異はないので、すべての定義を記述します。
// ./base/portal/service.yaml
apiVersion: v1
kind: Service
metadata:
name: portal-nginx
labels:
run: portal-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: portal-nginx
各環境固有のマニフェスト
ファイル名の制約
共通のマニフェストと同様ファイルの名に制約はありません。 例では環境固有の設定を記載するファイルはdeployment-patch.yamlとしています。配置場所
例として配置場所は以下となります。 例えば、prodのディレクトリ配下のdeployment-patch.yamlには本番環境固有の定義を記述します。
overlays
├─prod
│ └─portal
│ └─deployment-patch.yaml
└─dev
└─portal
└─deployment-patch.yaml
記述内容
./overlays/prod/portal/deployment-patch.yaml
ここでは本番環境の固有の設定を記述します。
まず上書きする対象の場所を特定するための情報として、baseで定義している内容と等しいapiVersionとkind、metadata.nameを記述します。 そして、固有の設定例として、spec.replicas: 2を記述します。
// ./overlays/prod/portal/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: portal-nginx
spec:
replicas: 2
./overlays/dev/portal/deployment-patch.yaml
固有の設定例として、spec.replicas: 1を記述します。
// ./overlays/dev/portal/deployment-patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: portal-nginx
spec:
replicas: 1
kustomization.yamlファイル
最後にkustomization.yamlファイルについて説明します。 kustomization.yamlは、kustomizeコマンドにどのファイルを使用して、マニフェスト定義を作成するかを指示する役割となります。
ファイル名の制約
ファイルの名称は必ず「kustomization.yaml」とする必要があります。配置場所
ディレクトリ構造の末端となる場所配置しましょう。 例では、portalのディレクトリ配下となります。
base
│ └─portal
│ ├─kustomization.yaml
│ ├─deployment.yaml
│ └─service.yaml
overlays
├─prod
│ └─portal
│ ├─kustomization.yaml
│ ├─deployment-patch.yaml
│ └─service-patch.yaml
└─dev
└─portal
├─kustomization.yaml
├─deployment-patch.yaml
└─service-patch.yaml
記述内容
記述内容は、base側とoverlays側かによって、違ってきます。それぞれ個別に説明します。
base側
./base/portal/kustomization.yaml
apiVersion:とkind:の行は書かなくても動作しますが、可読性を考慮して親切に書いておきましょう。
resources:は必須となります。ここに全環境共通の定義が記述されたマニフェストファイルのファイル名を記述しましょう。
// ./base/portal/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
overlays側
./overlays/prod/portal/kustomization.yaml
base側と同じく、apiVersion:とkind:の行は書かなくても動作しますが、可読性を考慮して親切に書いておきましょう。
bases:は必須となります。 ここに全環境共通の定義が記述されたマニフェストファイルの配置ディレクトリを相対パスで記述しましょう。
patchesStrategicMerge:も必須となります。ここに固有の定義が記述されたマニフェストファイルのファイル名を記述しましょう。
// ./overlays/prod/portal/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../../base/portal
patchesStrategicMerge:
- deployment-patch.yaml
./overlays/dev/portal/kustomization.yaml
./overlays/prod/portal/kustomization.yamlと同じ内容を記述します。
// ./overlays/dev/portal/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../../../base/portal
patchesStrategicMerge:
- deployment-patch.yaml
実際に使ってみよう
ここまでで説明した1~5を作ったとき、buildしてみると以下の結果となります。
prodディレクトリ配下のディレクトリを指定したので、replicasが2の状態になることを確認します。
# kubectl kustomize ./overlays/prod/portal/
apiVersion: v1
kind: Service
metadata:
labels:
run: portal-nginx
name: portal-nginx
spec:
ports:
- port: 80
protocol: TCP
selector:
run: portal-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: portal-nginx
spec:
replicas: 2
selector:
matchLabels:
run: portal-nginx
template:
metadata:
labels:
run: portal-nginx
spec:
containers:
- image: nginx
name: portal-nginx
本当に環境毎に違う設定が出力されるのか疑わしいので、 以下のようにdiff確認もしてみました。環境間でreplicasに差が出てますね。
# sdiff <(kubectl kustomize ./overlays/dev/portal/) <(kubectl kustomize ./overlays/prod/portal/)
apiVersion: v1 apiVersion: v1
kind: Service kind: Service
metadata: metadata:
labels: labels:
run: portal-nginx run: portal-nginx
name: portal-nginx name: portal-nginx
spec: spec:
ports: ports:
- port: 80 - port: 80
protocol: TCP protocol: TCP
selector: selector:
run: portal-nginx run: portal-nginx
--- ---
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: portal-nginx name: portal-nginx
spec: spec:
replicas: 1 | replicas: 2
selector: selector:
matchLabels: matchLabels:
run: portal-nginx run: portal-nginx
template: template:
metadata: metadata:
labels: labels:
run: portal-nginx run: portal-nginx
spec: spec:
containers: containers:
- image: nginx - image: nginx
name: portal-nginx name: portal-nginx
#
まとめ
コンテナを使っていると、簡単に複数の環境を用意できるため、環境が多重化しやすい傾向になると思います。
それはそれで開発するには便利なのですが、マニフェストファイルの管理が複雑化してしまいます。
複雑化すると、更新時の作業や確認負荷が大きくなり、いつか思わぬ人為的なミスによる事故に見舞われてしまう可能性が高まっていきます。
そのようなリスクをkustomizeは低減してくれます。 大規模なコンテナ環境を構築するときは、kustomizeの利用を検討してみてください。
お問合せはお気軽に
https://service.shiftinc.jp/contact/
SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/
SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/
SHIFTの導入事例
https://service.shiftinc.jp/case/
お役立ち資料はこちら
https://service.shiftinc.jp/resources/
SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/