Ritolabo
  1. Home
  2. Kubernetes
  3. ConfigMap: Kubernetes で Pod に渡す設定値

ConfigMap: Kubernetes で Pod に渡す設定値

  • 公開日
  • カテゴリ:Kubernetes
  • タグ:Kubernetes,学習メモ
ConfigMap: Kubernetes で Pod に渡す設定値

アプリには、動かす環境によって変えたい値がある。接続先のホスト名やログの出力レベルなど。こうした値をコンテナイメージの中に書き込むと、値を変えるたびにイメージを作り直すことになる。

ConfigMap は、設定の値をキーと値の組で保存するリソース。設定をコンテナイメージから切り離しておける。Pod は、ConfigMap の値を環境変数やファイルとして受け取れる。

この記事では、ConfigMap をローカルのクラスタに作り、Pod に環境変数とファイルの2通りで渡して、ConfigMap を書き換えたときの動きを確認する。

この記事でやること:

  • ConfigMap の YAML の確認
  • ConfigMap の作成と中身の確認
  • 環境変数としての受け取り
  • ファイルとしての受け取り
  • ConfigMap を書き換えたときの動き
  • Pod を作り直したときの動き
  • ConfigMap がない状態での Pod の起動

contents

  1. 環境
  2. ConfigMap の YAML
  3. ConfigMap を作る
    1. ConfigMap はどこにあるか
  4. Pod から ConfigMap を参照する
  5. 環境変数として受け取る
  6. ファイルとして受け取る
    1. volumes と volumeMounts
    2. ConfigMap と Pod の関係
  7. ConfigMap を書き換える
  8. Pod を作り直す
  9. ConfigMap と Deployment を消す
  10. ConfigMap がない状態で Pod を起動する
  11. 機密情報は ConfigMap に入れない
  12. 用語メモ
  13. 参考 URL

環境

kind で作ったクラスタ(Control Plane 1台 + Worker 2台)を使う。(作り方は「Kubernetes の Pod とは?コンテナを動かす最小単位を整理する」を参照)

  • 環境: macOS(Apple Silicon)、Docker Desktop 29.8.0、kind v0.33.0、Kubernetes v1.37.0、kubectl v1.36.1

ConfigMap の YAML

# app-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  color: blue
  message.txt: |
    Hello from ConfigMap
    This is line 2
場所意味
metadata.nameConfigMap の名前。Pod からは、この名前で参照する
data設定の本体。キーと値の組を並べる
  • Pod や Deployment の YAML にある spec は、ConfigMap にはない。代わりに data を持つ
  • color は1行の値、message.txt は複数行の値(| は、続く字下げした行をまとめて1つの値にする YAML の書き方)
  • ConfigMap は、1行の値と複数行の値を区別しない。違いが出るのは、Pod がその値をどう受け取るか

ConfigMap を作る

$ kubectl apply -f app-config.yaml

# => configmap/app-config created

$ kubectl get configmaps

NAME               DATA   AGE
app-config         2      15s
kube-root-ca.crt   1      4d10h
  • app-config が作った ConfigMap。kube-root-ca.crt は最初からあるもの
  • DATA の 2 は、キーの数

中身は kubectl describe で確認できる。

$ kubectl describe configmap app-config

Name:         app-config
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
color:
----
blue

message.txt:
----
Hello from ConfigMap
This is line 2



BinaryData
====

Events:  <none>

Data に、YAML に書いたキーと値がそのまま入っている。

ConfigMap はどこにあるか

ConfigMap は、動いているプログラムではなく、YAML に書いた内容が記録されたデータ(オブジェクト)。Service や Deployment と同じく、Control Plane で動いている etcd に保存される。(「Service: Kubernetes で Pod への宛先を固定する」の「Service や Deployment はどこにあるか」を参照)

図を描画しています…
  • ConfigMap、Service、Deployment、ReplicaSet は、Control Plane の etcd に保存されたデータ。Control Plane で動いているプログラムではない
  • 図のリソースのうち、Node の上にあるのは Pod だけ
  • 矢印は、そのデータが何についての定義かを示す。データ自身が何かを作ったり渡したりするわけではない
  • 保存されたデータを読んで実際に動くのは、別のプログラム。Deployment や ReplicaSet のデータを読んで Pod を作るのは Control Plane の kube-controller-manager、ConfigMap のデータを読んでコンテナに渡すのは Node の kubelet
  • Deployment demo-app と Pod は、このあと作るもの
  • ConfigMap を作っただけでは、Pod は増えない。どの Node の上でも何も動かない
  • ConfigMap の値が使われるのは、ConfigMap を参照する Pod のコンテナが起動するとき。その Pod が置かれた Node の kubelet が、ConfigMap のデータを使ってコンテナを起動する

Pod から ConfigMap を参照する

どの ConfigMap を使うかは、Deployment の YAML に書く。

Pod を1つ動かす Deployment を用意する。(Deployment については「Deployment: Kubernetes で Pod の数と更新を管理する」を参照)

