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

アプリには、動かす環境によって変えたい値がある。接続先のホスト名やログの出力レベルなど。こうした値をコンテナイメージの中に書き込むと、値を変えるたびにイメージを作り直すことになる。
ConfigMap は、設定の値をキーと値の組で保存するリソース。設定をコンテナイメージから切り離しておける。Pod は、ConfigMap の値を環境変数やファイルとして受け取れる。
この記事では、ConfigMap をローカルのクラスタに作り、Pod に環境変数とファイルの2通りで渡して、ConfigMap を書き換えたときの動きを確認する。
この記事でやること:
- ConfigMap の YAML の確認
- ConfigMap の作成と中身の確認
- 環境変数としての受け取り
- ファイルとしての受け取り
- ConfigMap を書き換えたときの動き
- Pod を作り直したときの動き
- ConfigMap がない状態での Pod の起動
contents
- 環境
- ConfigMap の YAML
- ConfigMap を作る
- Pod から ConfigMap を参照する
- 環境変数として受け取る
- ファイルとして受け取る
- ConfigMap を書き換える
- Pod を作り直す
- ConfigMap と Deployment を消す
- ConfigMap がない状態で Pod を起動する
- 機密情報は ConfigMap に入れない
- 用語メモ
- 参考 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.name | ConfigMap の名前。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 exec | Pod のコンテナの中でコマンドを実行する |
deploy/demo-app | Deployment 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 をコンテナの中にマウントする。
volumes | volumeMounts | |
|---|---|---|
| 内容 | 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-app | Deployment demo-app の Pod を、新しい Pod に入れ替える |
kubectl rollout status deployment demo-app | 入れ替えが終わるまで待つ |
上の kubectl get pods と printenv の結果からわかること:
| 入れ替える前(Deployment を作ったとき) | 入れ替えた後 | |
|---|---|---|
| Pod の名前 | demo-app-6bbfb9c47b-cptw4 | demo-app-67cf57bf8f-sfcfd |
環境変数 APP_COLOR | blue | green |
kubectl get podsに出ている Pod は、Deployment を作ったときの Pod とは名前が違う。別の Pod に入れ替わっている- 入れ替わった後の Pod では、
printenv APP_COLORの結果がgreenになっている
環境変数 APP_COLOR | ファイル /config/color | |
|---|---|---|
| 最初 | blue | blue |
| ConfigMap を書き換えた後 | blue | green |
| Pod を作り直した後 | green | green |
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を用意しようとして、ConfigMapapp-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
- [official] ConfigMap | Kubernetes
- [official] Podを構成してConfigMapを使用する | Kubernetes
- [official] Updating Configuration via a ConfigMap | Kubernetes
- [official] ボリューム | Kubernetes
- [official] Secret | Kubernetes

