zaki work log

作業ログやら生活ログやらなんやら

[Kubernetes] KustomizeでConfigMapを扱う (configMapGenerator)

KustomizeにおけるConfigMapの管理おためし。 configMapGeneratorを使用する。

kubectl.docs.kubernetes.io

KustomizeおよびConfigMapそのものについては以下も参照。

zaki-hmkc.hatenablog.com

zaki-hmkc.hatenablog.com

Secretについては2022.12.08記事作成

zaki-hmkc.hatenablog.com

ConfigMapリソースの作成

key=value形式をkusomization.yamlにインライン記述

resources:
- sample-http.yaml
namespace: sample
configMapGenerator:
- name: sample-configure
  literals:
  - KUSTOMIZE_SAMPLE_HOST=172.29.0.1
  - KUSTOMIZE_SMPALE_PORT=6443

生成されるConfigMapは以下。

$ kubectl get cm -n sample
NAME                          DATA   AGE
kube-root-ca.crt              1      11s
sample-configure-8fctf9658k   2      11s
kubectl get cm -n sample sample-configure-7fgcbkm8mg -o yaml
apiVersion: v1
data:
  KUSTOMIZE_SAMPLE_HOST: 172.29.0.1
  KUSTOMIZE_SMPALE_PORT: "6443"
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"KUSTOMIZE_SAMPLE_HOST":"172.29.0.1","KUSTOMIZE_SMPALE_PORT":"6443"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"sample-configure-8fctf9658k","namespace":"sample"}}
  creationTimestamp: "2022-11-20T06:37:06Z"
  name: sample-configure-8fctf9658k
  namespace: sample
  resourceVersion: "527167"
  uid: b021e399-b1f0-46d9-91ad-a344bfbd5c80

key=value形式のファイル参照

kustomization.yamlファイルのある場所基準で、以下のファイルを用意しておく。

$ cat config/sample.ini 
HOST=10.0.0.2
PORT=25

この状態で

resources:
- sample-http.yaml
namespace: sample
configMapGenerator:
- name: sample-configure
  envs:
  - config/sample.ini

生成されるConfigMapは以下の通り。

$ kubectl get cm -n sample
NAME                          DATA   AGE
kube-root-ca.crt              1      13m
sample-configure-d26ddgbkb6   2      84s
$ kubectl get cm -n sample sample-configure-d26ddgbkb6 -o yaml
apiVersion: v1
data:
  HOST: 10.0.0.2
  PORT: "25"
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"HOST":"10.0.0.2","PORT":"25"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"sample-configure-d26ddgbkb6","namespace":"sample"}}
  creationTimestamp: "2022-11-20T05:16:05Z"
  name: sample-configure-d26ddgbkb6
  namespace: sample
  resourceVersion: "525398"
  uid: 5a289dcc-9af5-48b5-a71d-d4a5f168145e

ファイルそのものをConfigMap化

ミドルウェアの設定ファイルのように、ConfigMapリソースのマニフェストkustomization.yamlファイルへのインライン記述でなく、ファイル単独でバージョン管理したい場合などは、

$ cat config/sample.config 
this is sample file.

このようにconfig/sample.configファイルがある状態で、以下のkustomization.yamlを使ってデプロイする。

resources:
- sample-http.yaml
namespace: sample
configMapGenerator:
- name: sample-configure
  files:
  - config/sample.config

生成されるConfigMapは以下の通り。

$ kubectl get cm -n sample 
NAME                          DATA   AGE
sample-configure-cch6ttcgtb   1      4m52s
kube-root-ca.crt              1      4m52s
$ kubectl get cm -n sample sample-configure-cch6ttcgtb -o yaml
apiVersion: v1
data:
  sample.config: |
    this is sample file.
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"sample.config":"this is sample file.\n"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"sample-configure-cch6ttcgtb","namespace":"sample"}}
  creationTimestamp: "2022-11-20T05:03:55Z"
  name: sample-configure-cch6ttcgtb
  namespace: sample
  resourceVersion: "525139"
  uid: 5a4e9bd2-9452-41b1-8db1-552e9fd084ab

ConfigMapリソースの参照

Kustomizeで生成したConfigMapにはランダムなsuffixが付与されるが、nameで指定したConfigMap名を指定しておけば、Kustomizeがデプロイ時によしなにしてくれる。

環境変数として参照

Pod側の参照設定は、Deploymentリソースなどの定義で従来通りenvFromフィールド以下でconfigMapRefを使用して行う。
次のような感じで、kustomization.yamlのconfigMapGeneratorで指定するConfigMap名と同じリソース名を指定すればOK。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: sample-http
  name: sample-http
  namespace: kustomize-sample
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-http
  template:
    metadata:
      labels:
        app: sample-http
    spec:
      containers:
      - image: httpd
        name: httpd
        envFrom:
        - configMapRef:
            name: sample-configure   # <- これ