# demo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: demo-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: demo-app
  template:
    metadata:
      labels:
        app: demo-app
    spec:
      containers:
        - name: nginx
          image: nginx:1.16.1
          env:
            - name: APP_COLOR
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: color
          volumeMounts:
            - name: config-volume
              mountPath: /config
              readOnly: true
      volumes:
        - name: config-volume
          configMap:
            name: app-config

ConfigMap を参照しているのは、env と、volumeMounts・volumes の2か所。コンテナの image は nginx だが、nginx の機能は使わない。動き続けるコンテナとして使っている。

$ kubectl apply -f demo-deployment.yaml

# => deployment.apps/demo-app created

$ kubectl get pods -o wide

NAME                        READY   STATUS    RESTARTS   AGE   IP           NODE               NOMINATED NODE   READINESS GATES
demo-app-6bbfb9c47b-cptw4   1/1     Running   0          5s    10.244.1.2   k8s-study-worker   <none>           <none>

環境変数として受け取る

          env:
            - name: APP_COLOR
              valueFrom:
                configMapKeyRef:
                  name: app-config
                  key: color
場所意味
env.nameコンテナに設定する環境変数の名前
configMapKeyRef.name参照する ConfigMap の名前
configMapKeyRef.keyその ConfigMap の中のキー。このキーの値が、環境変数の値になる

Pod のコンテナの中で、環境変数を表示する。

$ kubectl exec deploy/demo-app -- printenv APP_COLOR

# => blue
部分意味
kubectl execPod のコンテナの中でコマンドを実行する
deploy/demo-appDeployment demo-app の Pod を対象にする。Pod の名前を指定しなくて済む
-- printenv APP_COLORコンテナの中で実行するコマンド。環境変数 APP_COLOR の値を表示する
  • ConfigMap の color の値(blue)が、コンテナの環境変数 APP_COLOR に入っている
  • 環境変数の名前は、ConfigMap のキーと別の名前にできる

ファイルとして受け取る

          volumeMounts:
            - name: config-volume
              mountPath: /config
              readOnly: true
      volumes:
        - name: config-volume
          configMap:
            name: app-config

Pod のコンテナの中で、/config を見る。

$ kubectl exec deploy/demo-app -- ls /config

color
message.txt

$ kubectl exec deploy/demo-app -- cat /config/message.txt

Hello from ConfigMap
This is line 2

$ kubectl exec deploy/demo-app -- cat /config/color

# => blue
  • ConfigMap のキーがファイル名、値がファイルの中身になっている
  • キーが2つあるので、ファイルも2つ

volumes と volumeMounts

ファイルとして受け取る指定は、volumes と volumeMounts の2か所に分かれている。

volume は、Pod の中のコンテナからアクセスできるディレクトリ。ConfigMap を元にした volume の場合、Pod が置かれた Node の kubelet が ConfigMap のデータを取得し、その Node の上でファイルにする。kubelet は、その volume をコンテナの中にマウントする。

volumesvolumeMounts
内容Pod に用意する volume の指定volume を、コンテナの中のどこにマウントするかの指定
YAML の場所Pod の spec の直下各コンテナの中
今回の指定ConfigMap app-config を元にした volume を、config-volume という名前で用意するconfig-volume を、コンテナの中の /config にマウントする
  • 2か所は、volume の名前(config-volume)で対応している
  • volume は Pod に用意されるもので、コンテナの外にある。Pod の中のコンテナは、マウントすることで volume にアクセスできる
  • volume の実体は、Pod が置かれた Node の上のディレクトリ
  • Pod にコンテナが複数ある場合、volumeMounts はコンテナごとに書く。volumes は ConfigMap ごとに1つでよい

ConfigMap と Pod の関係

図を描画しています…
  • ConfigMap は、どの Node にも属していない。Node の上にあるのは、Pod とその volume
  • 環境変数は、ConfigMap のキー color の値だけを受け取っている
  • volume は、ConfigMap のすべてのキーをファイルとして持つ

ConfigMap を書き換える

app-config.yaml の color を blue から green に書き換えて、apply する。

data:
  color: green
$ kubectl apply -f app-config.yaml

# => configmap/app-config configured

Pod には何もせずに、環境変数とファイルをもう一度見る。

$ kubectl exec deploy/demo-app -- printenv APP_COLOR

# => blue

$ kubectl exec deploy/demo-app -- cat /config/color

# => green
受け取り方ConfigMap を書き換えた後
環境変数blue のまま
ファイルgreen に変わった
  • ファイルは、Pod を作り直さなくても更新される。ただし apply の直後には変わらず、今回は数秒程度かかった
  • 更新までの時間は、最大で「kubelet の同期の間隔 + キャッシュの伝播にかかる時間」
  • 環境変数として受け取った値は、自動では更新されない
  • ファイルが更新されても、起動時に一度だけ設定を読み込むアプリは、変更に気づかない

Pod を作り直す

