Kubernetesやってみた:Kubernetes 1.14以降の Kustomize 機能 実践

Kubernetes 1.14 以降にGAになったkustomize 機能について実践ベースで紹介します。

こんにちは。ペットのゴールデンハムスターのキンクマを眺めながらWork From Homeしている高田です。 ゴールデンと言えば最近無料配信中のゴールデンカムイを最新話まで勢いで読み切りました。勢いも情報量も凄まじかったですが、面白かったです。

さて今回は、というよりは今回もKubernetesのKustomizeについての話となります。

Kubernetes 1.14 より Kustomize 機能がGAとなっています(https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/)

前回の私の記事で Kusutomize 機能のセットアップから使い方までを紹介しました。 Kubernetes 1.14以降のバージョンへアップグレードすることで、前回のようなセットアップは不要で、Kustomize機能をサブコマンドのように扱えるようになったようです。 ということで今回は Kubernetes 1.14以降のバージョンにて、実際に新しい方法で動作を確認していきたいと思います。

Kustomize機能とそのセットアップ方法については前回の記事を参照してみてください。

今回試した際のKubernetesバージョンはこちらです

Server Version: v1.18.20-gke.501

ディレクトリ構成は以下となります

$ tree .
.
└── base
    ├── deployment.yaml
    ├── kustomization.yaml
    └── service.yaml
└── overlays
  └── dev
      ├── deployment.yaml
      ├── kustomization.yaml
      └── service.yaml
    

baseディレクトリの準備

まずは構築場所の定義ということで、以下のような構成をとります

.
└── base
    ├── deployment.yaml
    ├── kustomization.yaml
    └── service.yaml

上記のコマンド結果はbase配下のディレクトリ構成を示しています。 各yamlファイル内は以下の様にします。

base/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx

base/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-nginx
  labels:
    run: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx

base/kustomization.yaml

resources:
- deployment.yaml
- service.yaml

確認

kubectl kustomize <kustomization_directory>を実行できるとのこと kustomization.yamlファイルを定義したディレクトリへ移動しkubectl kustomize .を実行すると、デプロイされるmanifestsを出力することができました。

$ cd ../base
$ kubectl kustomize .
apiVersion: v1
kind: Service
metadata:
  labels:
    run: my-nginx
  name: my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - image: nginx
        name: my-nginx

ovarlaysの準備

続いて拡張機能側をセットアップしていきます。

.
└── overlays
  └── dev
      ├── deployment.yaml
      ├── kustomization.yaml
      └── service.yaml

各yamlファイルの設定内容です

overlays/dev/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  selector:
    matchLabels:
      run: my-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        ports:
        - containerPort: 80

拡張設定用のkustomize.yamlは公式ドキュメントの通りにpod名にprefixを追加するだけのシンプルなものとします。

overlays/dev/kustomization.yaml

bases:
- ../../base
namePrefix: dev-

確認

base同様にkustomize.yamlファイルの定義したディレクトリ先で実行可能です。

apiVersion: v1
kind: Service
metadata:
  labels:
    run: my-nginx
  name: dev-my-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dev-my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - image: nginx
        name: my-nginx

ディレクトリを間違えてたり、kustomization.yamlで定義したファイル名が間違っていると以下の様にエラーになります。 以下は、ディレクトリを謝って確認コマンドを実行したときの実行例です。

# "overlays/dev/" ディレクトリではなく、"overlays/" ディレクトリで実行すると:

$ cd overlays
$ kubectl kustomize .
Error: unable to find one of 'kustomization.yaml', 'kustomization.yml' or 'Kustomization' in directory '/home/takadamio/polaris-dev-etc/manifest/overlays'


Examples:
  # Use the current working directory
  kubectl kustomize .

  # Use some shared configuration directory
  kubectl kustomize /home/configuration/production

  # Use a URL
  kubectl kustomize github.com/kubernetes-sigs/kustomize.git/examples/helloWorld?ref=v1.0.6

Usage:
  kubectl kustomize <dir> [flags] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

# kustomization.yamlファイルが見つからずエラーとなってしまった

デプロイ

公式ドキュメントの通りkubectl apply -k <kustomization directory>とありますので oveylays/dev/ ディレクトリへ移動して以下のコマンドでデプロイしてみます。

$ cd overlays/dev/
$ kubectl apply -k ./
service/dev-my-nginx created
deployment.apps/dev-my-nginx created

kubectl get podを実行すると、overlaysされたpodがデプロイされていることが確認できました。

$ kubectl get pod
dev-my-nginx-54cc7d6865-j2gl9          1/1     Running            0          82s
dev-my-nginx-54cc7d6865-ms9r4          1/1     Running            0          82s

既存設定を変更して差分確認する&その時に気をつけたいこと

