30
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

kubectl -k と kubectl kustomize で出来ること

Last updated at Posted at 2020-07-10

Kubernetes 1.14 (GA: March 25,2019) から Kustomize が kubectl に統合され、kubectl apply -k <ディレクトリ> として利用できるようになっている。この便利な機能は積極的に活用したいので、有用そうな機能についてピックアップしてみた。この実行環境には IBM Cloud Kubernetesサービス v1.17.7 を利用した。

リソース

kustomization.yaml の resources フィールド に、リソースの構成ファイルへのパスを設定できる。

kustomization.yaml
resources:
  - deployment.yaml
  - service.yaml

kustomization.yaml が存在するディレクトリで、kubectl apply -k ./を実行することで、resources フィールドに列挙した構成ファイルを適用することができる。もちろん、同じディレクトリに deployment.yaml と service.yaml も存在する必要がある。

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

反対にAPIオブジェクトの作成もできる。

$ kubectl delete -k ./
service "my-nginx" deleted
deployment.apps "my-nginx" deleted

リソースフィールドに列挙された構成ファイルで、APIオブジェクトのリストも表示できる。

$ kubectl get -k ./
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
service/my-nginx   ClusterIP   172.21.202.192   <none>        80/TCP    11s

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/my-nginx   2/2     2            2           11s

一つのベースから複数のマニフェストを生成

baseに入っているリソースの構成ファイルを 開発環境 dev と 本番環境 prod のそれぞれの kustomization.yaml でオブジェクト名を変更してデプロイする。言い方を変えると、同一名前空間内で同じ構成ファイルから、異なるオブジェクト名でデプロイできることになる。

├── base
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
├── dev
│   └── kustomization.yaml
└── prod
    └── kustomization.yaml
base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml

開発環境用 kustomization.yaml では、オブジェクト名のプレフィックスを追加する namePrefix に dev- を設定するだけで良い。

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

こちらは本番用で、同様にプレフィックスに prod- を設定する。

prod/kustomization.yaml
bases:
- ../base
namePrefix: prod-

両者とも base の kustomization.yaml が呼び出され、二つの構成ファイルにオブジェクト名の書き換えの設定が実行される。

$ cd dev

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

$ kubectl get -k ./
NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/dev-my-nginx   ClusterIP   172.21.33.60   <none>        80/TCP    24s

NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/dev-my-nginx   2/2     2            2           23s

$ cd ../prod/

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

$ kubectl get -k .
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/prod-my-nginx   ClusterIP   172.21.134.12   <none>        80/TCP    6s

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/prod-my-nginx   2/2     2            2           5s

ラベルとアノテーションの一括変更

ベースの構成ファイルから、ラベルを一度に書き換え、アノテーションを追加する方法である。元になる構成ファイルを共有して再利用する場合、ラベルの設定が重なると、サービスとポッドの対応関係が乱れ、意図しない動きとなる。この方法は、その様なケースを回避するために役立つ。

この kustomization.yaml では、commonLabels と commonAnnotations によって、 resources/deployment.yaml のラベルとアノテーションを変更する。

kustomization.yaml
namespace: my-namespace
namePrefix: dev-
nameSuffix: "-001"
commonLabels:
  app: bingo
commonAnnotations:
  oncallPager: 800-555-1212
resources:
- deployment.yaml

以下が対象の構成ファイルで、全てのラベルを置き換える。

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx

以下では kubectl kustomize ./ によって、ラベルが app: nginx から app:bingo に変更になった。

$ ls -al
total 16
drwxr-xr-x@  4 maho  staff  128  7 10 20:13 .
drwxr-xr-x@ 13 maho  staff  416  7 10 21:07 ..
-rw-r--r--@  1 maho  staff  277  7 10 20:13 deployment.yaml
-rw-r--r--@  1 maho  staff  162  7 10 20:13 kustomization.yaml

$ kubectl kustomize ./
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    oncallPager: 800-555-1212
  labels:
    app: bingo
  name: dev-nginx-deployment-001
  namespace: my-namespace
spec:
  selector:
    matchLabels:
      app: bingo
  template:
    metadata:
      annotations:
        oncallPager: 800-555-1212
      labels:
        app: bingo
    spec:
      containers:
      - image: nginx
        name: nginx

シークレット の base64 自動変換

シークレットにパスワードやユーザー名を設定する場合、base64に変換しなくてはならない。 kustomize を利用することで、その手間を省くことができる。

