参考資料
Configure a Pod to Use a Volume for Storage (kubernetes.io)
Declarative Management of Kubernetes Objects Using Kustomize (kubernetes.io)
Volumes emptyDir (kubernetes.io)
何を学べるか
- コンテナでデータを保存するには
Volumeを使う -
Volume種別毎に、データの生存期間が異なる
事前知識
- コンテナが終了(再起動)した時、コンテナが持っているファイルシステム内の変更は全て失われる
→コンテナ生成元のイメージと同等の状態に戻る - 上記の通りなので、コンテナをステートフルで使いたい(状態、データを保存したい)ならば、永続ストレージをコンテナへマウントしておく必要がある
前提条件
- k8s v1.14以降 (Kustomizeが必要)
- k8sクラスタ起動済み
環境情報
- CNI実装: calico
- CRI実装: Docker
- ホストOS: Ubuntu 18.04
手順
1/5 : Podを作って状態を監視する
後続のコマンドを実行するにはC-zで監視をバックグラウンドジョブにするか、別シェルを立ち上げましょう(C-Shift-t等)
kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml && \
kubectl get pod redis --watch
pod/redis created
NAME READY STATUS RESTARTS AGE
redis 0/1 ContainerCreating 0 0s
redis 1/1 Running 0 17s
2/5 : 作ったPodでシェルを起動する
kubectl exec -it redis -- /bin/bash
root@redis:/data#
3/5 : 起動したシェルでファイルを作る
cd /data/redis/
echo Hello > test-file && ls
test-file
4/5 : シェルでUbuntuのリポジトリ情報を更新し、procpsパッケージをインストールし、ps auxで動いているプロセスの情報を見る
...失敗。。corednsがきちんと動いてませんでした。
apt-get update
Err:1 http://security.debian.org/debian-security buster/updates InRelease
Temporary failure resolving 'security.debian.org'
Err:2 http://deb.debian.org/debian buster InRelease
Temporary failure resolving 'deb.debian.org'
Err:3 http://deb.debian.org/debian buster-updates InRelease
Temporary failure resolving 'deb.debian.org'
Reading package lists... Done
W: Failed to fetch http://deb.debian.org/debian/dists/buster/InRelease Temporary failure resolving 'deb.debian.org'
W: Failed to fetch http://security.debian.org/debian-security/dists/buster/updates/InRelease Temporary failure resolving 'security.debian.org'
W: Failed to fetch http://deb.debian.org/debian/dists/buster-updates/InRelease Temporary failure resolving 'deb.debian.org'
W: Some index files failed to download. They have been ignored, or old ones used instead.
こっちの記事にて解決したので、以下は解決後です。
apt-get update
Get:1 http://security-cdn.debian.org/debian-security buster/updates InRelease [39.1 kB]
Get:2 http://cdn-fastly.deb.debian.org/debian buster InRelease [118 kB]
Get:3 http://cdn-fastly.deb.debian.org/debian buster-updates InRelease [46.8 kB]
Get:4 http://security-cdn.debian.org/debian-security buster/updates/main amd64 Packages [53.4 kB]
Get:5 http://cdn-fastly.deb.debian.org/debian buster/main amd64 Packages [7897 kB]
Fetched 8154 kB in 6s (1375 kB/s)
Reading package lists... Done
apt-get install procps
...
ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
redis 1 0.3 0.2 40704 4124 ? Ssl 06:26 0:06 redis-server *:6379
root 338 0.6 0.1 3868 2928 pts/0 Ss 07:02 0:00 /bin/bash
root 344 0.0 0.1 7640 2656 pts/0 R+ 07:02 0:00 ps aux
5/5 : redisプロセスを落とし、Podでシェルを起動し、作ったファイル/data/redis/test-fileが存在する事を確かめる
kill 1
root@redis:/data# command terminated with exit code 137
kubectl get pod redis --watchのその後の状態
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 41m
redis 0/1 Completed 0 42m
redis 0/1 CrashLoopBackOff 0 43m
redis 1/1 Running 1 43m
kubectl exec -it redis -- /bin/bash
root@redis:/data# ls /data/redis
test-file
test-fileは生きてますね、今回のタスクは成功です。
終わったらクリーンアップしましょう。
kubectl delete pod redis
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 1 43m
redis 1/1 Terminating 1 53m
redis 0/1 Terminating 1 53m
疑問
/data/redis/はホストOSのどこのパスにマウントされたのでしょう?
今回使ったVolume種別のVolumes emptyDir (kubernetes.io)仕様を見てみましょう。
In this exercise, you create a Pod that runs one Container. This Pod has a Volume of type emptyDir that lasts for the life of the Pod, even if the Container terminates and restarts. Here is the configuration file for the Pod:
PodがスケジューリングされたNodeから追い出されるまでは、emptyDirVolumeは生きているらしいです。
By default, emptyDir volumes are stored on whatever medium is backing the node - that might be disk or SSD or network storage, depending on your environment. However, you can set the emptyDir.medium field to "Memory" to tell Kubernetes to mount a tmpfs (RAM-backed filesystem) for you instead
emptyDirは、デフォルトの動作ではNodeが持っているストレージを使い、emptyDir.mediumフィールドへ"Memory"を設定した場合は、Nodeのメモリ上にtmpfs(RAMディスク)を構築してくれるらしいです。
今回は何も設定していないので、やはりホストOS内のストレージのルート/パーティション以下にtest-fileが存在すると考えるのですが・・・locate kubernetesでホストOS内を探してみるも、作ったtest-file相当のファイルは見当たりません。
今回はこれ以上深堀りせず、ここまでとします。
現在のPodのVolume状態チェック
kubectl describe pod redis
...
Containers:
redis:
Mounts:
/data/redis from redis-storage (rw)
...
redis-storage:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
SizeLimit: <unset>
まとめ
今回はemptyDirというVolume種別について、簡単に触るタスクでした。
emptyDirは、基本的にPodがNodeから追い出されるまでは生きているVolume
という事で、Pod内のコンテナが死んでも、再度同じNode内で復活すれば、保存したデータも復旧できる、という事のようです。
(Node自体を信用出来ない状況になった際、別NodeへPodを移動したいケースには合わないな・・・と、k8sの運用では現実的でない感じがします)
いずれ、今回のタスクは「Pod内のコンテナにVolumeをマウントする事」がメインだったので、これは達成出来ました。
Volume, ストレージについては様々な知識を深堀りする必要はありますが、最低限
- マウント、アンマウントの方法と場所(お互いのパス、紐付け方)
- データの生存期間
- Volumeの指定方法(メモリ、永続ストレージ等)
を抑えておけば大丈夫かなと考えています。
以上です。
補足:略語(慣習的な用語を除く)
- k8s: Kubernetes
- CNI: Container Networking Interface
- CRI: Container Runtime Interface




