0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KubernetesのVolume・PV・PVCとは何か?

0
Posted at

はじめに

前回は、Secretを使ってパスワードやAPIトークンなどの機密情報をPodへ渡す仕組みを学びました。

Secret
        ↓
Pod
        ↓
Container

ConfigMapやSecretは、設定値をPodへ渡すための仕組みです。

では、アプリケーションが実行中に作成したデータはどこへ保存すればよいのでしょうか。

たとえば、次のようなデータです。

ユーザーがアップロードしたファイル
アプリケーションが生成したファイル
データベースのデータ
一時的なキャッシュ
複数コンテナで共有するファイル

コンテナ内へ保存するだけでは、コンテナやPodの再作成によってデータが消える可能性があります。

そこで登場するのが、次の仕組みです。

  • Volume
  • PersistentVolume(PV)
  • PersistentVolumeClaim(PVC)
  • StorageClass

この記事では、次の内容を整理します。

  • コンテナ内のデータが消える理由
  • Volumeとは何か
  • emptyDirとは何か
  • PVとPVCの違い
  • StorageClassと動的プロビジョニング
  • PodからPVCを利用する方法
  • Access Modeの違い
  • Reclaim Policyの違い
  • EKS・EBS CSI Driverとの関係
  • EBSとAZの関係
  • EBS・EFS・S3の使い分け
  • Railsで何をどこへ保存するのか

結論

Volumeとは、Pod内のコンテナから利用する保存場所です。

そのうち、Podが削除されてもデータを残したい場合は、PVとPVCを利用します。

Pod
└── PVCを使いたいと申請する
        ↓
PVC
└── 必要な容量・種類を要求する
        ↓ バインド
PV
└── Kubernetes上でストレージを表す
        ↓
実際のストレージ
└── EBS・EFS・NFSなど

StorageClassを利用すると、PVCの要求に応じて実際のストレージとPVを自動的に作成できます。

PVCを作成
        ↓
StorageClassを参照
        ↓
CSI Driverがストレージを作成
        ↓
PVが作成される
        ↓
PVCとPVがバインドされる
        ↓
Podから利用する

EKSでEBSを使う場合は、Amazon EBS CSI DriverがAWS APIを通してEBS Volumeの作成やNodeへの接続を行います。

なぜコンテナ内へ保存するだけでは駄目なのか

コンテナには、書き込み可能なファイルシステムがあります。

そのため、コンテナ内へファイルを作成すること自体はできます。

Container
└── /app/tmp/example.txt

しかし、コンテナは再作成されることがあります。

  • Deploymentを更新した
  • コンテナが異常終了した
  • Podが別のNodeへ作り直された
  • Nodeで障害が発生した
  • Podを手動で削除した
  • オートスケーリングでPodが入れ替わった

コンテナが作り直されると、そのコンテナ固有の書き込み領域は引き継がれません。

古いContainer
└── /app/data/file.txt
        ↓ Containerを再作成
新しいContainer
└── file.txtは存在しない

Kubernetesでは、Podやコンテナが入れ替わることを前提として、保存先を分離します。

Volumeとは

Volumeは、Pod内のコンテナから利用できる保存場所です。

PodのYAMLでは、次の2か所を設定します。

spec.volumes
└── Podが使うVolumeを定義する

spec.containers[].volumeMounts
└── Container内のどこへVolumeを見せるか定義する
Pod
├── Volume
│   └── データを保持する
│
├── Container A
│   └── /app/sharedへマウント
│
└── Container B
    └── /worker/sharedへマウント

同じPod内の複数コンテナでVolumeを共有することもできます。

Volumeは1種類ではない

Volumeは、1つの製品名ではありません。

用途に応じて複数の種類があります。

Volumeの例 主な用途 Pod削除後
emptyDir Pod内の一時データ・コンテナ間共有 消える
configMap 設定ファイルを渡す ConfigMapが元データ
secret 機密ファイルを渡す Secretが元データ
persistentVolumeClaim 永続ストレージを利用する ストレージ側へ残せる
CSI Volume 外部ストレージと連携する 種類・設定による

つまり、すべてのVolumeが永続化されるわけではありません。

Volume
├── 一時的なVolume
└── 永続ストレージへつながるVolume

