kubernetesでSecretやConfigMapのVolumeマウントがなかなか意図した通りにいかなかったときの対処を備忘録として残しておきます。
kubernetesでのVolume管理
そもそもkubernetesでのVolumeはどうなっているのか確認してみます。
試しに下記のようにConfigMap
とそれをマウントして可視化するようなJob
を実行して
Volumeマウントしたディレクトリ配下を見てみます。
job.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: extra-config
namespace: default
data:
some_config: thisisconfigvalue
---
apiVersion: batch/v1
kind: Job
metadata:
name: mounttest-job
namespace: default
spec:
template:
spec:
containers:
- name: ls-recursive
image: busybox
command: ["ls", "-laR", "/volumes/"]
volumeMounts:
- name: config-volume
mountPath: /volumes
volumes:
- name: config-volume
configMap:
name: extra-config
restartPolicy: Never
で実行してみます
ᐅ kubectl apply -f job.yaml && \
sleep 5 && \
kubectl logs jobs/mounttest-job && \
kubectl delete jobs/mounttest-job
configmap/extra-config created
job.batch/mounttest-job created
/volumes/:
total 12
drwxrwxrwx 3 root root 4096 Jul 4 09:08 .
drwxr-xr-x 1 root root 4096 Jul 4 09:08 ..
drwxr-xr-x 2 root root 4096 Jul 4 09:08 ..2021_07_03_09_08_23.921812632
lrwxrwxrwx 1 root root 31 Jul 4 09:08 ..data -> ..2021_07_03_09_08_23.921812632
lrwxrwxrwx 1 root root 18 Jul 4 09:08 some_config -> ..data/some_config
/volumes/..2021_07_03_09_08_23.921812632:
total 12
drwxr-xr-x 2 root root 4096 Jul 4 09:08 .
drwxrwxrwx 3 root root 4096 Jul 4 09:08 ..
-rw-r--r-- 1 root root 17 Jul 4 09:08 some_config
job.batch "mounttest-job" deleted
kubernetesでのVolumeは、上記の通りSym link構造の構成となっています。
- 目的のConfigファイル
/volumes/some_config
はVolume dir直下..data
dir配下のsome_configへのlink ..data
dirはtimestamp dirへのlink- 実態は
/volumes/<timestamp>/some_config
にある
..data
ディレクトリの参照先をtimestampディレクトリに貼ることでAtomicな構成を実現しているようです。
で、この特異な構成によって困ったことがあったのでそのケースと対応についてまとめます。
Case and Solutions
CASE1: あるDir配下のConfigを再帰的に捜査する処理の場合
例えば、特定ディレクトリを指定して、そのディレクトリ配下のファイルを再帰的に捜査して読み込む
ようなプログラム(例えばmigrateツールなど)を実行する場合、困ることがあります。
上記の例だと、/volumes
dir配下のsome_config
を読み込みたい場合、
/volumes/some_config
/volumes/<timestamp>/some_config
… と、同一ファイルが2回読み込まれてしまいます。。
この場合、考えられる対処として下記で対応しました。
- dir指定に
..data
(上記例だと/volumes/..data/
)を指定する - kubernetesでのVolumeを使わずあらかじめ利用するImageに入れておく
- 影響のない適当なdir配下にマウントし、コマンドで該当dir配下にlinkを貼る(またはmv,cpなど)
3の方法は、具体的には下記の感じです。
job2.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: mounttest-job2
namespace: default
spec:
template:
spec:
containers:
- name: ls-recursive
image: busybox
command: ["/bin/sh", "-c"]
args:
- |
ln -s /configmaps/some_config /volumes/some_config
ls -laR /volumes/
volumeMounts:
- name: config-volume
mountPath: /configmaps
volumes:
- name: config-volume
configMap:
name: extra-config
restartPolicy: Never
本来指定したいdirにはマウントせず、適当な影響ないdirに一旦マウントしてコマンドの最初にlink処理を行います。
実行してみると下記の感じになります。
ᐅ kubectl apply -f job2.yaml && \
sleep 10 && \
kubectl logs jobs/mounttest-job2 && \
kubectl delete jobs/mounttest-job2
job.batch/mounttest-job2 created
/volumes/:
total 12
drwxr-xr-x 1 root root 4096 Jul 4 18:51 .
drwxr-xr-x 1 root root 4096 Jul 4 18:51 ..
lrwxrwxrwx 1 root root 23 Jul 4 18:51 some_config -> /configmaps/some_config
job.batch "mounttest-job2" deleted
上記の通り重複読み込みはないですね
CASE2: 既存のImageの設定にConfigMapで設定追加する場合
既存のコンテナイメージの特定dir配下の設定ファイルに、kubernetesのVolumeマウントで設定追加したい場合にも困ることがあります。
試しに下記のようなconfigを同梱したイメージを作成し、マウントしてみます。
Dockerfile
FROM busybox
COPY conf/example.conf /volumes/example.conf
上記イメージを使って/volumes
dirに追加でマウントしてみます。
docker build -t mount-busybox:local .
job3.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: mounttest-job3
namespace: default
spec:
template:
spec:
containers:
- name: ls-recursive
image: mount-busybox:local
# for pull from local
imagePullPolicy: Never
command: ["ls", "-laR", "/volumes/"]
volumeMounts:
- name: config-volume
mountPath: /volumes
volumes:
- name: config-volume
configMap:
name: extra-config
restartPolicy: Never
で、上記を実行してみると、、
ᐅ kubectl apply -f job3.yaml && \
sleep 10 && \
kubectl logs jobs/mounttest-job3 && \
kubectl delete jobs/mounttest-job3
job.batch/mounttest-job3 created
/volumes/:
total 12
drwxrwxrwx 3 root root 4096 Jul 4 19:18 .
drwxr-xr-x 1 root root 4096 Jul 4 19:18 ..
drwxr-xr-x 2 root root 4096 Jul 4 19:18 ..2021_07_04_19_18_49.338411331
lrwxrwxrwx 1 root root 31 Jul 4 19:18 ..data -> ..2021_07_04_19_18_49.338411331
lrwxrwxrwx 1 root root 18 Jul 4 19:18 some_config -> ..data/some_config
/volumes/..2021_07_04_19_18_49.338411331:
total 12
drwxr-xr-x 2 root root 4096 Jul 4 19:18 .
drwxrwxrwx 3 root root 4096 Jul 4 19:18 ..
-rw-r--r-- 1 root root 17 Jul 4 19:18 some_config
job.batch "mounttest-job3" deleted
上記の通りもともとコンテナイメージに同梱していた/volumes
dir配下のexample.conf
が消えています。
kube公式docsにも確かにそう記載されています。
Caution: If there are some files in the /etc/config/ directory, they will be deleted.
これはCASE1
での3の方法で対応しました。
CASE3: あるDir配下に複数のVolumeをマウントする場合
これは調べればすぐ出てきますが一応。。
下記のように同一ディレクトリ配下に複数マウントする場合、エラーとなります。
...
spec:
template:
spec:
containers:
- name: ls-recursive
image: busybox
command: ["ls", "-laR", "/volumes/"]
volumeMounts:
- name: config-volume
mountPath: /volumes
- name: config-volume2
mountPath: /volumes
volumes:
- name: config-volume
configMap:
name: extra-config
- name: config-volume2
configMap:
name: extra-config2
ᐅ kubectl apply -f job4.yaml && \
sleep 10 && \
kubectl logs jobs/mounttest-job4 && \
kubectl delete jobs/mounttest-job4
The Job "mounttest-job4" is invalid: spec.template.spec.containers[0].volumeMounts[1].mountPath: Invalid value: "/volumes": must be unique
projected
でVolumeを束ねてからマウントさせます。
参考:https://kubernetes.io/docs/concepts/storage/volumes/#projected
...
spec:
template:
spec:
containers:
- name: ls-recursive
image: busybox
command: ["/bin/sh", "-c"]
args:
- |
#ln -s /configmaps/some_config /volumes/some_config;
ls -laR /volumes/
volumeMounts:
- name: config-bundle-volume
mountPath: /volumes
volumes:
- name: config-bundle-volume
projected:
sources:
- configMap:
name: extra-config
- configMap:
name: extra-config2
確認してみるとちゃんと意図したとおりにマウントされています。
ᐅ kubectl apply -f job4.yaml && \
sleep 10 && \
kubectl logs jobs/mounttest-job4 && \
kubectl delete jobs/mounttest-job4
job.batch/mounttest-job4 created
/volumes/:
total 4
drwxrwxrwt 3 root root 120 Jul 4 19:47 .
drwxr-xr-x 1 root root 4096 Jul 4 19:47 ..
drwxr-xr-x 2 root root 80 Jul 4 19:47 ..2021_07_04_19_47_19.259541501
lrwxrwxrwx 1 root root 31 Jul 4 19:47 ..data -> ..2021_07_04_19_47_19.259541501
lrwxrwxrwx 1 root root 18 Jul 4 19:47 some_config -> ..data/some_config
lrwxrwxrwx 1 root root 19 Jul 4 19:47 some_config2 -> ..data/some_config2
/volumes/..2021_07_04_19_47_19.259541501:
total 8
drwxr-xr-x 2 root root 80 Jul 4 19:47 .
drwxrwxrwt 3 root root 120 Jul 4 19:47 ..
-rw-r--r-- 1 root root 17 Jul 4 19:47 some_config
-rw-r--r-- 1 root root 18 Jul 4 19:47 some_config2
job.batch "mounttest-job4" deleted
まとめ
基本的にkubernetesのVolumeマウントは、基本的にピンポイントにファイル指定して利用する分には問題になりにくいでしょうが、仕様を把握してないとあれ?っとなりますです。。
ちゃんと仕様を把握して気をつけましょう。
ここでの例ではConfigMap
でのものでしたが、これはSecret
でも同様です。
参考
- https://kubernetes.io/docs/concepts/storage/volumes/
- https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/