HackyViolette

人生暇つぶし

StorageClass の Dynamic Provisioning と VolumeBindingMode について

CKA受験勉強時にはStorageClassについて全くと言っていいほど知らなかった(なんかあるなぁって感じ)のですが、CKAD受験に向けて基本のキを知ったのでメモします。

StorageClass

kubernetes.io

ストレージの実体をどのようにプロビジョニングするかの定義的なものと理解しました。

主なフィールドは以下の通りです。

  • provisioner: Volumeプラグイン(どのような形でストレージを実装するか)を指定
  • parameters: Volumeプラグインのパラメータを指定
  • reclaimPolicy: Delete / Retain(PVCの削除とともにPVを削除 / PVC削除後にPVが残る)
  • volumeBindingMode: Immediate / WaitForFirstConsumer(PVC作成後即PVを割り当てる / PodでPVCが使われるまでPVを割り当てない)

example-sc.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: example-sc                 # 本来はこのような名前はNG(容量重視とかパフォーマンス重視とかわかりやすい名前をつける)
provisioner: kubernetes.io/aws-ebs # AWS EBSプラグインを使用(PVの実体)
parameters:
  type: gp3                        # EBSのgp3を指定
reclaimPolicy: Retain              # PVC削除後もPVは残る(再利用できるわけではない)
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate       # PVC作成後すぐにPVが割り当てられる

PVやPVCマニフェストでもこのStorageClassが設定されています。

設定しない場合はデフォルトのStorageClassが当たります(デフォルトがあれば)。

example-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
  labels:
    type: local
spec:
  storageClassName: example-sc # StorageClassを指定
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/mnt/data"

example-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: example-pvc
spec:
  storageClassName: example-sc # StorageClassを指定
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi

Dynamic Provisioning

PV を使うためには基本的には以下の流れでリソースを作成していきます。

  1. StorageClass 作成
  2. PV 作成 ※
  3. PVC 作成 ※
  4. Pod 作成(volumesに PVC を指定)

※ PV 作成と PVC 作成は実際にはどちらが先でもよいです。

このような流れで作成した場合、Podを作成するときには PV と PVC が先に存在しなければなりません。

PVC は StorageClassやAccessMode、Resources の要件に合う PV を探すので、この例の場合にはstorageClassName==example-sc, accessMode==ReadWriteOnce, requests.storage==3Gi(以上)を探し、example-pvとバインドされます。PVとしてEBSが10Gi確保され、PVCで3Giリクエストされている状態です。これはPVCに対して過剰な容量のPVが当たっているのでストレージが無駄になります。

それを解決するのが Dynamic Provisioning です。

kubernetes.io

Dynamic Provisioning では PVC が作成されたタイミングでその要件に沿った PV を作成しバインドします。そのため過剰なストレージ容量を食うことなく PV を作成することができます。ただし、Dynamic Provisioning に対応した provisioner を利用する必要があるため注意です(EKS / AKS / GKE を利用し、クラウドストレージを普通に利用する分には問題ないです)。

以下のように用途に合わせてslow, fast といった StorageClass を作成できます(GCP PDを利用する場合の例)。

example-sc-dynamic.yaml

---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: slow
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-standard
---
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast
provisioner: kubernetes.io/gce-pd
parameters:
  type: pd-ssd

PVC を作成する際にこれらの StorageClass を指定することで、用途にあった PD タイプ(pd-standard or pd-ssd)で PV を確保できます。

VolumeBindingMode

VolumeBindingMode は PVC が作成されたあとにどのタイミングで PV とバインドするかをコントロールする仕組みです。

kubernetes.io

Immediate モードの場合には、PVC 作成後すぐに PV のバインディングとプロビジョニングが行われます。

WaitForFirstConsumer モードの場合には、PVC 作成後、Podが作成されるまではバインディングとプロビジョニングは行われません。

Dynamic Provisioning と VolumeBindingMode の関係

きちんと手元で検証したわけではないですが、以下のような動きになると思います。間違っていたらすみません。

Dynamic Provisioning VolumeBindingMode PVC 作成後の動作
Immediate 即時 PV が払い出されバインドされる。
WaitForFirstConsumer PV は払い出されない。
PVC を利用する Pod がスケジュールされるタイミングで PV が払い出されバインドされる。
Immediate PV は手動で作成する。
PVC と PV は条件が合うものが見つかり次第即時バインドされる。
WaitForFirstConsumer PV は手動で作成する。
PVC を利用する Pod がスケジュールされるタイミングで PV と PVC がバインドされる。

※手動というのはあくまでも「Dynamic Provisioning の機能を使わない」という意味です。

ローカルストレージの場合(no-provisioner)

ローカルボリュームの場合には Dynamic Provisioning はサポートされません。provisioner として no-provisioner を指定します。

example-sc-local.yaml

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

とりあえず今日はここまでにします。ありがとうございました。