Kubernetes Kubernetes

永続ストレージ:ボリューム、PersistentVolume、クレーム

PVC で Pod の再起動をまたいでデータを保持し、StorageClass が各要素をどうつなぐかを理解します。

14 min learn.level.中級

コンテナのファイルシステムは、コンテナが存続する間しか続きません。Pod が置き換えられると、それが書き込んだものはすべてなくなります。ステートレスな Web サーバーならそれで問題ありませんが、データベース、アップロードされたファイル、その他生き残る必要のあるものにとっては問題です。このガイドでは、Kubernetes が Pod に永続的なストレージをどうアタッチするかを説明します。

コンテナのストレージでは不十分な理由

コンテナは小さく使い捨てであることを意図しているため、データをその中に置くことはモデルに反します。データは、コンテナの外、Pod の外、Pod の起動時に Kubernetes がアタッチするストレージ上に存在する必要があります。そのストレージが何であるかについて、Kubernetes は関知しません。クラウドのディスク、ネットワーク共有、ローカルドライブなどです。また、データのバックアップもしてくれません。それは引き続き、あなたの仕事です。

ストレージの連鎖

4 つのオブジェクトが連携します。

  • StorageClass は、ストレージの種類と、それをオンデマンドで作成する方法を記述します(たとえば「クラウドプロバイダーの高速な SSD ボリューム」)。
  • PersistentVolume(PV) は、クラスター内の実際のストレージの 1 つの単位です。
  • PersistentVolumeClaim(PVC) は、ユーザーまたはアプリケーションによるストレージの要求です。「1 つのノードが読み書きできる 1 GiB が必要」というものです。
  • Pod は、そのクレームをボリュームとして参照し、コンテナにマウントします。
コンテナ ─ mountPath ─▶ Pod のボリューム ─▶ PVC ─ バインド ─▶ PV ─▶ 実際のストレージ
                                                              ▲
                                       StorageClass がオンデマンドで PV を作成

PVC は、正確に 1 つの PV にバインドされます。Pod は PV を決して参照せず、クレームだけを参照します。これが、アプリケーションをストレージの詳細から独立させている仕組みです。

PVC でストレージを要求する

ほとんどのクラスターには、ボリュームをオンデマンドで作成する(動的プロビジョニングと呼ばれる)デフォルトの StorageClass があり、minikube にも含まれています。お使いのものを確認します。

kubectl get storageclass

次に、ストレージを要求します。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
kubectl apply -f pvc.yaml
kubectl get pvc,pv

クレームは Bound になり、対応する PV が現れるはずです。一部のストレージクラスは、Pod が実際にクレームを使うまでボリュームの作成を待つため、この時点での Pending は、必ずしもエラーではありません。

Pod にマウントして、永続性を証明する

apiVersion: v1
kind: Pod
metadata:
  name: storage-demo
spec:
  containers:
    - name: app
      image: busybox:1.36
      command: ["sh", "-c", "sleep 3600"]
      volumeMounts:
        - name: data
          mountPath: /data
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: data

ファイルを書き込み、Pod を破棄し、再作成して、ファイルが残っていることを確認します。

kubectl apply -f pod.yaml
kubectl exec storage-demo -- sh -c 'echo persisted > /data/proof.txt'
kubectl delete pod storage-demo
kubectl apply -f pod.yaml
kubectl exec storage-demo -- cat /data/proof.txt

新しい Pod はまったく別のコンテナですが、クレームと、その背後のデータが、再びアタッチされました。

アクセスモード、reclaim ポリシー、静的ボリューム

  • アクセスモードは、ボリュームをどのようにマウントできるかを示します。ReadWriteOnce は、単一のノードによる読み書きを意味するため、そのノード上の複数の Pod は、それでも共有できます。ReadOnlyMany と ReadWriteMany は、ストレージがサポートしていれば、多くのノードを許可します。ReadWriteOncePod は、単一の Pod に制限します。
  • reclaim ポリシーは、クレームが削除されたときにボリュームがどうなるかを決めます。動的にプロビジョニングされたボリュームは通常、デフォルトが Delete で、基盤のストレージとそのデータを削除します。データを保持したい場合は Retain を使います。
  • 静的プロビジョニングは、管理者が PV を手作業で作成し、クレームが適合するものにバインドされることを意味します。ノード上のディレクトリを使う hostPath の PV は、よくあるデモですが、データを 1 台のマシンに縛りつけるため、単一ノードの開発にしか適していません。

データベースと StatefulSet

Deployment の Pod に 1 つのクレームをマウントすることはできますが、Deployment のレプリカは交換可能で同一であり、ほとんどのデータベースはそのようには動作しません。StatefulSet は、ステートフルなワークロード向けに作られています。各 Pod に安定した ID(db-0、db-1)を与え、順番に起動と更新を行い、レプリカごとに別々の PVC を作成できます。

spec:
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 5Gi

StatefulSet が扱うのは ID とストレージであり、データのレプリケーションではありません。レプリカ同士を一貫させるのはデータベースの仕事であり、そのため、Kubernetes 上でデータベースを実行することは、ステートレスなサービスの実行より難しくなります。多くのチームは、マネージドデータベースやデータベース operator を使い、ステートレスなアプリケーションをクラスターに置いています。

人気のガイド