PersistentVolumeはクラスタ内のストレージ・リソースの一部で、管理者がアクティブに作成して提供するか、StorageClassを使用して動的に提供します。ノード・リソースと同様に、どのネームスペースにも属さず、独自の独立したライフサイクルを持ちます。ユーザは、PersistentVolumeClaimを介してストレージ・リソースを要求します。
ライフサイクル
Kubernetesクラスタでは、PVはストレージリソースとして存在し、PodはPVCを通じてPVを利用します。PVとPVCの相互作用には独自のライフサイクルがあり、5つのフェーズに分けられます:
- プロビジョニング:直接またはStorageClassを使用してPVを作成します;
- Binding: PV を PVC に割り当てます;
- 使用法:ポッドはPVCを通してこのボリュームを使用します;
- リリース:ポッドはボリュームをリリースし、PVCを取り外します;
- Recycle:PVをリサイクルすることで、次回使用するためにPVを保存したり、クラウドストレージから直接PVを削除することができます;
上記の5つのフェーズに基づき、ストレージボリュームには以下の4つの状態が存在します:
- Available:使用可能状態。この状態は、PVがPVCによって使用可能な状態であることを示します;
- Bound:PVがPVCに割り当てられていることを示すバウンド状態;
- リリース済み:PVをアンバンドリングしているが、まだリサイクル方針を実施していないことを示すリリース状態;
- Failed: PV でエラーが発生したことを示すエラーステータス;
供給
プロビジョニングとは、クラスタで利用可能なストレージボリュームのプロビジョニングのことで、Kubernetesでは永続的なストレージボリュームのプロビジョニングに静的と動的の2つの方法があります。
スタティック
PVはKubernetesクラスタ管理者が作成するもので、Podが実ストレージとして利用できる実ストレージを表します。静的プロビジョニングの場合、クラスタ管理者があらかじめPVを作成し、開発者がPVCとPodを作成し、PodはPVが提供するストレージをPVCを通じて利用します。スタティック・プロビジョニングのプロセスを下図に示します:
ダイナミック
動的プロビジョニングの場合、管理者が作成した静的PVの中にユーザのPVCに一致するものがない場合、クラスタはStorageClassに基づいてPVC用のストレージ・ボリュームを自動的にプロビジョニングしようとします。クラスタ管理者は、API-ServerでDefaultStorageClassコントローラを有効にする必要があります。ダイナミック・プロビジョニング・プロセスを次の図に示します:
バウンド
Kubernetesは利用可能なPVに動的にPVCをバインドし、PVが新しいPVCに動的にプロビジョニングされることがあれば、PVCのバインドは排他的になります。さらに、ユーザは常に要求したストレージを取得しますが、ボリュームが要求を超える可能性があります。一度バインドされたPVCバインディングは、バインドモードに関係なく排他的です。
例えば、クラスタ内に50GのPVが多数存在する場合でも、100Gの容量を必要とするPVCは要件を満たすPVとマッチングされず、クラスタ内に100GのPVが存在するまでPVCはバインドされません。以下の条件が同時に存在する場合は、すべての条件を満たすPVがバインド対象として選択されます。
PVCがストレージクラスを指定した場合、同じストレージクラスが指定されたPVのみがバインドされます;
PVCがセレクタを設定すると、セレクタは適合するPVと一致します。
ストレージクラスを指定せずにピッカーを設定した場合、PVCはストレージ容量サイズとアクセスパターンに基づいて適合するPVをマッチングします。
そのため
PodはPVCをボリュームとして使用し、クラスタはPVCを通じてバインドされたPVを検索してPodにマウントします。複数のアクセス方法をサポートするボリュームの場合、ユーザーはPVCをボリュームとして使用するときに必要なアクセス方法を指定できます。ユーザーがバインドされたPVCを所有すると、バインドされたPVはそのユーザーが所有することになります。ユーザーは、Podのストレージ・ボリュームに含まれるPVCを通じて占有PVにアクセスできます。
4 リリース
PVCの削除後、対応する永続ストレージボリュームは "解放 "とみなされますが、この時点で他のPVCに使用することはできません。PVC削除後、対応する永続ストレージボリュームは「解放」とみなされますが、他のPVCに使用することはできません。
リサイクル
PVのreclaimポリシーは、PVCがボリュームを解放したときにクラスタに何をするかを記述します。現在使用できるポリシーは、reservation、reclaimed、deletedの3種類です。予約ポリシーでは、このリソースを再要求できます。削除ポリシーは、PVCがサポートできる場合、AWS EBS/GCE PDまたはCinderボリューム内のボリュームとストレージの内容の両方を削除します。プラグインがサポートできる場合、reclaimポリシーはベース消去操作を実行し、このボリュームを再要求できます。
予約済み
予約再利用ポリシーでは、リソースの手動再利用が可能です。PVCが削除されると、PVは既存のデータを保存し続け、ストレージボリュームは解放状態になりますが、他のPVCからは利用できないままです。管理者は、以下の手順でストレージボリュームを手動で再要求できます:
PV削除:PVを削除しても、関連するストレージ資産は外部施設に残ります;
外部ストレージに残っているデータを手動で削除します;
ストレージ資産を再利用する必要がある場合は、手動で削除し、新しいPVを作成します;
サイクル
この戦略は廃止され、その後はダイナミック・プロビジョニング・モデルを使用することが推奨されます。
サイクリック・リサイクルは、ストレージ・ボリューム上で基本的な消去コマンドrm -rf /thevolume/を実行し、新しいPVCがデータを利用できるようにします。
削除
削除再利用ポリシーをサポートするストレージボリュームプラグインの場合、削除によってPVはKubernetesから削除され、AWS EBS、GCE PD、Azure Disk、Cinder Storage Volumesなどの関連する外部ファシリティからもストレージ資産が削除されます。
永続ストレージボリュームの作成
永続ボリュームPVを作成する際には、実際のストレージタイプを指定する必要があります。このタイプはプラグインとして実装されており、現在以下のプラグインがサポートされています:
- GCEPersistentDisk
- AWSElasticBlockStore
- アズールファイル
- アジュールディスク
- CSI
- FC
- フレックスボリューム
- Flocker
- ネットワークファイルシステム
- iSCSI
- アールビーディー
- CephFS
- Cinder
- Glusterfs
- VsphereVolume
- クオバイトボリューム
- HostPath
- ポートワークスボリューム
- ScaleIO Volumes
- ストレージOS
以下は永続ボリュームの宣言的なYAML構成ファイルです。この構成ファイルでは、ストレージスペースが要求され、ストレージモードが *Filesystem で、* アクセスモードが *、永続ストレージボリュームが reclaim ポリシーによってリクレイムされ、ストレージクラスが指定され、プラグインタイプが使用されます。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv
spec:
capacity: #容量
storage: 5Gi
volumeMode: Filesystem #ボリューム・モード
accessModes: #アクセス・モード
- ReadWriteOnce
persistentVolumeReclaimPolicy: Recycle #永続ボリューム回復ポリシー
storageClassName: slow #
mountOptions: #フックアップオプション
- hard
- nfsvers=4.1
nfs:
path:/tmp
server:.2
容量
PVは、capcity属性でストレージ容量を指定する必要があります。
ストレージ・ボリューム・モード
Kubernetesv1.9以降では、ファイルシステムに加えてブロックデバイスもサポートするvolumeModeの値を指定できます。
アクセス方法
アクセスモードのオプション範囲は以下の通りです:
- ReadWriteOnce:単一ノードのマウントにのみ読み取りと書き込みを許可します;
- ReadOnlyMany: 複数のノードをマウントし、読み取り専用にすることができます;
- ReadWriteMany: 読み書きのための複数のノードマウントを許可します;
特定のストレージボリュームプラグインが複数のアクセスモードをサポートしていても、一 度に設定できるアクセスモードは1つだけです。以下は、各ストレージボリュームプラグインでサポートされているアクセスモードの一覧です:
クラス
StorageClassリソース・オブジェクトの名前であるストレージ・クラスは、storageClassName属性で指定します。特定のクラスを持つPVは、そのクラスを要求するPVCにのみバインドできます。
リサイクル
現在のリサイクル戦略のオプション値は以下の通りです:
- 保持 -- 永続ボリュームはリリース後もデータを保持するため、手動での再要求操作が必要です;
- Recycle ・・・PVC削除後、ベース消去コマンドrm-rf /thevolume/*を実行;
- Delete -- PVCを削除すると、PVに関連付けられた保存データが削除されます;
取り付けパラメータ
PVをノードにマウントする際、追加のマウントパラメータを設定する必要がある場合があります。ただし、マウントパラメータをサポートしているのは以下のストレージボリュームタイプのみです:
- GCEPersistentDisk
- AWSElasticBlockStore
- アズールファイル
- アジュールディスク
- ネットワークファイルシステム
- FC
- アールビーディー
- Flocker
- NFS
- iSCSI
- VsphereVolume
- クオバイトボリューム
- VMware Photon
永続的ボリュームステートメント
以下は、永続ボリューム宣言YAML構成ファイルで、名前は、アクセス・モードは、ストレージ・ボリューム・スキーマは、必要なストレージ・サイズは、指定されたストレージ・クラスは、ラベル・セレクタと一致式が設定されています。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc
spec:
accessModes: #アクセス・モード
- ReadWriteOnce
volumeMode: Filesystem #ボリューム・モード
resources: #
requests:
storage: 8Gi
storageClassName: slow #
selector: #
matchLabels:
release: "stable"
matchExpressions: #マッチ式
- {key: environment, operator: In, values: [dev]}
セレクタ
PVCでは、PVをラベルセレクタでさらにフィルタリングすることができます。セレクタには2つのタイプがあります:
- matchLabels: ここと同じラベルを持つPVだけがPVCによって選択されます;
- matchExpressions: マッチ式はキー、値、演算子で構成され、演算子には and が含まれます;
とandの両方が設定されている場合、合計が実行されます。つまり、上記の両方のマッチング要件を満たすPVのみが選択されます。
クラス
ラベルによるPVのフィルタリングに加え、storageClassName属性でストレージクラスを指定することができ、PVはこのストレージクラスでなければPVCにバインドできません。
ポッドでのPVCの使用
PodはPVCを使用してPVにアクセスします。PVCはクラスタ内の適切なPVにバインドし、PVをホストとPodにマウントします。
kind: Pod
apiVersion: v1
metadata:
name: mypod
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- mountPath: "/var/www/html"
name: mypd # マウントされているボリューム名
volumes:
- name: mypd
persistentVolumeClaim:
claimName: myclaim # PVC
ローカル永続ストレージ
ローカル永続ストレージは、Podが実行されているホスト上のデータのストレージであり、Podがローカル永続ストレージを持つノードにディスパッチされるようにする必要があります。
なぜこのようなストレージが必要なのでしょうか?アプリケーションのディスクIOに対する要求が高く、ネットワークストレージのパフォーマンスがローカルほど高くないことがあります。
非ローカル永続ストレージのシナリオでは、まずPVが作成され、次にPVCが作成され、一致すれば自動的にバインドされます。動的なPV作成の場合でも、まずPodがノードにディスパッチされ、次にPVCに従ってPVが作成され、最後にPodにバインドされます。
しかし、ローカル永続ストレージの問題点として、PVを事前に用意する必要があり、すべてのクラスタノードがPVを持っているわけではないので、Podを自由にディスパッチできないことが挙げられます。では、PVを持つノードに確実にPodをディスパッチするにはどうすればよいでしょうか。この場合、PVでノードアフィニティを宣言し、Podのスケジューリング時にボリュームの分散も考慮する必要があります。
- ノード上に/data/vol1ディレクトリがあっても、nodeAffinity属性がアフィニティホストを設定するため、PVは必ずしもそこにあるとは限りません。
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 5Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local: # local
path: /data/vol1 # ノード上の特定のパス
nodeAffinity: # ここでノード・アフィニティを設定する。
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node01 # ここではnode01ノードを使用する。/data/vol1
- ストレージクラスを定義します:
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
この設定はPVへのPVCバインディングのタイミングに影響し、指定したPVCを使用する最初のPodが発生したときにのみPVにバインドされます。
- PVCを定義します:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: local-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: local-storage
PVCは状態であり、ポッドがまだ存在しないため、遅延バインディングであることがわかります。
- Podを定義します:
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat-deploy
spec:
replicas: 1
selector:
matchLabels:
appname: myapp
template:
metadata:
name: myapp
labels:
appname: myapp
spec:
containers:
- name: myapp
image: tomcat:8.5.38-jre8
ports:
- name: http
containerPort: 8080
protocol: TCP
volumeMounts:
- name: tomcatedata
mountPath : "/data"
volumes:
- name: tomcatedata
persistentVolumeClaim:
claimName: local-claim
この時点でPVはノード上にあるため、Podはそのノードにディスパッチされ、Podが作成される前に削除されても、そのノードにディスパッチされます。また、PVCはすでにバインドされた状態になっています。