一度デプロイが完了したpodをそのまま使い続けるというよりは、パラメータを変更しながら運用するケースの方が多いかと思います。 既にデプロイ済みのyamlファイルとの差分を確認する方法として 以下のようにパイプしてコマンドを組み合わせて、デプロイされた既存のmanifestと更新差分を出力確認することが出来ます。

kubectl diff -k .

では先ほどデプロイしたoverlays/dev/kustomization.yamlを変更してやってみましょう。

overlays/dev/kustomization.yamlを以下の様に変更します。pod名にsuffixを追加しました。

bases:
- ../../base
namePrefix: grasys-
nameSuffix: "-grasys01"

既存のpodとの差分を確認してみます

$ cd overlays/dev/
$ kubectl diff -k . 
diff -u -N /tmp/LIVE-979226958/apps.v1.Deployment.default.dev-my-nginx-grasys01 /tmp/MERGED-087402581/apps.v1.Deployment.default.dev-my-nginx-grasys01
--- /tmp/LIVE-979226958/apps.v1.Deployment.default.dev-my-nginx-grasys01        2021-08-16 07:34:48.450766595 +0000
+++ /tmp/MERGED-087402581/apps.v1.Deployment.default.dev-my-nginx-grasys01      2021-08-16 07:34:48.601766503 +0000
@@ -0,0 +1,81 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  creationTimestamp: "2021-08-16T07:34:48Z"
+  generation: 1
+  managedFields:
+  - apiVersion: apps/v1
+    fieldsType: FieldsV1
+    fieldsV1:
+      f:spec:
+        f:progressDeadlineSeconds: {}
+        f:replicas: {}
+        f:revisionHistoryLimit: {}
+        f:selector:
+          f:matchLabels:
+            .: {}
+            f:run: {}
+        f:strategy:
+          f:rollingUpdate:
+            .: {}
+            f:maxSurge: {}
+            f:maxUnavailable: {}
+          f:type: {}
+        f:template:
+          f:metadata:
+            f:labels:
+              .: {}
+              f:run: {}
+          f:spec:
+            f:containers:
+              k:{"name":"my-nginx"}:
+                .: {}
+                f:image: {}
+                f:imagePullPolicy: {}
+                f:name: {}
+                f:resources: {}
+                f:terminationMessagePath: {}
+                f:terminationMessagePolicy: {}
+            f:dnsPolicy: {}
+            f:restartPolicy: {}
+            f:schedulerName: {}
+            f:securityContext: {}
+            f:terminationGracePeriodSeconds: {}
+    manager: kubectl
+    operation: Update
+    time: "2021-08-16T07:34:48Z"
+  name: dev-my-nginx-grasys01
+  namespace: default
+  selfLink: /apis/apps/v1/namespaces/default/deployments/dev-my-nginx-grasys01
+  uid: 903e78c4-d381-43fb-96c7-b9816d677d6c
+spec:
+  progressDeadlineSeconds: 600
+  replicas: 2
+  revisionHistoryLimit: 10
+  selector:
+    matchLabels:
+      run: my-nginx
+  strategy:
+    rollingUpdate:
+      maxSurge: 25%
+      maxUnavailable: 25%
+    type: RollingUpdate
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        run: my-nginx
+    spec:
+      containers:
+      - image: nginx
+        imagePullPolicy: Always
+        name: my-nginx
+        resources: {}
+        terminationMessagePath: /dev/termination-log
+        terminationMessagePolicy: File
+      dnsPolicy: ClusterFirst
+      restartPolicy: Always
+      schedulerName: default-scheduler
+      securityContext: {}
+      terminationGracePeriodSeconds: 30
+status: {}
diff -u -N /tmp/LIVE-979226958/v1.Service.default.dev-my-nginx-grasys01 /tmp/MERGED-087402581/v1.Service.default.dev-my-nginx-grasys01
--- /tmp/LIVE-979226958/v1.Service.default.dev-my-nginx-grasys01        2021-08-16 07:34:47.927766912 +0000
+++ /tmp/MERGED-087402581/v1.Service.default.dev-my-nginx-grasys01      2021-08-16 07:34:48.081766820 +0000
@@ -0,0 +1,45 @@
+apiVersion: v1
+kind: Service
+metadata:
+  creationTimestamp: "2021-08-16T07:34:48Z"
+  labels:
+    run: my-nginx
+  managedFields:
+  - apiVersion: v1
+    fieldsType: FieldsV1
+    fieldsV1:
+      f:metadata:
+        f:labels:
+          .: {}
+          f:run: {}
+      f:spec:
+        f:ports:
+          .: {}
+          k:{"port":80,"protocol":"TCP"}:
+            .: {}
+            f:port: {}
+            f:protocol: {}
+            f:targetPort: {}
+        f:selector:
+          .: {}
+          f:run: {}
+        f:sessionAffinity: {}
+        f:type: {}
+    manager: kubectl
+    operation: Update
+    time: "2021-08-16T07:34:48Z"
+  name: dev-my-nginx-grasys01
+  namespace: default
+  selfLink: /api/v1/namespaces/default/services/dev-my-nginx-grasys01
+  uid: 28472b6c-6472-4eda-91ed-380a4dea7583
+spec:
+  ports:
+  - port: 80
+    protocol: TCP
+    targetPort: 80
+  selector:
+    run: my-nginx
+  sessionAffinity: None
+  type: ClusterIP
+status:
+  loadBalancer: {}
exit status 1