次のYAMLは、literals:の配列に、ユーザー名とパスワードを平文でおいてある。これを secretGenerator: でシークレットを作成すると、base64への自動変換を実施してくれる。動きを確認するために pod.yaml でシークレットを環境変数にセットして確認する。

kustomization.yaml
secretGenerator:
- name: example-secret-1
  literals:
  - username=admin
  - password=secret
generatorOptions:
  disableNameSuffixHash: true
resources:
- pod.yaml

このファイルは、上記のresources に書かれた pod.yaml で、シークレットが作成された後に、このポッドがデプロイされる。

pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-pod2
spec:
  containers:
    - name: test-container
      image: maho/my-ubuntu:0.1
      command: ["tail",  "-f", "/dev/null"]
      env:
        - name: SECRET_USERNAME
          valueFrom:
            secretKeyRef:
              name: example-secret-1
              key: username
        - name: SECRET_PASSWORD
          valueFrom:
            secretKeyRef:
              name: example-secret-1
              key: password

次のkubectl apply -k . 実行結果では、作成されたシークレットはポッドから読み込まれ環境変数に設定される。その結果を表示したものだ。base64コマンドを利用しなくても、シークレットの値がコンテナに渡されていることが理解できると思う。

$ ls
kustomization.yaml      password.txt            pod.yaml

$ kubectl apply -k .
secret/example-secret-1 created
pod/my-pod2 created

$ kubectl exec -it my-pod2 -- bash
root@my-pod2:/# echo $SECRET_USERNAME
admin
root@my-pod2:/# echo $SECRET_PASSWORD
secret

パッチ Json6902

resources: に設定した構成ファイルに対して、- target:に設定した条件の場所に、path:のパッチを適用する。

kustomization.yaml
resources:
- deployment.yaml

patchesJson6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: my-nginx
  path: patch.yaml

このパッチで、spec.replicas を設定変更できる。

patch.yaml
- op: replace
  path: /spec/replicas
  value: 3

このコマンド kubectl kustomize <ディレクトリ> で、標準出力に構成ファイルが表示される。

$ kubectl kustomize ./

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

kubectl apply -k <ディレクトリ>で変更されたマニフェストが適用される。

$ kubectl get deployment.apps my-nginx -o yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    deployment.kubernetes.io/revision: "1"
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"my-nginx","namespace":"default"},"spec":{"replicas":3,"selector":{"matchLabels":{"run":"my-nginx"}},"template":{"metadata":{"labels":{"run":"my-nginx"}},"spec":{"containers":[{"image":"nginx","name":"my-nginx","ports":[{"containerPort":80}]}]}}}}
  creationTimestamp: "2020-07-10T22:50:58Z"
  generation: 1
  name: my-nginx
  namespace: default
  resourceVersion: "1978107"
  selfLink: /apis/apps/v1/namespaces/default/deployments/my-nginx
  uid: 3c6ae986-7254-4493-9ddd-ca80d1cc2709
spec:
  progressDeadlineSeconds: 600
  replicas: 3
  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
        ports:
        - containerPort: 80
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
status:
  availableReplicas: 3
  conditions:
  - lastTransitionTime: "2020-07-10T22:51:07Z"
    lastUpdateTime: "2020-07-10T22:51:07Z"
    message: Deployment has minimum availability.
    reason: MinimumReplicasAvailable
    status: "True"
    type: Available
  - lastTransitionTime: "2020-07-10T22:50:59Z"
    lastUpdateTime: "2020-07-10T22:51:07Z"
    message: ReplicaSet "my-nginx-75897978cd" has successfully progressed.
    reason: NewReplicaSetAvailable
    status: "True"
    type: Progressing
  observedGeneration: 1
  readyReplicas: 3
  replicas: 3

まとめ

kubectl -kを利用して YAMLの構成ファイルの管理が少しでも簡単になればと思う。

参考資料

[1] Kubernetes 1.14: Production-level support for Windows Nodes, Kubectl Updates, Persistent Local Volumes GA, https://kubernetes.io/blog/2019/03/25/kubernetes-1-14-release-announcement/
[2] Declarative Management of Kubernetes Objects Using Kustomize, https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
[3] Kustomization.yaml Reference, https://kubectl.docs.kubernetes.io/pages/reference/kustomize.html
[4] kubectl に統合された Kustomize をさわってみた, https://qiita.com/os1ma/items/076a57b25e74e54476ba
[5] https://github.com/takara9/kustomize

30
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
24

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?