見出し画像

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を使うには、以下を準備する必要があります。

  1. Kustomizeのコマンド

  2. baseとoverlaysディレクトリとその配下のディレクトリ

  3. 全環境共通のマニフェスト

  4. 上書きする各環境固有のマニフェスト

  5. 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を動作させる上で必要なファイルを配置していきます。

全環境共通のマニフェスト

まずは全環境共通のマニフェスト定義が記述されたファイルを配置します。

前提として、例として運用している環境が以下の構成とします。

  1. 開発環境と本番環境の2環境がある

  2. Pod内のWebServerとして起動しているContainerがあり、開発環境は1台、本番環境は2台の構成

  3. 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の利用を検討してみてください。


執筆者プロフィール:北野 啓史
ITベンダーで13年間インフラエンジニアとして金融、人材などのお客様のITシステムの開発に携わってきた。
SHIFTには2021年に入社し、現在はコンテナ基盤のインフラ設計・構築を担当している。

お問合せはお気軽に
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/