resources:
- sample-http.yaml
namespace: sample
configMapGenerator:
- name: sample-configure             # <- これ
  literals:
  - SAMPLE_HOST=172.29.0.1
  - SMPALE_PORT=6443

この内容でKustomizeを使ってデプロイすると以下の通り、生成されたConfigMapのsuffixも自動で付与される。

$ kubectl get pod -n sample 
NAME                           READY   STATUS    RESTARTS   AGE
sample-http-7cfb94f7d4-f7d65   1/1     Running   0          92s
sample-http-7cfb94f7d4-z4js5   1/1     Running   0          92s
$ kubectl get pod -n sample sample-http-7cfb94f7d4-f7d65 -o yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: "2022-11-20T06:37:06Z"
  generateName: sample-http-7cfb94f7d4-
  labels:
    app: sample-http
    pod-template-hash: 7cfb94f7d4
  name: sample-http-7cfb94f7d4-f7d65
  namespace: sample
  ownerReferences:
  - apiVersion: apps/v1
    blockOwnerDeletion: true
    controller: true
    kind: ReplicaSet
    name: sample-http-7cfb94f7d4
    uid: d3021a2a-823c-4620-bfa3-156f53e49634
  resourceVersion: "527195"
  uid: 62438100-d305-44f5-b50d-5b5293280f36
spec:
  containers:
  - envFrom:
    - configMapRef:
        name: sample-configure-8fctf9658k
    image: httpd
    imagePullPolicy: Always
    name: httpd
  :
  :
status:
 :
 :

Pod内の環境変数を確認すると以下の通り。

$ kubectl exec -it -n sample sample-http-7cfb94f7d4-f7d65 -- env | sort
:
KUSTOMIZE_SAMPLE_HOST=172.29.0.1
KUSTOMIZE_SMPALE_PORT=6443
:

ファイルシステムへマウント

コンテナ内にファイルシステムとしてマウントするには、これも通常のマニフェストと同様にvolumesフィールドでconfigMapを指定する。
Deploymentの定義としては以下のような感じ。

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: sample-http
  name: sample-http
  namespace: kustomize-sample
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sample-http
  template:
    metadata:
      labels:
        app: sample-http
    spec:
      containers:
      - image: httpd
        name: httpd
        volumeMounts:
        - name: config-volume
          mountPath: /opt
      volumes:
      - name: config-volume
        configMap:
          name: sample-configure   # <- これ
resources:
- sample-http.yaml
namespace: sample
configMapGenerator:
- name: sample-configure           # <- これ
  files:
  - config/sample.config

マウントしたファイルは以下の通り。

$ kubectl get pod -n sample 
NAME                          READY   STATUS    RESTARTS   AGE
sample-http-99587f5b9-dt8zk   1/1     Running   0          7m15s
sample-http-99587f5b9-k8pl8   1/1     Running   0          7m15s
$ kubectl exec -it -n sample sample-http-99587f5b9-dt8zk -- ls /opt
sample.config
$ kubectl exec -it -n sample sample-http-99587f5b9-dt8zk -- cat /opt/sample.config
this is sample file.

リソース名のランダムな文字

デフォルトの動作では生成されるConfigMapリソース名の末尾にsuffixが付与される。
一見ランダムだけど、内容が同じConfigMapであれば同じハッシュ値が付与される…ように見える。(仕様未確認)

この動作は、例えばミドルウェアの設定ファイル更新のような「ファイルが更新されただけではダメでアプリケーションのプロセスの再起動が必要」というケースで都合がよく、Kustomizeを使ってConfigMapの更新が行われConfigMapリソース名も変更されることによって、Podの再生成までが自動で行われる。

それに対してhtmlコンテンツや画像のようにファイルが更新されてもプロセス再起動は不要な場合は、ConfigMapの更新によってPodも再作成されるのは効率が悪い。

このsuffixを付与する動作を抑制するには、オプションのdisableNameSuffixHashを指定する。

resources:
- sample-http.yaml
namespace: sample
configMapGenerator:
- name: sample-configure
  files:
  - config/sample.config
  options:
    disableNameSuffixHash: true

これでsuffixが付与されずにkusomization.yamlで指定したConfigMap名がそのままリソース名となる。
suffixが付与されないため、ConfigMapの内容を変更して再度Kustomizeを実行しても、ConfigMapリソースを参照しているPodは再生成されなくなる。

$ kubectl get cm -n sample
NAME               DATA   AGE
sample-configure   1      7s
kube-root-ca.crt   1      7s

環境

k3s v1.24を使用

$ kubectl version --short
Client Version: v1.25.3
Kustomize Version: v4.5.7
Server Version: v1.24.3+k3s1