emptyDirとは

emptyDirは、Podが作成されたときに用意される空の領域です。

apiVersion: v1
kind: Pod
metadata:
  name: shared-data-example
spec:
  containers:
    - name: writer
      image: busybox:1.36
      command: ["sh", "-c", "echo hello > /shared/message.txt && sleep 3600"]
      volumeMounts:
        - name: shared-data
          mountPath: /shared

    - name: reader
      image: busybox:1.36
      command: ["sh", "-c", "cat /shared/message.txt && sleep 3600"]
      volumeMounts:
        - name: shared-data
          mountPath: /shared

  volumes:
    - name: shared-data
      emptyDir: {}

このPodでは、2つのコンテナが同じemptyDirを利用します。

Pod
├── writer Container
│   └── /shared/message.txtへ書き込む
│
├── emptyDir: shared-data
│
└── reader Container
    └── /shared/message.txtを読み込む

コンテナだけが再起動した場合、同じPodが存続していればemptyDirのデータは残ります。

しかし、Podが削除・再作成されるとemptyDirも削除されます。

Containerの再起動
→ 同じPodならemptyDirは残る

Podの削除・再作成
→ emptyDirも消える

一時ファイル・処理途中のデータ・同一Pod内のコンテナ間共有などに向いています。

永続Volumeが必要になる場面

Podが削除されても残す必要があるデータには、永続ストレージを利用します。

Pod A
└── /dataへファイルを保存
        ↓ Pod Aを削除
永続ストレージ
└── データは残る
        ↓
Pod B
└── 同じデータを利用する

Kubernetesでは、永続ストレージを扱うために主にPVとPVCを使用します。

PersistentVolumeとは

PersistentVolumeは、略して PV と呼ばれます。

PVは、Kubernetesクラスターから利用できるストレージを表すリソースです。

PV
└── 実際のストレージをKubernetes上で表現する
        ↓
EBS・EFS・NFS・その他のストレージ

PVは特定のPodだけに属するものではありません。

Podより長いライフサイクルを持ち、Namespaceにも属さないクラスター単位のリソースです。

Podを削除
        ↓
PV・実ストレージ
設定に応じて残せる

PersistentVolumeClaimとは

PersistentVolumeClaimは、略して PVC と呼ばれます。

PVCは、Pod側から出すストレージの利用申請です。

PVC
├── 10Giほしい
├── 読み書きしたい
└── このStorageClassを使いたい

Kubernetesは、PVCの条件に合うPVを探して結び付けます。

この結び付きを バインド と呼びます。

PVC
10Gi・ReadWriteOnceを要求
        ↓ 条件を照合
PV
20Gi・ReadWriteOnceを提供
        ↓
Bound

PVCはNamespaceに所属します。

同じNamespaceのPodからPVCを参照します。

PVとPVCを分ける理由

PodがAWS EBSやNFSなどの詳細を直接すべて意識すると、アプリケーションとインフラが強く結び付きます。

PVとPVCを分けることで、利用者は必要な条件を申請し、管理側はその条件を満たすストレージを提供できます。

アプリケーション側
「10Giの読み書きできる領域がほしい」
        ↓ PVC

クラスター・ストレージ側
「条件に合うストレージを提供する」
        ↓ PV
リソース 視点 主な内容
PV ストレージを提供する側 容量、Access Mode、実体との接続
PVC ストレージを利用する側 必要な容量、Access Mode、StorageClass

PV・PVCを手動で用意する流れ

管理者が先にストレージとPVを用意する方法を、静的プロビジョニングと呼びます。

1. 管理者が実ストレージを作成
        ↓
2. 管理者がPVを作成
        ↓
3. 利用者がPVCを作成
        ↓
4. 条件の合うPVとPVCをバインド
        ↓
5. PodがPVCを利用

PVの概念を理解するための簡略例です。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: example-storage
  csi:
    driver: example.csi.driver
    volumeHandle: example-volume-id

実際のcsi設定は、利用するストレージやCSI Driverによって異なります。

PVCを定義するYAML

次のPVCは、10Giのストレージを要求します。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: gp3
  resources:
    requests:
      storage: 10Gi

