ConfigMapとは
ConfigMapとはKubernetes1.2で導入された、設定情報を扱うためのリソースです。
- Podに対して複数の設定情報を以下の形で渡すことができる
- 環境変数
- コンテナの引数
- ファイル(Volume)
- Volumeとして使った場合、動的に変更が反映される
- Volumeの場合ファイルはシンボリックリンクになっている (後述)
似たような機能のSecretは動的に反映はされなかったので、動的な変更の反映が個人的には嬉しいです。(Issueはあがっていて対応はされそうです。Secret volume should refresh when secrets are updated #18372)
参考:
- 公式ドキュメント Using ConfigMap
- Designドキュメント Generic Configuration Object
ConfigMapを作る
ConfigMapには複数の作り方があります。
-
kubectl create -f config.conf
方式- 設定ファイル(yaml/json)を直接書く方式
-
kubectl create configmap
コマンドを使う方法- ファイルやディレクトリ(
--from-file
オプション)を指定して、配置したい設定ファイルを指定する - 引数に直接設定情報を書く(
--from-literal
オプション)
- ファイルやディレクトリ(
ここでは設定ファイルを直接書く方式で試してみます。まず以下のような設定ファイルを書きます。
apiVersion: v1
kind: ConfigMap
metadata:
name: example-config
data:
# key, value形式で設定を記述する
example.property.1: hello
example.property.2: world
設定を反映させます。
$ kubectl create -f example-config.yaml
以下のようにConfigMapが作られました。
$ kubectl get configmap example-config -o yaml
apiVersion: v1
data:
example.property.1: hello
example.property.2: world
kind: ConfigMap
metadata:
creationTimestamp: 2016-03-19T12:33:55Z
name: example-config
namespace: default
resourceVersion: "1522"
selfLink: /api/v1/namespaces/default/configmaps/example-config
uid: d82ebdbc-edce-11e5-8c6d-08002701bf15
PodからConfigMapのデータを使う
作ったConfigMapをPodから読んでみます。環境変数に設定する方法と、ファイルとしてマウントする(Volume)方法の2つの方式があります。ここではVolumeを使ってファイルとしてマウントしてみます。
apiVersion: v1
kind: Pod
metadata:
name: pod-using-config
spec:
containers:
- name: example-container
image: busybox
# あとからexecで操作するためsleepさせておく
command: ["sleep", "3600"]
# 定義したConfigMapのvolumeをマウントする
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
# ConfigMapのvolume定義
- name: config-volume
configMap:
# 作ったConfigMapのname
name: example-config
上記設定のPodをデプロイします。
$ kubectl create -f pod-using-config.yaml
Podのマウントした/etc/config
以下にキー名のファイルが作られ値にアクセスすることが確認できます。
$ kubectl exec pod-using-config cat /etc/config/example.property.1
hello
$ kubectl exec pod-using-config cat /etc/config/example.property.2
world
ConfigMapの変更の反映を確認する
ConfigMapをVolumeとして使った場合、ConfigMapの変更が動的にPodにも反映されます。
先ほど作成したexample-config
をkubectl edit
を使って変更してみます。
$ kubectl edit configmap example-config
デフォルトではviが立ち上がるので、下記のようにconfigを書き換えます。
...
data:
# 値を書き換える
example.property.1: hello-updated
example.property.2: world-updated
値の変更を確認します。変更の反映に時間がかかる場合があります。(KubeletのSyncLoopのタイミングで反映されるようです。cf. kubelet#syncLoopIteration)
$ kubectl exec pod-using-config cat /etc/config/example.property.1
hello-updated
$ kubectl exec pod-using-config cat /etc/config/example.property.2
world-updated
Volumeの場合ファイルはシンボリックリンクになっている
VolumeとしてConfigMapを使った場合、設定ファイルはシンボリックリンクになっていました。複数の設定ファイルを一つ一つ新しい物に置き換えると全体でアトミックにならないため、ディレクトリのシンボリックリンクを切り替える方式が使われているようです。シンボリックリンクを見ないプログラムの場合は注意が必要だと思われます。
実際にPodにマウントされたファイルを見てみると以下の様になっています。
$ kubectl exec pod-using-config -- ls /etc/config -lra
total 8
lrwxrwxrwx 1 root root 25 Mar 19 05:23 example.property.2 -> ..data/example.property.2
lrwxrwxrwx 1 root root 25 Mar 19 05:23 example.property.1 -> ..data/example.property.1
lrwxrwxrwx 1 root root 31 Mar 19 05:33 ..data -> ..3983_19_03_05_33_10.012371420
drwx------ 2 root root 80 Mar 19 05:33 ..3983_19_03_05_33_10.012371420
drwxr-xr-x 1 root root 4096 Mar 19 05:23 ..
drwxrwxrwt 3 root root 120 Mar 19 05:33 .
実際のアトミックな切り替え処理はatomic_writer.goでやっており、以下が処理のイメージになります。
- タイムスタンプを元に
..3983_19_03_05_33_10.012371420
のような名前でディレクトリを作り、各設定ファイルを書く -
..data
というディレクトリ名で上のディレクトリにシンボリックリンクを貼る - マウント先のデータは
.data
の各設定ファイルに対してシンボリックリンクを貼る - 更新があった場合、タイムスタンプを元に新しいディレクトリに、各設定ファイルを書く
-
..data
のシンボリック先を新しいものに切り替えること - 設定ファイルすべてアトミックに切り替わる