CKA受験勉強時にはStorageClassについて全くと言っていいほど知らなかった(なんかあるなぁって感じ)のですが、CKAD受験に向けて基本のキを知ったのでメモします。
- StorageClass
- Dynamic Provisioning
- VolumeBindingMode
- Dynamic Provisioning と VolumeBindingMode の関係
- ローカルストレージの場合(no-provisioner)
StorageClass
ストレージの実体をどのようにプロビジョニングするかの定義的なものと理解しました。
主なフィールドは以下の通りです。
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 を使うためには基本的には以下の流れでリソースを作成していきます。
- StorageClass 作成
- PV 作成 ※
- PVC 作成 ※
- 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 です。
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 とバインドするかをコントロールする仕組みです。
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
とりあえず今日はここまでにします。ありがとうございました。