各項目の意味は次のとおりです。

項目 意味
accessModes ストレージへどのように接続するか
storageClassName 利用したいStorageClass
resources.requests.storage 必要な容量

Pod・DeploymentからPVCを使う

PVCを作成しただけでは、コンテナ内へ表示されません。

DeploymentのvolumesからPVCを参照し、コンテナのvolumeMountsへマウント先を書きます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rails
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rails
  template:
    metadata:
      labels:
        app: rails
    spec:
      containers:
        - name: rails
          image: example/rails-app:1.0
          volumeMounts:
            - name: app-data
              mountPath: /app/data
      volumes:
        - name: app-data
          persistentVolumeClaim:
            claimName: app-data-pvc

関係は次のようになります。

Container
└── /app/data
        ↓ volumeMounts
PodのVolume
└── app-data
        ↓ persistentVolumeClaim
PVC
└── app-data-pvc
        ↓ バインド
PV
        ↓
実際のストレージ

mountPathは、コンテナ内でストレージを見せる場所です。

PVC名をclaimNameへ指定します。

StorageClassとは

StorageClassは、どのようなストレージを作るか定義するリソースです。

StorageClass
├── どのCSI Driverを使うか
├── どの種類のストレージを作るか
├── 削除時にどうするか
├── いつVolumeを作るか
└── 拡張を許可するか

EKSでEBSのgp3を利用する概念例です。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gp3
provisioner: ebs.csi.aws.com
parameters:
  type: gp3
  encrypted: "true"
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer
allowVolumeExpansion: true
項目 意味
provisioner ストレージ作成を担当するCSI Driver
parameters ストレージ固有の設定
reclaimPolicy PVC解放後のストレージの扱い
volumeBindingMode PVを作成・バインドするタイミング
allowVolumeExpansion 容量拡張を許可するか

この例は標準のAmazon EBS CSI Driver向けです。

EKS Auto Modeでは、EBS用Provisioner名がebs.csi.eks.amazonaws.comとなり、標準EBS CSI Driverのebs.csi.aws.comとは別に管理されます。

動的プロビジョニングとは

StorageClassを使い、PVCが作成されたときにストレージとPVを自動作成する仕組みを、動的プロビジョニングと呼びます。

PVCを作成
10Gi・StorageClass gp3を要求
        ↓
StorageClass gp3
        ↓
EBS CSI Driver
        ↓ AWS API
10GiのEBS Volumeを作成
        ↓
PVを自動作成
        ↓
PVCとPVをバインド

管理者がPVを1個ずつ事前作成する必要がなくなります。

現在のクラウド環境では、動的プロビジョニングを利用する構成が一般的です。

デフォルトStorageClass

デフォルトのStorageClassが設定されている場合、PVCでstorageClassNameを省略すると、そのStorageClassが利用されます。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

StorageClassを確認します。

kubectl get storageclass

短縮形も利用できます。

kubectl get sc

出力例です。

NAME            PROVISIONER       DEFAULT
gp3 (default)   ebs.csi.aws.com   Yes

どのStorageClassがデフォルトなのか確認せずに省略すると、意図しない種類のストレージが作られる可能性があります。

明示的に選びたい場合はstorageClassNameを指定します。

WaitForFirstConsumerとは

EBSのように特定のAZへ作成されるストレージでは、Podの配置先とVolumeのAZを合わせる必要があります。

PVC作成直後にEBSを作ると、PodがどのAZへ配置されるか決まっていない場合があります。

EBS Volume
└── AZ-aへ先に作成

Pod
└── AZ-cへ配置したい

AZが違うため接続できない

StorageClassへ次を指定します。

volumeBindingMode: WaitForFirstConsumer

これにより、PVCを利用する最初のPodがスケジュールされるまで、Volumeの作成・バインドを待ちます。

PVCを作成
        ↓ 待機
Podを作成
        ↓ 配置可能なAZを判断
Podの配置先に合わせてVolumeを作成
        ↓
PodとVolumeを同じAZで利用

複数AZを持つEKSクラスターでは特に重要な設定です。

Access Modeとは

Access Modeは、VolumeをNodeからどのようにマウントできるかを表します。

