Kubernetesストレージ(Storage)
Config Map
Config Mapというリソースを使用すると、環境変数などをKey Valueペアとして保存できる。Config Mapは、設定された環境変数をボリュームとしてPodにマウントする。 環境変数の設定は、マニフェスト内のspecの中にenvという項目を設けて設定することもできる。しかし、この場合は変数を再利用できなくなる。この問題をConfig Mapを使用して解決できる。
具体的にどのように作成するのか見ていく。まずConfig Mapマニフェストを作成する。これはkubectl createコマンドでconfigmapを指定することで可能である。以下の例ではYAMLファイルを作成している。この場合、TEST_ENVという環境変数にHello_Worldという文字列を保存する。
kubectl create configmap my-config --from-literal TEST_ENV=Hello_World -o yaml > configmap.yaml
上のコマンドを実行して作成したYAMLファイルは次のとおりである。
configmap.yaml
apiVersion: v1
data:
TEST_ENV: Hello_World
kind: ConfigMap
metadata:
creationTimestamp: "2022-09-08T08:29:59Z"
name: my-config
namespace: default
resourceVersion: "10632"
uid: 2371e43c-c361-40be-8ab9-5269edfb41c3
この場合、YAMLファイルの1段目にdataが書かれているが、これは作成するNodeが持つデータを指定する項目である。この場合は単純にkey: TEST_ENVにvalue: Hello_Worldを表している。
このように作成したYAMLファイルを利用してNodeを作成し、環境変数を利用する場合は、Pod作成時にこのConfig Mapを参照して使用できる。
以下のように、Pod作成用のYAMLファイルに記述することでConfig Mapの情報を反映する。
pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: helloworld
name: helloworld
spec:
containers:
- env:
# Podで使用する環境変数名を指定
- name: TEST_ENV_POD
# valueFromでnameに指定した環境変数へ何を入れるか指定
valueFrom:
# configMapから参照するよう指定
configMapKeyRef:
# 名前がmy-config(上で作成した)というconfigMapを指定
name: my-config
# nameで指定されたconfigMapからkeyがTEST_ENVの環境変数を参照するよう指定
key: TEST_ENV
image: gcr.io/google-samples/hello-app:1.0
ports:
- containerPort: 8080
上のpod.yamlの場合、helloworldというPodを作成するYAMLファイルだが、helloworld内の環境変数としてTEST_ENV_PODを作り、その内容にはmy-configというConfig MapのTEST_ENVに保存された値を使うよう指定している。このような指定方法にすると、他のPodでも同じように利用できるため、再利用性を高められる。
続いて、PodにVolumeをマウントする方法を見ていく。Podは管理上の基本単位であり、仮想Network Interface(IP、ファイルシステム)を共有すると前に述べたが、これはつまり、Pod自体がKubernetes上では仮想ホストのように考えられることを意味する。このようなPodに、Config Mapをボリュームとしてマウントする。Config Mapは環境変数だけでなくKey-Valueペアも保存でき、そのデータをファイルとしてボリュームにマウントできる。上で見たものは、Config Mapに保存されたデータを環境変数として呼び出していた。
これを実現するため、次のようにpod.yamlファイルを修正する。
pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: helloworld-configmap-volume
name: helloworld-configmap-volume
spec:
containers:
- image: gcr.io/google-samples/hello-app:1.0
name: helloworld-configmap-volume
ports:
- containerPort: 8080
resoueces: {}
volumeMounts:
# volume名を指定
- name:my-config-volume
# volumeをマウントするコンテナのファイルパスを指定
mountPath: /my-config/TEST_ENV
volume:
# 作成するボリューム名を指定
- name: my-config-volume
configMap:
# Config Map名を指定
name: my-config
items:
# Config MapにあるKey名を指定
- key: TEST_ENV
path: keys
このYAMLファイルでは、ボリュームに関して、my-configという名前のConfig Mapをmy-config-volumeという名前のボリュームとして指定し、この名前を指定してマウントを実行し、そのとき対応するコンテナ内のパス名を/my-config/TEST_ENVにしている。このようにするとファイル化され、変更できるという利点がある。
永続Volume
続いて、永続Volume(Persistent Volume)について見ていく。
コンテナでは、Pod内にあるVolumeに変更を行うことでデータを書き込んでいる。したがってPodが消えるとデータも消える。これを防ぐには、クラスタ全体のNodeにあるPersistent Volumeにデータを保存する。実際の動作としては、複数Nodeがあるクラスタ内に各Nodeが共有できるvolume、つまりPersistent Volumeを作成し、各Nodeが必要な分だけこの共通volumeへ要求し、取得したvolumeを要求元のNodeへマウントする。
そのため、共通volumeを定義するYAMLファイル(pv.yaml)と要求事項を入れたYAMLファイル(pvc.yaml)を用意し、Pod、つまりNode作成時に使用するYAMLファイル(pod.yaml)には、この要求事項を参照するように記述する。各ファイルのサンプルは以下のとおりである。
pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv
spec:
storageClassName: manual
# volumeのサイズを指定
capacity: 100M
# アクセス権限範囲を指定
accessModes: ReadWriteOnce
hostPath:
# Node上のパスを指定
path: "/mnt/pvc"
pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc
spec:
storageClassName: manual
# アクセス権限範囲を指定
accessModes: ReadWriteOnce
resources:
# 要求事項を指定
requests:
# 必要な容量を指定
storage: 10M
pod.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: helloworld-pvc
name: helloworld-pvc
spec:
containers:
- image: gcr.io/google-samples/hello-app:1.0
name: helloworld-pvc
ports:
- containerPort: 8080
resoueces: {}
volumeMounts:
# volume名を指定
- name:my-pv
# volumeをマウントするコンテナのファイルパスを指定
mountPath: /mnt/pvc
volume:
# 作成するボリューム名を指定
- name: my-pv
# 永続ボリューム要求名を指定
persistentVolumeClaim:
name: pvc
実行する場合は、上の3つのファイルを順番にkubectl applyで実行していくが、その前にクラスタにディレクトリを作成しておく必要がある。そのため、minikubeを使用している場合は、以下のようにコマンドでクラスタへ接続して作成する。
$ minikube ssh
$ sudo mkdir mnt/pvc