環境変数に新しい値を渡すには、Pod を置き換える。Deployment の Pod は、kubectl rollout restart で新しい Pod に入れ替えられる。

$ kubectl rollout restart deployment demo-app

# => deployment.apps/demo-app restarted

$ kubectl rollout status deployment demo-app

# => deployment "demo-app" successfully rolled out

$ kubectl get pods

NAME                        READY   STATUS    RESTARTS   AGE
demo-app-67cf57bf8f-sfcfd   1/1     Running   0          14s

$ kubectl exec deploy/demo-app -- printenv APP_COLOR

# => green
コマンド意味
kubectl rollout restart deployment demo-appDeployment demo-app の Pod を、新しい Pod に入れ替える
kubectl rollout status deployment demo-app入れ替えが終わるまで待つ

上の kubectl get pods と printenv の結果からわかること:

入れ替える前(Deployment を作ったとき)入れ替えた後
Pod の名前demo-app-6bbfb9c47b-cptw4demo-app-67cf57bf8f-sfcfd
環境変数 APP_COLORbluegreen
  • kubectl get pods に出ている Pod は、Deployment を作ったときの Pod とは名前が違う。別の Pod に入れ替わっている
  • 入れ替わった後の Pod では、printenv APP_COLOR の結果が green になっている
環境変数 APP_COLORファイル /config/color
最初blueblue
ConfigMap を書き換えた後bluegreen
Pod を作り直した後greengreen

ConfigMap と Deployment を消す

Deployment と ConfigMap は別々のリソースなので、それぞれ消す。

$ kubectl delete -f demo-deployment.yaml

# => deployment.apps "demo-app" deleted from default namespace

$ kubectl delete -f app-config.yaml

# => configmap "app-config" deleted from default namespace

$ kubectl get configmaps

NAME               DATA   AGE
kube-root-ca.crt   1      4d10h

ConfigMap がない状態で Pod を起動する

ConfigMap を作らずに、Deployment だけを apply する。

$ kubectl apply -f demo-deployment.yaml

# => deployment.apps/demo-app created

$ kubectl get pods

NAME                        READY   STATUS              RESTARTS   AGE
demo-app-6bbfb9c47b-lhjpg   0/1     ContainerCreating   0          5s

STATUS は ContainerCreating のままで、Running にならない。kubectl describe pod の Events: は次のとおり。

$ kubectl describe pod -l app=demo-app

(省略)
Events:
  Type     Reason       Age               From               Message
  ----     ------       ----              ----               -------
  Normal   Scheduled    21s               default-scheduler  Successfully assigned default/demo-app-6bbfb9c47b-lhjpg to k8s-study-worker
  Warning  FailedMount  5s (x6 over 21s)  kubelet            MountVolume.SetUp failed for volume "config-volume" : configmap "app-config" not found
  • Pod は Node(k8s-study-worker)に割り当てられている
  • その Node の kubelet が volume config-volume を用意しようとして、ConfigMap app-config が見つからずに失敗している(FailedMount)
  • 参照先の ConfigMap が存在しない場合、その参照を optional にしていなければ、Pod は起動しない

機密情報は ConfigMap に入れない

ConfigMap は、機密性や暗号化を提供しない。パスワードのような機密情報には、ConfigMap ではなく Secret を使う。

用語メモ

用語読み方意味
ConfigMapコンフィグマップ機密性のない設定の値を、キーと値の組で保存するリソース
configMapKeyRefコンフィグマップ キー レフ環境変数の値として、ConfigMap の特定のキーを参照する指定
volumeボリュームPod の中のコンテナからアクセスできるディレクトリ
volumeMountsボリュームマウンツvolume を、コンテナの中のどこにマウントするかの指定
kubeletキューブレット各 Node で動き、Pod のコンテナを起動するコンポーネント

まとめ

  • ConfigMap は、設定の値をキーと値の組で保存するリソース。設定をコンテナイメージから切り離しておける
  • ConfigMap は動いているプログラムではなく、保存されたデータ。値が使われるのは、参照する Pod のコンテナが起動するとき
  • どの ConfigMap を使うかは、Deployment の YAML に書く
  • 環境変数として受け取るには、env の configMapKeyRef で ConfigMap の名前とキーを指定する
  • ファイルとして受け取るには、volumes で ConfigMap を元にした volume を用意し、volumeMounts でコンテナの中にマウントする。キーがファイル名、値がファイルの中身になる
  • ConfigMap を書き換えると、ファイルは Pod を作り直さなくても更新される。環境変数は、Pod を作り直すまで変わらない
  • 参照先の ConfigMap が存在しないと、Pod は起動しない
  • 機密情報には、ConfigMap ではなく Secret を使う

参考 URL


[Prev] Service: Kubernetes で Pod への宛先を固定する

Author

rito

rito

  • Backend Engineer
  • Tokyo, Japan
  • PHP 5 技術者認定上級試験 認定者
  • 統計検定 3 級