Access Mode 略称 意味
ReadWriteOnce RWO 1つのNodeから読み書きできる
ReadOnlyMany ROX 複数Nodeから読み取り専用で利用できる
ReadWriteMany RWX 複数Nodeから読み書きできる
ReadWriteOncePod RWOP クラスター内の1つのPodだけが読み書きできる

ここで注意したいのは、ReadWriteOnceは「1つのPodだけ」という意味ではないことです。

ReadWriteOnce
= 1つのNodeから読み書き可能

同じNode上にある複数Podから利用できる場合があります。

1つのPodだけに限定したい場合は、対応するCSI DriverでReadWriteOncePodを検討します。

また、YAMLへAccess Modeを書くだけで、ストレージ自体の能力が変わるわけではありません。

利用するストレージとCSI Driverが、そのAccess Modeへ対応している必要があります。

EBSとAccess Mode

Amazon EBSは、EC2インスタンスへ接続して利用するブロックストレージです。

EKSで一般的に利用する場合、EBSはReadWriteOnceの用途に向いています。

AZ-a
├── Node A
│   └── Pod
│       └── EBS Volumeをマウント
│
└── EBS Volume

複数Nodeにまたがる多数のPodから同時に同じファイルを読み書きしたい場合は、EFSなど別のストレージを検討します。

Reclaim Policyとは

Reclaim Policyは、PVCが削除・解放された後にPVや実ストレージをどう扱うか決めます。

主な値は次の2つです。

Reclaim Policy 動作
Delete PVと実ストレージを削除する
Retain PVや実ストレージを残し、手動対応する

Delete

PVCを削除
        ↓
PVを削除
        ↓
EBS Volumeなども削除

不要なストレージが自動的に片付く一方、誤ってPVCを削除するとデータも失う可能性があります。

Retain

PVCを削除
        ↓
PV・実ストレージを残す
        ↓
管理者が確認・回収する

重要なデータを誤削除から守りやすくなりますが、不要なストレージを手動で管理する必要があります。

本番環境では、バックアップ・スナップショット・削除保護を含めて決めます。

PVとPVCの状態

次のコマンドで状態を確認します。

kubectl get pv
kubectl get pvc

代表的な状態は次のとおりです。

状態 意味
Available PVがまだPVCへ割り当てられていない
Pending PVCが利用できるVolumeを待っている
Bound PVとPVCが結び付いている
Released PVCは削除されたがPVがまだ回収されていない
Failed 自動回収などに失敗した

PVCがPendingのままの場合は、条件に合うPVがないか、動的プロビジョニングに問題がある可能性があります。

PVCを作成して確認する

PVCを作成します。

kubectl apply -f pvc.yaml

状態を確認します。

kubectl get pvc

詳細やイベントを確認します。

kubectl describe pvc app-data-pvc

PVも確認します。

kubectl get pv

StorageClassを確認します。

kubectl get storageclass

PodがVolumeをマウントできない場合は、Podのイベントも確認します。

kubectl describe pod rails-xxxxx

EKSでEBSを使うときの登場人物

標準的なEKSでEBSを動的作成する場合、次の要素が関係します。

Pod
        ↓ PVCを参照
PVC
        ↓ StorageClassを参照
StorageClass
        ↓ Provisionerを指定
Amazon EBS CSI Driver
        ↓ AWS APIを呼ぶ
EBS Volume
        ↓ Nodeへ接続
PodのContainerへマウント
要素 役割
PVC 必要な容量・Access Modeを要求する
StorageClass EBSの種類や作成方法を定義する
EBS CSI Driver KubernetesとAWS EBSを連携する
EBS Volume 実際にデータを保存する
Node EBSを接続し、Podへマウントする

CSI Driverとは

CSIは、Container Storage Interfaceの略です。

Kubernetesと外部ストレージをつなぐための共通インターフェースです。

Kubernetes
        ↓ CSIという共通の約束
CSI Driver
        ↓ ストレージ固有のAPI
EBS・EFS・その他のストレージ

EBS CSI Driverは、主に次の処理を行います。

  • EBS Volumeを作成する
  • EBS Volumeを削除する
  • EBS VolumeをNodeへ接続する
  • Nodeから切り離す
  • ファイルシステムとしてマウントする
  • 対応する構成で容量を拡張する
  • Snapshot機能と連携する

