はじめに
前回は、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 について整理します。