TT Lab
はじめる
学ぶ 学習パス コース

KCNA — Kubernetes・クラウドネイティブ入門

合うディスクがあるのに PVC がバインドされない

TT Labで続きを見る

目標

no-provisionerのStorageClassと手で作ったPVを使い、PVCがいつバインドされるのか(WaitForFirstConsumer)、どんな要求だと最後までバインドされないのか(accessModeの不一致)、PVCを削除したあとPVがどう残るのか(Retain → Released)を、自分で観察します。

なぜ重要なのか

Podが消えても、データは残らなければなりません。Kubernetesはそのために、「ディスクそのもの(PV)」と「ディスクをくださいという要求(PVC)」を分け、両者を対応づける仕事をコントローラーに任せています。そのため、PVCがPendingという1つの症状の裏には、「まだ使うPodがないので、わざと待っている最中」と「条件に合うボリュームがそもそもない」という、まったく異なる原因が隠れています。

reclaimポリシーも、運用でよく事故が起きる箇所です。Deleteポリシーだと、PVCを1つ削除しただけでデータが消え、Retainだとデータは守られますが、PVがReleasedのまま残って自動的には再利用されません。両者の違いを知らずにPVCを削除すると、取り返しのつかないことが起こります。

ステップ

  1. ネームスペースkcna-storageを作成してください。
  2. StorageClasslocal-fast(no-provisioner、WaitForFirstConsumer、Retain)を作成してください。
  3. PVpv-fast-1(1Gi、ReadWriteOnce、Retain、hostPath)を作成してください。
  4. PVCdataを作成し、消費者がいないためPendingのままであることを確認してください。
  5. Podwriterがdataをマウントすると、PVCがpv-fast-1にバインドされることを確認してください。
  6. ReadWriteManyを要求するPVCwideとPodwiderが、最後までバインドされないことを確認してください。
  7. writerとdataを削除し、pv-fast-1がReleasedのまま残ることを確認してください。
  8. 観察結果を/root/kcna-storage/report.txtに帳簿として残してください。

参考

ディスクを分け与える作業場を開く

ネームスペースkcna-storageを作成してください。

PVCとPodはネームスペースに属しますが、PVとStorageClassはクラスタースコープです。まず、PVCが入るネームスペースを用意してください。createを--dry-run=client -o yamlで出力してapplyすれば、繰り返し実行しても安全です。

使う人が現れるまで待つストレージのクラス

StorageClasslocal-fastを作成してください。provisionerはkubernetes.io/no-provisioner、volumeBindingModeはWaitForFirstConsumer、reclaimPolicyはRetainです。

no-provisionerは、ボリュームを自動で作らないという意味なので、PVは管理者が手で用意します。volumeBindingModeのデフォルト値Immediateは、PVCができた途端にPVを対応づけ、WaitForFirstConsumerは、そのPVCを使うPodがスケジュールされるまで対応づけを遅らせます。StorageClassにはkubectl createのサブコマンドがないので、YAML(apiVersion storage.k8s.io/v1)で書いてapplyしてください。

管理者が手で敷いておいた1Giのディスク

PersistentVolumepv-fast-1を作成してください。容量は1Gi、accessModesは[ReadWriteOnce]、persistentVolumeReclaimPolicyはRetain、storageClassNameはlocal-fast、hostPathのパスは/tmp/pv-fast-1です。

PVはクラスタースコープのオブジェクトなので、metadataにnamespaceがありません。PVCと対応づけられるには、storageClassName・accessModes・容量が要求を満たしている必要があります。StorageClassのreclaimPolicyは、動的プロビジョニングされたPVにのみ適用されるため、手で作るPVには、specにreclaimポリシーを直接書く必要があります。作成した直後にSTATUSを見てください。

合うディスクがあるのにPVCがPendingのままになる

ネームスペースkcna-storageにPVCdataを作成してください。accessModesは[ReadWriteOnce]、storageClassNameはlocal-fast、要求容量は1Giです。まだこのPVCを使うPodがないので、Pendingのままになります。その瞬間を/root/kcna-storage/pending.jsonに記録してください。PVCのuid・phase・volumeNameの3つのキーです。あとのステップでPVCがバインドされて削除されても、このステップはこの記録とクラスターのイベントで判定します。

条件に合うPVがあっても、WaitForFirstConsumerのクラスでは、消費者(Pod)が現れるまでバインドが起こりません。これは故障ではなく設計です。Podがどのノードに行くかが決まってから、そのノードで使えるボリュームを選ぶためです。kubectl describe pvc dataのEventsで理由を読んだあと、kubectl get pvc data -o jsonから必要な3つの値をjqで選び出し、ファイルに残してください。値を手で作り出すと、イベントのUIDと合わず失敗します。

Podが現れるとPVCがバインドされる

ネームスペースkcna-storageにPodwriter(イメージnginx:1.27-alpine)を作成し、PVCdataを/dataにマウントしてください。PVCdataがBoundになり、対応づけられたボリュームがpv-fast-1であれば、その瞬間のPVCのuid・phase・volumeNameを/root/kcna-storage/bound.jsonに記録してください。

PodのspecのvolumesにpersistentVolumeClaim(claimName)のボリュームを宣言し、コンテナのvolumeMountsで、そのボリューム名をmountPathに結び付けます。スケジューラーがPodをノードに配置した瞬間に、遅延していたバインドが進みます。固定のsleepの代わりに、PVCのstatus.phaseを数秒おきに読み直して、Boundになるまで待ってください。

複数で一緒に使いたいという要求は、誰も受け入れてくれない

ネームスペースkcna-storageにPVCwideを作成してください。accessModesは[ReadWriteMany]、storageClassNameはlocal-fast、要求容量は1Giです。そしてPodwider(イメージnginx:1.27-alpine)が、このPVCをマウントするようにしてください。ReadWriteManyを提供するPVがないので、PVCwideはBoundにならないはずです。

PVCのaccessModesは、「この方式が可能なボリュームをください」という要求です。クラスターにあるPVはReadWriteOnceの1つだけで、それも、すでにほかのPVCにバインドされています。消費者のPodがあっても、条件を満たすPVがなければ、PVCはPending、Podはスケジュールされません。ステップ5と同じ形でPVCとPodを作り、accessModesだけを変えてください。

PVCを削除したのに、ディスクは残った

Podwriterを削除してから、PVCdataを削除してください。reclaimポリシーがRetainのPVpv-fast-1は、削除されずReleased状態で残る必要があります。

使用中のPVCは、保護用のfinalizerのため、Podが消えるまで削除されないので、先にPodを削除します。PVCが消えると、PVはreclaimポリシーに従います。Deleteなら、PVも削除され、Retainなら、データを守るためにReleasedのまま残り、ほかのPVCには再びバインドされません。PVのSTATUSが変わるまでポーリングしてください。

ディスクがどう流れていったかを帳簿に残す

観察した結果を/root/kcna-storage/report.txtに、ちょうど4行で書いてください。sc-binding-mode=WaitForFirstConsumer、pv-reclaim=Retain、pv-phase-after-release=Released、wide-pvc=Pendingです。値は実際のクラスターの状態と一致している必要があります。

採点ツールは、各行を、実際のStorageClassのvolumeBindingMode、PVのreclaimポリシーとphase、PVC wideのphaseと照合します。kubectl get sc,pvとkubectl get pvc -n kcna-storageで確認した値を、そのまま写してください。