EKSでは、AWSはAmazon EBS CSI DriverをEKS Add-onとして導入する方法を推奨しています。

EBS CSI DriverがAWS APIを操作するため、Pod IdentityやIRSAなどを使って必要なIAM権限を付与します。

EBSとAZの関係

EBS Volumeは、作成された1つのAvailability Zoneに属します。

東京リージョン
├── AZ-a
│   ├── Node A
│   └── EBS Volume A
│
├── AZ-c
│   └── Node C
│
└── AZ-d
    └── Node D

AZ-aのEBS Volumeを、AZ-cのNodeへ直接接続することはできません。

そのため、EBSを利用するPodは、Volumeと同じAZへ配置する必要があります。

EBS Volume:AZ-a
        ↓
Pod:AZ-aのNodeへスケジュール

Podが別AZへ自由に移動できる状態と、単一AZに存在するEBSには違いがあります。

障害対策では、EBS Snapshot・アプリケーション側のレプリケーション・マネージドデータベースなども検討します。

EKS Auto Modeでの注意点

通常のEKSとEKS Auto Modeでは、EBSのProvisionerが異なります。

構成 Provisioner
標準Amazon EBS CSI Driver ebs.csi.aws.com
EKS Auto ModeのBlock Storage ebs.csi.eks.amazonaws.com

既存の標準EBS CSI DriverのVolumeと、Auto Modeが管理するVolumeは別に管理されます。

構成図やStorageClassを見るときは、どちらのProvisionerを利用しているか確認します。

FargateとEBSの注意点

AWSの公式ドキュメントでは、EBS VolumeをFargate Podへマウントすることはできません。

EBS CSI ControllerをFargate Node上で動かすことはできますが、Node側のDaemonSetはEC2インスタンス上で動作する必要があります。

EKSでFargateを利用する場合は、必要なストレージ方式が対応しているか事前に確認します。

EBS・EFS・S3の違い

AWSには複数の保存先がありますが、役割が異なります。

サービス 種類 主な特徴
EBS ブロックストレージ EC2 Nodeへ接続し、ディスクのように使う
EFS ファイルストレージ 複数Node・Podから共有しやすい
S3 オブジェクトストレージ API経由でファイルを保存する

EBS

Pod
↓ ファイルシステムとして利用
EBS Volume
  • 低レイテンシーなブロックストレージ
  • 1つのAZに属する
  • 一般的な構成ではReadWriteOnce向け
  • EBS CSI DriverでPVとして利用できる

EFS

Pod A ─┐
Pod B ─┼→ EFS
Pod C ─┘
  • 複数Nodeから共有できるファイルストレージ
  • ReadWriteManyが必要な用途に向いている
  • EFS CSI DriverでPVとして利用できる
  • ファイル数やアクセス特性によって性能・コストを確認する

S3

Rails
↓ AWS SDK・HTTP API
S3 Bucket
  • ファイルシステムではなくオブジェクトストレージ
  • 通常はPVCとしてマウントするのではなくAPI経由で利用する
  • 画像・PDF・添付ファイル・バックアップなどに向いている
  • 複数Podや複数AZから同じオブジェクトへアクセスできる

用途に合ったサービスを選ぶことが重要です。

Railsでは何をどこへ保存するのか

Railsアプリケーションを例に整理します。

データ 保存先の例
ユーザー情報・契約情報 RDS・Aurora
アップロード画像・PDF S3
SidekiqのJob ElastiCache for Redis・Valkey
キャッシュ ElastiCache for Redis・Valkey
一時ファイル emptyDir
特定Podだけが使う永続ファイル EBS+PVCを検討
複数Podで共有するファイルシステム EFS+PVCを検討

WebアプリケーションのPodへEBSを付ければ、何でも解決するわけではありません。

たとえば、Rails Podを3つ動かし、1つのPodが受け取ったアップロードファイルをローカルEBSへ保存すると、別のPodから同じファイルを参照できない構成になる可能性があります。

Rails Pod 1
└── EBSへfile.pdfを保存

Rails Pod 2
└── file.pdfが見えない