行頭の"+“から始まる部分が、これからデプロイされる際に新規追加となる差分情報です。 このままデプロイをしてみます。

$ kubectl apply -k .
service/dev-my-nginx-grasys01 created
deployment.apps/dev-my-nginx-grasys01 created

get podしてみると、既存環境はRunningのまま、suffix定義したdev-my-nginx-grasys01-の名前を含むpodが新たに2つ追加してデプロイされました。

$ kubectl get pod
NAME                                     READY   STATUS             RESTARTS   AGE
dev-my-nginx-54cc7d6865-j2gl9            1/1     Running            0          23m
dev-my-nginx-54cc7d6865-ms9r4            1/1     Running            0          23m
dev-my-nginx-grasys01-54cc7d6865-29k7g   1/1     Running            0          12s
dev-my-nginx-grasys01-54cc7d6865-2dk9v   1/1     Running            0          12s

既存環境2つだけを消す手順ですが まずは追加したkustomization.yamlファイルのnameSuffixをコメントアウトして保存、、、としがちですが、これでは削除されません。(理由は後ほど)

# kustomization.yamlで追加した部分をコメントアウトしても、既存のpodを消せない例:
$ cat kustomization.yaml
bases:
- ../../base
namePrefix: dev-
#nameSuffix: "-grasys01"

$ kubectl diff -k .
$ 

$ kubectl apply -k .
service/dev-my-nginx unchanged
deployment.apps/dev-my-nginx unchanged

$ kubectl get pod
NAME                                     READY   STATUS             RESTARTS   AGE
dev-my-nginx-54cc7d6865-j2gl9            1/1     Running            0          30m
dev-my-nginx-54cc7d6865-ms9r4            1/1     Running            0          30m
dev-my-nginx-grasys01-54cc7d6865-29k7g   1/1     Running            0          7m28s
dev-my-nginx-grasys01-54cc7d6865-2dk9v   1/1     Running            0          7m28s

kustomization.yamlで追加した内容をコメントアウトしてdiff確認して削除、の流れで、既存のpod環境が削除出来なかった理由はこちらです。 https://github.com/kubernetes-sigs/kustomize/blob/master/examples/transformerconfigs/README.md

Kustomize creates new resources by applying a series of transformations to an original set of resources. Kustomize provides the following default transformers:

  • annotations
  • images
  • labels
  • name reference
  • namespace
  • prefix/suffix
  • variable reference

プレフィックス/サフィックストランスフォーマーは、metadata/nameすべてのリソースのフィールドにプレフィックス/サフィックスを追加します。

上記の内容から、この様な流れで情報が読み込まれたこととなります。

  1. 最初のデプロイでdev-my-nginxというpod名のmanifestがデプロイされた
  2. kustomization.yamlにdev-my-nginx-grasys01というpod名のmanifestが新規でデプロイされた
  3. kustomization.yamlで追加した内容をコメントアウトしてdiff確認しても、それは 最初にデプロイしたdev-my-nginxというpod名のmanifestの設定でdiff対象に認識された(このため kubectl diff -k .しても何も差分は表示されなかった)

今回のケースでは既存環境はdeploymentを削除することで対応できます。

$ kubectl get deployment
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
dev-my-nginx            2/2     2            2           30m
dev-my-nginx-grasys01   2/2     2            2           7m41s

$ kubectl delete deployment dev-my-nginx
deployment.apps "dev-my-nginx" deleted

$ kubectl get pod
NAME                                     READY   STATUS             RESTARTS   AGE
dev-my-nginx-54cc7d6865-ms9r4            0/1     Terminating        0          36m
dev-my-nginx-grasys01-54cc7d6865-29k7g   1/1     Running            0          13m
dev-my-nginx-grasys01-54cc7d6865-2dk9v   1/1     Running            0          13m

バージョンアップしてkustomize機能をサブコマンドライクに使えて便利に扱える一方で、問題や予期せぬ動作などが起きるすると、対処が難しくなってきます。 どこまでがパラメータの更新でどこまでがkustomize機能となるのかは注意が必要したいところです。

それでは今回はこの辺で。