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_ENVvalue: 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