ユーザーのアップロードファイルは、Rails Active StorageからS3へ保存する構成が一般的です。

ブラウザ
        ↓
Rails Pod
        ↓ Active Storage
S3

データベースもPod内で自前運用するより、可用性・バックアップ・運用負荷を考えてRDSやAuroraを利用する構成がよくあります。

DeploymentでPVCを使うときの注意点

Deploymentのreplicasを複数にした場合、すべてのPodが同じPVCを使えるとは限りません。

spec:
  replicas: 3

EBSのようなReadWriteOnceのVolumeでは、Podが異なるNodeへ配置されると、同じVolumeを全Podへ接続できない場合があります。

Node A
└── Pod 1 ─→ EBS

Node B
└── Pod 2 ─× 同じEBS

複数Podから同じデータへアクセスしたい場合は、次を検討します。

  • S3などのオブジェクトストレージを利用する
  • EFSなどReadWriteMany対応のストレージを利用する
  • 各Podへ個別のVolumeを与える
  • アプリケーションやデータベース側でレプリケーションする

StatefulSetとPVC

各Podへ個別の永続Volumeを持たせたい場合、StatefulSetのvolumeClaimTemplatesを利用できます。

StatefulSet
├── app-0 → PVC-0 → Volume-0
├── app-1 → PVC-1 → Volume-1
└── app-2 → PVC-2 → Volume-2

Deploymentは交換可能なPodを扱う用途に向いています。

StatefulSetは、安定したPod名やPodごとの永続ストレージが必要なワークロードに向いています。

ただし、StatefulSetを使えばデータベース運用が自動的に安全になるわけではありません。

バックアップ・レプリケーション・障害復旧は別途設計が必要です。

StatefulSetは別の記事で詳しく整理します。

PVCの容量を増やす

StorageClassで次が有効な場合、PVCの要求容量を増やせます。

allowVolumeExpansion: true

たとえば、10Giから20Giへ変更します。

resources:
  requests:
    storage: 20Gi

ただし、縮小は同じようには行えません。

また、利用するCSI Driver・ストレージ・ファイルシステムが拡張へ対応している必要があります。

変更前にバックアップと公式仕様を確認します。

データを消さないために必要なこと

PVCを使うだけで、データ保護が完成するわけではありません。

永続化
≠
バックアップ

永続Volumeにも、次の問題が起こり得ます。

  • 誤操作による削除
  • アプリケーションによるデータ破壊
  • ファイルシステムの破損
  • AWSアカウントやリージョン規模の問題
  • 暗号化キーの削除
  • Reclaim Policyの設定ミス

重要なデータでは、次を設計します。

  • Snapshot
  • 定期バックアップ
  • 別リージョン・別アカウントへの保管
  • 復元手順
  • 削除権限の制限
  • EBS暗号化
  • Reclaim Policy
  • 復旧訓練

よくあるトラブル

PVCがPendingのまま

考えられる原因は次のとおりです。

  • StorageClassが存在しない
  • Provisioner名が間違っている
  • CSI Driverが導入されていない
  • CSI DriverにIAM権限がない
  • 要求条件に合うPVがない
  • 指定したAZでVolumeを作れない
  • Pod作成を待つWaitForFirstConsumerの状態である

確認します。

kubectl describe pvc app-data-pvc
kubectl get storageclass
kubectl get pods -n kube-system

PodがContainerCreatingのまま

Volumeの作成・接続・マウントで失敗している可能性があります。

kubectl describe pod rails-xxxxx

イベントに、次のような情報がないか確認します。

  • VolumeのAttach失敗
  • Mount失敗
  • AZの不一致
  • ファイルシステムの問題
  • IAM権限不足

PVCを消したらEBSも消えた

StorageClassやPVのReclaim PolicyがDeleteだった可能性があります。

本番データでは、削除前にReclaim Policy・Snapshot・バックアップを確認します。

Podを増やしたらVolumeをマウントできない

EBSとReadWriteOnceを複数NodeのPodで共有しようとしている可能性があります。

ストレージのAccess ModeとPodの配置を確認します。

よくある勘違い

Volumeを使えば必ずデータが永続化される

VolumeにはemptyDirのような一時的な種類もあります。

永続化したい場合は、永続ストレージへ接続するVolumeを利用します。

emptyDirはコンテナ再起動で消える

同じPodが存続していれば、コンテナが再起動してもemptyDirは残ります。

Pod自体が削除されると消えます。

PVCが実際のディスクである

PVCはストレージの利用申請です。

実際のストレージをKubernetes上で表すのはPVです。

PVがEBSそのものである

PVはKubernetes上のリソースです。

EBS VolumeはAWS上に存在する実際のストレージです。

PVCを作ると必ず管理者がPVを作る

StorageClassとCSI Driverを使えば、PVと実ストレージを動的に作成できます。

ReadWriteOnceは1つのPodしか使えない

ReadWriteOnceは、基本的に1つのNodeから読み書きできるAccess Modeです。

1つのPodだけへ制限するAccess ModeはReadWriteOncePodです。

PVCを使えばバックアップは不要

永続化とバックアップは別です。

Snapshotや復元手順も必要です。

S3はPVCである

S3はオブジェクトストレージです。

通常のRailsアプリケーションでは、AWS SDKやActive Storageを通してAPI経由で利用します。

コマンドで関係を確認する

StorageClassを確認します。

kubectl get storageclass

PVCを確認します。

kubectl get pvc -A

PVを確認します。

kubectl get pv

PVCの詳細を確認します。

kubectl describe pvc app-data-pvc -n production

PVの詳細を確認します。

kubectl describe pv example-pv

Podが参照するPVCを確認します。

kubectl describe pod rails-xxxxx -n production

EBS CSI DriverのPodを確認します。

kubectl get pods -n kube-system \
  -l app.kubernetes.io/name=aws-ebs-csi-driver

EKS Add-onをAWS CLIで確認します。

aws eks describe-addon \
  --cluster-name example-cluster \
  --addon-name aws-ebs-csi-driver

これまでの流れへVolumeを加える

ここまで学んだリソースを整理します。

Ingress
└── 外部のHTTP・HTTPS通信をServiceへ振り分ける
        ↓
Service
└── Pod群へ安定した接続先を提供する
        ↓
Pod
└── Containerを動かす
        ↑
Deployment
└── Podの数と更新を管理する

ConfigMap
└── 機密ではない設定値をContainerへ渡す

Secret
└── 機密情報をContainerへ渡す

PVC → PV → EBS・EFSなど
└── Containerが使う永続データを保存する

経路を分けると理解しやすくなります。

通信の流れ
Ingress → Service → Pod → Container

設定の流れ
ConfigMap・Secret → Pod → Container

永続データの流れ
Container → Volume → PVC → PV → 実ストレージ

まとめ

Volumeは、Pod内のコンテナから利用する保存場所です。

Podが削除されてもデータを残したい場合は、PVとPVCを使って永続ストレージへ接続します。

Volume
= Podから見える保存場所

PV
= Kubernetes上でストレージを表すリソース

PVC
= Pod側から出すストレージの利用申請

StorageClass
= どのようなストレージを作るか定義する設計図

CSI Driver
= Kubernetesと実ストレージをつなぐもの

重要な点は次のとおりです。

  • コンテナ固有の書き込み領域は再作成で失われる
  • すべてのVolumeが永続化されるわけではない
  • emptyDirはPodの削除とともに消える
  • PVCは必要な容量やAccess Modeを要求する
  • PVは実ストレージをKubernetes上で表現する
  • StorageClassで動的プロビジョニングを行える
  • PodはPVCを参照し、コンテナ内へマウントする
  • Reclaim PolicyによってPVC削除後の扱いが変わる
  • EBSは1つのAZに属する
  • WaitForFirstConsumerでPodの配置先を考慮できる
  • 標準EBS CSI DriverとEKS Auto ModeではProvisioner名が異なる
  • EBS・EFS・S3は用途が異なる
  • RailsのアップロードファイルにはS3が向いている
  • 永続化とバックアップは別である

一言でまとめると、次のようになります。

PVCで必要なストレージを申請し、PVを通してEBSなどの実ストレージへ接続することで、Podが入れ替わってもデータを残せます。

次は、Podごとに安定した名前と個別の永続Volumeを持たせる StatefulSet について整理します。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?