ボリューム
コンテナ内のディスク上のファイルは一時的なものであり、コンテナ内で実行する場合、重要なアプリケーションでいくつかの問題が発生します。1つの問題は、コンテナがクラッシュしたときにファイルが失われることです。kubeletはコンテナを再起動しますが、クリーンな状態です。
2番目の問題は、Pod
で一緒に実行されているコンテナ間でファイルを共有するときに発生します。
Kubernetesボリュームの抽象化は、これらの問題の両方を解決します。
Podに精通していることをお勧めします。
背景
Dockerにはボリュームの概念がありますが、多少緩く、管理も不十分です。Dockerボリュームは、ディスク上または別のコンテナ内のディレクトリです。Dockerはボリュームドライバーを提供しますが、機能は多少制限されています。
Kubernetesは多くの種類のボリュームをサポートしています。 Podは任意の数のボリュームタイプを同時に使用できます。 エフェメラルボリュームタイプにはPodの存続期間がありますが、永続ボリュームはPodの存続期間を超えて存在します。 Podが存在しなくなると、Kubernetesはエフェメラルボリュームを破棄します。ただしKubernetesは永続ボリュームを破棄しません。 特定のPod内のあらゆる種類のボリュームについて、データはコンテナの再起動後も保持されます。
コアとなるボリュームはディレクトリであり、Pod内のコンテナからアクセスできるデータが含まれている可能性があります。 ディレクトリがどのように作成されるか、それをバックアップするメディア、およびそのコンテンツは、使用する特定のボリュームタイプによって決まります。
ボリュームを使用するには、.spec.volumes
でPodに提供するボリュームを指定し、.spec.containers[*].volumeMounts
でそれらのボリュームをコンテナにマウントする場所を宣言します。
コンテナ内のプロセスはコンテナイメージの初期コンテンツと、コンテナ内にマウントされたボリューム(定義されている場合)で構成されるファイルシステムビューを確認します。
プロセスは、コンテナイメージのコンテンツと最初に一致するルートファイルシステムを確認します。
そのファイルシステム階層内への書き込みは、もし許可されている場合、後続のファイルシステムアクセスを実行するときにそのプロセスが表示する内容に影響します。
ボリュームはイメージ内の指定されたパスへマウントされます。
Pod内で定義されたコンテナごとに、コンテナが使用する各ボリュームをマウントする場所を個別に指定する必要があります。
ボリュームは他のボリューム内にマウントできません(ただし、関連するメカニズムについては、subPathの使用を参照してください)。 またボリュームには、別のボリューム内の何かへのハードリンクを含めることはできません。
ボリュームの種類
Kubernetesはいくつかのタイプのボリュームをサポートしています。
awsElasticBlockStore
awsElasticBlockStore
ボリュームは、Amazon Web Services(AWS)EBSボリュームをPodにマウントします。
Podを削除すると消去されるemptyDir
とは異なり、EBSボリュームのコンテンツは保持されたままボリュームはアンマウントされます。
これは、EBSボリュームにデータを事前入力でき、データをPod間で共有できることを意味します。
aws ec2 create-volume
またはAWSAPIを使用してEBSボリュームを作成する必要があります。awsElasticBlockStore
ボリュームを使用する場合、いくつかの制限があります。
- Podが実行されているノードはAWS EC2インスタンスである必要があります
- これらのインスタンスは、EBSボリュームと同じリージョンおよびアベイラビリティーゾーンにある必要があります
- EBSは、ボリュームをマウントする単一のEC2インスタンスのみをサポートします
AWS EBSボリュームの作成
PodでEBSボリュームを使用する前に作成する必要があります。
aws ec2 create-volume --availability-zone=eu-west-1a --size=10 --volume-type=gp2
ゾーンがクラスターを立ち上げたゾーンと一致していることを確認してください。サイズとEBSボリュームタイプが使用に適していることを確認してください。
AWS EBS設定例
apiVersion: v1
kind: Pod
metadata:
name: test-ebs
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-ebs
name: test-volume
volumes:
- name: test-volume
# This AWS EBS volume must already exist.
awsElasticBlockStore:
volumeID: "<volume id>"
fsType: ext4
EBSボリュームがパーティション化されている場合は、オプションのフィールドpartition: "<partition number>"
を指定して、マウントするパーティションを指定できます。
AWS EBS CSIの移行
Kubernetes v1.17 [beta]
awsElasticBlockStore
のCSIMigration
機能を有効にすると、すべてのプラグイン操作が既存のツリー内プラグインからebs.csi.aws.com
Container Storage Interface(CSI)ドライバーにリダイレクトされます。
この機能を使用するには、AWS EBS CSIドライバーがクラスターにインストールされ、CSIMigration
とCSIMigrationAWS
のbeta機能が有効になっている必要があります。
AWS EBS CSIの移行の完了
Kubernetes v1.17 [alpha]
awsElasticBlockStore
ストレージプラグインがコントローラーマネージャーとkubeletによって読み込まれないようにするには、InTreePluginAWSUnregister
フラグをtrue
に設定します。
azureDisk
azureDisk
ボリュームタイプは、MicrosoftAzureデータディスクをPodにマウントします。
詳細については、azureDisk
ボリュームプラグインを参照してください。
azureDisk CSIの移行
Kubernetes v1.19 [beta]
azureDisk
のCSIMigration
機能を有効にすると、すべてのプラグイン操作が既存のツリー内プラグインからdisk.csi.azure.com
Container Storage Interface(CSI)ドライバーにリダイレクトされます。
この機能を利用するには、クラスターにAzure Disk CSI Driverをインストールし、CSIMigration
およびCSIMigrationAzureDisk
機能を有効化する必要があります。
azureFile
azureFile
ボリュームタイプは、Microsoft Azureファイルボリューム(SMB 2.1および3.0)をPodにマウントします。
詳細についてはazureFile
volume pluginを参照してください。
azureFile CSIの移行
Kubernetes v1.21 [beta]
zureFile
のCSIMigration
機能を有効にすると、既存のツリー内プラグインからfile.csi.azure.com
Container Storage Interface(CSI)Driverへすべてのプラグイン操作がリダイレクトされます。
この機能を利用するには、クラスターにAzure File CSI Driverをインストールし、CSIMigration
およびCSIMigrationAzureFile
フィーチャーゲートを有効化する必要があります。
Azure File CSIドライバーは、異なるfsgroupで同じボリュームを使用することをサポートしていません。AzurefileCSIの移行が有効になっている場合、異なるfsgroupで同じボリュームを使用することはまったくサポートされません。
cephfs
cephfs
ボリュームを使用すると、既存のCephFSボリュームをPodにマウントすることができます。
Podを取り外すと消去されるemptyDir
とは異なり、cephfs
ボリュームは内容を保持したまま単にアンマウントされるだけです。
つまりcephfs
ボリュームにあらかじめデータを入れておき、そのデータをPod間で共有することができます。
cephfs
ボリュームは複数の書き込み元によって同時にマウントすることができます。
詳細についてはCephFSの例を参照してください。
cinder
cinder
ボリュームタイプは、PodにOpenStackのCinderのボリュームをマウントするために使用されます。
Cinderボリュームの設定例
apiVersion: v1
kind: Pod
metadata:
name: test-cinder
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-cinder-container
volumeMounts:
- mountPath: /test-cinder
name: test-volume
volumes:
- name: test-volume
# This OpenStack volume must already exist.
cinder:
volumeID: "<volume id>"
fsType: ext4
OpenStack CSIの移行
Kubernetes v1.21 [beta]
CinderのCSIMigration
機能は、Kubernetes1.21ではデフォルトで有効になっています。
既存のツリー内プラグインからのすべてのプラグイン操作をcinder.csi.openstack.org
Container Storage Interface(CSI) Driverへリダイレクトします。
OpenStack Cinder CSIドライバーをクラスターにインストールする必要があります。
CSIMigrationOpenStack
フィーチャーゲートをfalse
に設定すると、クラスターのCinder CSIマイグレーションを無効化することができます。
CSIMigrationOpenStack
機能を無効にすると、ツリー内のCinderボリュームプラグインがCinderボリュームのストレージ管理のすべての側面に責任を持つようになります。
configMap
ConfigMapは構成データをPodに挿入する方法を提供します。
ConfigMapに格納されたデータは、タイプconfigMap
のボリュームで参照され、Podで実行されているコンテナ化されたアプリケーションによって使用されます。
ConfigMapを参照するときは、ボリューム内のConfigMapの名前を指定します。
ConfigMapの特定のエントリに使用するパスをカスタマイズできます。
次の設定は、log-config
ConfigMapをconfigmap-pod
というPodにマウントする方法を示しています。
apiVersion: v1
kind: Pod
metadata:
name: configmap-pod
spec:
containers:
- name: test
image: busybox
volumeMounts:
- name: config-vol
mountPath: /etc/config
volumes:
- name: config-vol
configMap:
name: log-config
items:
- key: log_level
path: log_level
log-config
ConfigMapはボリュームとしてマウントされ、そのlog_level
エントリに格納されているすべてのコンテンツは、パス/etc/config/log_level
のPodにマウントされます。
このパスはボリュームのmountPath
とlog_level
をキーとするpath
から派生することに注意してください。
downwardAPI
downwardAPI
ボリュームは、アプリケーションへのdownward APIデータを利用できるようになります。ディレクトリをマウントし、要求されたデータをプレーンテキストファイルに書き込みます。
subPath
ボリュームマウントとしてdownward APIを使用するコンテナは、downward APIの更新を受け取りません。詳細についてはdownward API exampleを参照してください。
emptyDir
emptyDir
ボリュームはPodがノードに割り当てられたときに最初に作成され、そのPodがそのノードで実行されている限り存在します。
名前が示すようにemptyDir
ボリュームは最初は空です。
Pod内のすべてのコンテナはemptyDir
ボリューム内の同じファイルを読み書きできますが、そのボリュームは各コンテナで同じパスまたは異なるパスにマウントされることがあります。
何らかの理由でPodがノードから削除されると、emptyDir
内のデータは永久に削除されます。
emptyDir
ボリューム内のデータは、コンテナのクラッシュしても安全です。emptyDir
のいくつかの用途は次の通りです。
- ディスクベースのマージソートなどのスクラッチスペース
- クラッシュからの回復のための長い計算のチェックポイント
- Webサーバーコンテナがデータを提供している間にコンテンツマネージャコンテナがフェッチするファイルを保持する
環境に応じて、emptyDir
ボリュームは、ディスクやSSD、ネットワークストレージなど、ノードをバックアップするあらゆる媒体に保存されます。
ただし、emptyDir.medium
フィールドを"Memory"
に設定すると、Kubernetesは代わりにtmpfs(RAMベースのファイルシステム)をマウントします。
tmpfsは非常に高速ですが、ディスクと違ってノードのリブート時にクリアされ、書き込んだファイルはコンテナのメモリー制限にカウントされることに注意してください。
SizeMemoryBackedVolumes
フィーチャーゲートが有効な場合、メモリーバックアップボリュームにサイズを指定することができます。
サイズが指定されていない場合、メモリーでバックアップされたボリュームは、Linuxホストのメモリーの50%のサイズになります。emptyDirの設定例
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /cache
name: cache-volume
volumes:
- name: cache-volume
emptyDir: {}
fc (fibre channel)
fc
ボリュームタイプを使用すると、既存のファイバーチャネルブロックストレージボリュームをPodにマウントできます。
targetWWNs
ボリューム構成のパラメーターを使用して、単一または複数のターゲットWorld Wide Name(WWN)を指定できます。
複数のWWNが指定されている場合、targetWWNは、それらのWWNがマルチパス接続からのものであると想定します。
詳細についてはfibre channelの例を参照してください。
flocker (非推奨)
Flockerはオープンソースのクラスター化されたコンテナデータボリュームマネージャーです。 Flockerは、さまざまなストレージバックエンドに支えられたデータボリュームの管理とオーケストレーションを提供します。
flocker
ボリュームを使用すると、FlockerデータセットをPodにマウントできます。
もしデータセットがまだFlockerに存在しない場合は、まずFlocker CLIかFlocker APIを使ってデータセットを作成する必要があります。
データセットがすでに存在する場合は、FlockerによってPodがスケジュールされているノードに再アタッチされます。
これは、必要に応じてPod間でデータを共有できることを意味します。
詳細についてはFlocker exampleを参照してください。
gcePersistentDisk
gcePersistentDisk
ボリュームは、Google Compute Engine (GCE)の永続ディスク(PD)をPodにマウントします。
Podを取り外すと消去されるemptyDir
とは異なり、PDの内容は保持されボリュームは単にアンマウントされるだけです。これはPDにあらかじめデータを入れておくことができ、そのデータをPod間で共有できることを意味します。
gcloud
を使用する前に、またはGCE APIまたはUIを使用してPDを作成する必要があります。gcePersistentDisk
を使用する場合、いくつかの制限があります。
- Podが実行されているノードはGCE VMである必要があります
- これらのVMは、永続ディスクと同じGCEプロジェクトおよびゾーンに存在する必要があります
GCE永続ディスクの機能の1つは、永続ディスクへの同時読み取り専用アクセスです。gcePersistentDisk
ボリュームを使用すると、複数のコンシューマーが永続ディスクを読み取り専用として同時にマウントできます。
これはPDにデータセットを事前入力してから、必要な数のPodから並行して提供できることを意味します。
残念ながらPDは読み取り/書き込みモードで1つのコンシューマーのみがマウントできます。同時書き込みは許可されていません。
PDが読み取り専用であるか、レプリカ数が0または1でない限り、ReplicaSetによって制御されるPodでGCE永続ディスクを使用すると失敗します。
GCE永続ディスクの作成
PodでGCE永続ディスクを使用する前に、それを作成する必要があります。
gcloud compute disks create --size=500GB --zone=us-central1-a my-data-disk
GCE永続ディスクの設定例
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
# This GCE PD must already exist.
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
リージョン永続ディスク
リージョン永続ディスク機能を使用すると、同じリージョン内の2つのゾーンで使用できる永続ディスクを作成できます。 この機能を使用するには、ボリュームをPersistentVolumeとしてプロビジョニングする必要があります。Podから直接ボリュームを参照することはサポートされていません。
リージョンPD PersistentVolumeを手動でプロビジョニングする
GCE PDのStorageClassを使用して動的プロビジョニングが可能です。 SPDPersistentVolumeを作成する前に、永続ディスクを作成する必要があります。
gcloud compute disks create --size=500GB my-data-disk
--region us-central1
--replica-zones us-central1-a,us-central1-b
リージョン永続ディスクの設定例
apiVersion: v1
kind: PersistentVolume
metadata:
name: test-volume
spec:
capacity:
storage: 400Gi
accessModes:
- ReadWriteOnce
gcePersistentDisk:
pdName: my-data-disk
fsType: ext4
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
# failure-domain.beta.kubernetes.io/zone should be used prior to 1.21
- key: topology.kubernetes.io/zone
operator: In
values:
- us-central1-a
- us-central1-b
GCE CSIの移行
Kubernetes v1.17 [beta]
GCE PDのCSIMigration
機能を有効にすると、すべてのプラグイン操作が既存のツリー内プラグインからpd.csi.storage.gke.io
Container Storage Interface (CSI) Driverにリダイレクトされるようになります。
この機能を使用するには、クラスターにGCE PD CSI Driverがインストールされ、CSIMigration
とCSIMigrationGCE
のbeta機能が有効になっている必要があります。
GCE CSIの移行の完了
Kubernetes v1.21 [alpha]
gcePersistentDisk
ストレージプラグインがコントローラーマネージャーとkubeletによって読み込まれないようにするには、InTreePluginGCEUnregister
フラグをtrue
に設定します。
gitRepo(非推奨)
gitRepo
ボリュームタイプは非推奨です。gitリポジトリを使用してコンテナをプロビジョニングするには、Gitを使用してリポジトリのクローンを作成するInitContainerにEmptyDirをマウントしてから、PodのコンテナにEmptyDirをマウントします。gitRepo
ボリュームは、ボリュームプラグインの一例です。このプラグインは空のディレクトリをマウントし、そのディレクトリにgitリポジトリをクローンしてPodで使えるようにします。
gitRepo
ボリュームの例を次に示します。
apiVersion: v1
kind: Pod
metadata:
name: server
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /mypath
name: git-volume
volumes:
- name: git-volume
gitRepo:
repository: "git@somewhere:me/my-git-repository.git"
revision: "22f1d8406d464b0c0874075539c1f2e96c253775"
glusterfs
glusterfs
ボリュームはGlusterfs(オープンソースのネットワークファイルシステム)ボリュームをPodにマウントできるようにするものです。
Podを取り外すと消去されるemptyDir
とは異なり、glusterfs
ボリュームの内容は保持され、単にアンマウントされるだけです。
これは、glusterfsボリュームにデータを事前に入力でき、データをPod間で共有できることを意味します。
GlusterFSは複数のライターが同時にマウントすることができます。
詳細についてはGlusterFSの例を参照してください。
hostPath
HostPathボリュームには多くのセキュリティリスクがあり、可能な場合はHostPathの使用を避けることがベストプラクティスです。HostPathボリュームを使用する必要がある場合は、必要なファイルまたはディレクトリのみにスコープを設定し、読み取り専用としてマウントする必要があります。
AdmissionPolicyによって特定のディレクトリへのHostPathアクセスを制限する場合、ポリシーを有効にするためにvolumeMounts
はreadOnly
マウントを使用するように要求されなければなりません。
hostPath
ボリュームは、ファイルまたはディレクトリをホストノードのファイルシステムからPodにマウントします。
これはほとんどのPodに必要なものではありませんが、一部のアプリケーションには強力なエスケープハッチを提供します。
たとえばhostPath
のいくつかの使用法は次のとおりです。
- Dockerの内部にアクセスする必要があるコンテナを実行する場合:
hostPath
に/var/lib/docker
を使用します。 - コンテナ内でcAdvisorを実行する場合:
hostPath
に/sys
を指定します。 - Podが実行される前に、与えられた
hostPath
が存在すべきかどうか、作成すべきかどうか、そして何として存在すべきかを指定できるようにします。
必須のpath
プロパティに加えて、オプションでhostPath
ボリュームにtype
を指定することができます。
フィールドtype
でサポートされている値は次のとおりです。
値 | ふるまい |
---|---|
空の文字列(デフォルト)は下位互換性のためです。つまり、hostPathボリュームをマウントする前にチェックは実行されません。 | |
DirectoryOrCreate | 指定されたパスに何も存在しない場合、必要に応じて、権限を0755に設定し、Kubeletと同じグループと所有権を持つ空のディレクトリが作成されます。 |
Directory | 指定されたパスにディレクトリが存在する必要があります。 |
FileOrCreate | 指定されたパスに何も存在しない場合、必要に応じて、権限を0644に設定し、Kubeletと同じグループと所有権を持つ空のファイルが作成されます。 |
File | 指定されたパスにファイルが存在する必要があります。 |
Socket | UNIXソケットは、指定されたパスに存在する必要があります。 |
CharDevice | キャラクターデバイスは、指定されたパスに存在する必要があります。 |
BlockDevice | ブロックデバイスは、指定されたパスに存在する必要があります。 |
このタイプのボリュームを使用するときは、以下の理由のため注意してください。
- HostPath は、特権的なシステム認証情報(Kubeletなど)や特権的なAPI(コンテナランタイムソケットなど)を公開する可能性があり、コンテナのエスケープやクラスターの他の部分への攻撃に利用される可能性があります。
- 同一構成のPod(PodTemplateから作成されたものなど)は、ノード上のファイルが異なるため、ノードごとに動作が異なる場合があります。
- ホスト上に作成されたファイルやディレクトリは、rootでしか書き込みができません。特権コンテナ内でrootとしてプロセスを実行するか、ホスト上のファイルのパーミッションを変更して
hostPath
ボリュームに書き込みができるようにする必要があります。
hostPathの設定例
apiVersion: v1
kind: Pod
metadata:
name: test-pd
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-pd
name: test-volume
volumes:
- name: test-volume
hostPath:
# directory location on host
path: /data
# this field is optional
type: Directory
FileOrCreate
モードでは、ファイルの親ディレクトリは作成されません。マウントされたファイルの親ディレクトリが存在しない場合、Podは起動に失敗します。
このモードが確実に機能するようにするには、FileOrCreate
構成に示すように、ディレクトリとファイルを別々にマウントしてみてください。hostPath FileOrCreateの設定例
apiVersion: v1
kind: Pod
metadata:
name: test-webserver
spec:
containers:
- name: test-webserver
image: k8s.gcr.io/test-webserver:latest
volumeMounts:
- mountPath: /var/local/aaa
name: mydir
- mountPath: /var/local/aaa/1.txt
name: myfile
volumes:
- name: mydir
hostPath:
# Ensure the file directory is created.
path: /var/local/aaa
type: DirectoryOrCreate
- name: myfile
hostPath:
path: /var/local/aaa/1.txt
type: FileOrCreate
iscsi
iscsi
ボリュームは、既存のiSCSI(SCSI over IP)ボリュームをPodにマウントすることができます。
Podを取り外すと消去されるemptyDir
とは異なり、iscsi
ボリュームの内容は保持され、単にアンマウントされるだけです。
つまり、iscsiボリュームにはあらかじめデータを入れておくことができ、そのデータをPod間で共有することができるのです。
iSCSIの特徴として、複数のコンシューマーから同時に読み取り専用としてマウントできることが挙げられます。 つまり、ボリュームにあらかじめデータセットを入れておき、必要な数のPodから並行してデータを提供することができます。 残念ながら、iSCSIボリュームは1つのコンシューマによってのみ読み書きモードでマウントすることができます。 同時に書き込みを行うことはできません。
詳細についてはiSCSIの例を参照してください。
local
local
ボリュームは、ディスク、パーティション、ディレクトリなど、マウントされたローカルストレージデバイスを表します。
ローカルボリュームは静的に作成されたPersistentVolumeとしてのみ使用できます。動的プロビジョニングはサポートされていません。
hostPath
ボリュームと比較して、local
ボリュームは手動でノードにPodをスケジューリングすることなく、耐久性と移植性に優れた方法で使用することができます。
システムはPersistentVolume上のノードアフィニティーを見ることで、ボリュームのノード制約を認識します。
ただし、local
ボリュームは、基盤となるノードの可用性に左右されるため、すべてのアプリケーションに適しているわけではありません。
ノードが異常になると、Podはlocal
ボリュームにアクセスできなくなります。
このボリュームを使用しているPodは実行できません。local
ボリュームを使用するアプリケーションは、基盤となるディスクの耐久性の特性に応じて、この可用性の低下と潜在的なデータ損失に耐えられる必要があります。
次の例では、local
ボリュームとnodeAffinity
を使用したPersistentVolumeを示しています。
apiVersion: v1
kind: PersistentVolume
metadata:
name: example-pv
spec:
capacity:
storage: 100Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /mnt/disks/ssd1
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- example-node
ローカルボリュームを使用する場合は、PersistentVolume nodeAffinity
を設定する必要があります。
KubernetesのスケジューラはPersistentVolume nodeAffinity
を使用して、これらのPodを正しいノードにスケジューリングします。
PersistentVolume volumeMode
を(デフォルト値の「Filesystem」ではなく)「Block」に設定して、ローカルボリュームをrawブロックデバイスとして公開できます。
ローカルボリュームを使用する場合、volumeBindingMode
をWaitForFirstConsumer
に設定したStorageClassを作成することをお勧めします。
詳細については、local StorageClassの例を参照してください。
ボリュームバインディングを遅延させると、PersistentVolumeClaimバインディングの決定が、ノードリソース要件、ノードセレクター、Podアフィニティ、Podアンチアフィニティなど、Podが持つ可能性のある他のノード制約も含めて評価されるようになります。
ローカルボリュームのライフサイクルの管理を改善するために、外部の静的プロビジョナーを個別に実行できます。 このプロビジョナーはまだ動的プロビジョニングをサポートしていないことに注意してください。 外部ローカルプロビジョナーの実行方法の例については、ローカルボリュームプロビジョナーユーザーガイドを参照してください。
nfs
nfs
ボリュームは、既存のNFS(Network File System)共有をPodにマウントすることを可能にします。Podを取り外すと消去されるemptyDir
とは異なり、nfs
ボリュームのコンテンツは保存され、単にアンマウントされるだけです。
つまり、NFSボリュームにはあらかじめデータを入れておくことができ、そのデータをPod間で共有することができます。
NFSは複数のライターによって同時にマウントすることができます。
詳細についてはNFSの例を参照してください。
persistentVolumeClaim
PersistentVolumeClaim
ボリュームはPersistentVolumeをPodにマウントするために使用されます。
PersistentVolumeClaimは、ユーザが特定のクラウド環境の詳細を知らなくても、耐久性のあるストレージ(GCE永続ディスクやiSCSIボリュームなど)を「要求」するための方法です。
詳細についてはPersistentVolumeを参照してください。
portworxVolume
portworxVolume
は、Kubernetesとハイパーコンバージドで動作するエラスティックブロックストレージレイヤーです。
Portworxは、サーバー内のストレージをフィンガープリントを作成し、機能に応じて階層化し、複数のサーバーにまたがって容量を集約します。
Portworxは、仮想マシンまたはベアメタルのLinuxノードでゲスト内動作します。
portworxVolume
はKubernetesを通して動的に作成することができますが、事前にプロビジョニングしてPodの中で参照することもできます。
以下は、事前にプロビジョニングされたPortworxボリュームを参照するPodの例です。
apiVersion: v1
kind: Pod
metadata:
name: test-portworx-volume-pod
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /mnt
name: pxvol
volumes:
- name: pxvol
# This Portworx volume must already exist.
portworxVolume:
volumeID: "pxvol"
fsType: "<fs-type>"
pxvol
という名前の既存のPortworxVolumeがあることを確認してください。詳細についてはPortworxボリュームの例を参照してください。
投影
投影ボリュームは、複数の既存のボリュームソースを同じディレクトリにマッピングします。 詳細については投影ボリュームを参照してください。
quobyte(非推奨)
quobyte
ボリュームは、既存のQuobyteボリュームをPodにマウントすることができます。
CSIは、Kubernetes内部でQuobyteボリュームを使用するための推奨プラグインです。 QuobyteのGitHubプロジェクトには、CSIを使用してQuobyteをデプロイするための手順と例があります
rbd
rbd
ボリュームはRados Block Device(RBD)ボリュームをPodにマウントすることを可能にします。
Podを取り外すと消去されるemptyDir
とは異なり、rbd
ボリュームの内容は保存され、ボリュームはアンマウントされます。つまり、RBDボリュームにはあらかじめデータを入れておくことができ、そのデータをPod間で共有することができるのです。
RBDの特徴として、複数のコンシューマーから同時に読み取り専用としてマウントできることが挙げられます。 つまり、ボリュームにあらかじめデータセットを入れておき、必要な数のPodから並行して提供することができるのです。 残念ながら、RBDボリュームは1つのコンシューマーによってのみ読み書きモードでマウントすることができます。 同時に書き込みを行うことはできません。
詳細についてはRBDの例を参照してください。
RBD CSIの移行
Kubernetes v1.23 [alpha]
RBD
のCSIMigration
機能を有効にすると、既存のツリー内プラグインからrbd.csi.ceph.com
CSIドライバーにすべてのプラグイン操作がリダイレクトされます。
この機能を使用するには、クラスターにCeph CSIドライバーをインストールし、CSIMigration
およびcsiMigrationRBD
フィーチャーゲートを有効にしておく必要があります。
ストレージを管理するKubernetesクラスターオペレーターとして、RBD CSIドライバーへの移行を試みる前に完了する必要のある前提条件は次のとおりです。
- Ceph CSIドライバー(
rbd.csi.ceph.com
)v3.5.0以降をKubernetesクラスターにインストールする必要があります。 - CSIドライバーの動作に必要なパラメーターとして
clusterID
フィールドがありますが、ツリー内StorageClassにはmonitors
フィールドがあるため、Kubernetesストレージ管理者はCSI config mapでモニターハッシュ(例:#echo -n '<monitors_string>' | md5sum
)に基づいたclusterIDを作成し、モニターをこのclusterID設定の下に保持しなければなりません。 - また、ツリー内Storageclassの
adminId
の値がadmin
と異なる場合、ツリー内Storageclassに記載されているadminSecretName
にadminId
パラメーター値のbase64値をパッチしなければなりませんが、それ以外はスキップすることが可能です。
secret
secret
ボリュームは、パスワードなどの機密情報をPodに渡すために使用します。
Kubernetes APIにsecretを格納し、Kubernetesに直接結合することなくPodが使用するファイルとしてマウントすることができます。
secret
ボリュームはtmpfs(RAM-backed filesystem)によってバックアップされるため、不揮発性ストレージに書き込まれることはありません。
SubPath
ボリュームマウントとしてSecretを使用しているコンテナは、Secretの更新を受け取りません。詳細についてはSecretの設定を参照してください。
storageOS(非推奨)
storageos
ボリュームを使用すると、既存のStorageOSボリュームをPodにマウントできます。
StorageOSは、Kubernetes環境内でコンテナとして実行され、Kubernetesクラスター内の任意のノードからローカルストレージまたは接続されたストレージにアクセスできるようにします。 データを複製してノードの障害から保護することができます。シンプロビジョニングと圧縮により使用率を向上させ、コストを削減できます。
根本的にStorageOSは、コンテナにブロックストレージを提供しファイルシステムからアクセスできるようにします。
StorageOS Containerは64ビットLinuxを必要とし、追加の依存関係はありません。 無償の開発者ライセンスが利用可能です。
次の例は、StorageOSを使用したPodの設定です。
apiVersion: v1
kind: Pod
metadata:
labels:
name: redis
role: master
name: test-storageos-redis
spec:
containers:
- name: master
image: kubernetes/redis:v1
env:
- name: MASTER
value: "true"
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /redis-master-data
name: redis-data
volumes:
- name: redis-data
storageos:
# The `redis-vol01` volume must already exist within StorageOS in the `default` namespace.
volumeName: redis-vol01
fsType: ext4
StorageOS、動的プロビジョニング、およびPersistentVolumeClaimの詳細については、StorageOSの例を参照してください。
vsphereVolume
vsphereVolume
は、vSphereVMDKボリュームをPodにマウントするために使用されます。
ボリュームの内容は、マウント解除されたときに保持されます。VMFSとVSANの両方のデータストアをサポートします。
Creating a VMDK volume
次のいずれかの方法を選択して、VMDKを作成します。
最初にESXにSSHで接続し、次に以下のコマンドを使用してVMDKを作成します。
vmkfstools -c 2G /vmfs/volumes/DatastoreName/volumes/myDisk.vmdk
次のコマンドを使用してVMDKを作成します。
vmware-vdiskmanager -c -t 0 -s 40GB -a lsilogic myDisk.vmdk
vSphere VMDKの設定例
apiVersion: v1
kind: Pod
metadata:
name: test-vmdk
spec:
containers:
- image: k8s.gcr.io/test-webserver
name: test-container
volumeMounts:
- mountPath: /test-vmdk
name: test-volume
volumes:
- name: test-volume
# This VMDK volume must already exist.
vsphereVolume:
volumePath: "[DatastoreName] volumes/myDisk"
fsType: ext4
詳細についてはvSphereボリュームの例を参照してください。
vSphere CSIの移行
Kubernetes v1.19 [beta]
vsphereVolume
のCSIMigration
機能を有効にすると、既存のツリー内プラグインからcsi.vsphere.vmware.com
CSIドライバーにすべてのプラグイン操作がリダイレクトされます。
この機能を使用するには、クラスターにvSphere CSIドライバーがインストールされ、CSIMigration
およびCSIMigrationvSphere
フィーチャーゲートが有効になっていなければなりません。
また、vSphere vCenter/ESXiのバージョンが7.0u1以上、HWのバージョンがVM version 15以上であることが条件です。
組み込みのvsphereVolume
プラグインの次のStorageClassパラメーターは、vSphere CSIドライバーでサポートされていません。
diskformat
hostfailurestotolerate
forceprovisioning
cachereservation
diskstripes
objectspacereservation
iopslimit
これらのパラメーターを使用して作成された既存のボリュームはvSphere CSIドライバーに移行されますが、vSphere CSIドライバーで作成された新しいボリュームはこれらのパラメーターに従わないことに注意してください。
vSphere CSIの移行の完了
Kubernetes v1.19 [beta]
vsphereVolume
プラグインがコントローラーマネージャーとkubeletによって読み込まれないようにするには、InTreePluginvSphereUnregister
機能フラグをtrue
に設定する必要があります。すべてのワーカーノードにcsi.vsphere.vmware.com
CSIドライバーをインストールする必要があります。
Portworx CSIの移行
Kubernetes v1.23 [alpha]
PortworxのCSIMigration
機能が追加されましたが、Kubernetes 1.23ではAlpha状態であるため、デフォルトで無効になっています。
すべてのプラグイン操作を既存のツリー内プラグインからpxd.portworx.com
Container Storage Interface(CSI)ドライバーにリダイレクトします。
Portworx CSIドライバーをクラスターにインストールする必要があります。
この機能を有効にするには、kube-controller-managerとkubeletでCSIMigrationPortworx=true
を設定します。
subPathの使用
1つのPodで複数の用途に使用するために1つのボリュームを共有すると便利な場合があります。
volumeMounts.subPath
プロパティは、ルートではなく、参照されるボリューム内のサブパスを指定します。
次の例は、単一の共有ボリュームを使用してLAMPスタック(Linux Apache MySQL PHP)でPodを構成する方法を示しています。
このサンプルのsubPath
構成は、プロダクションでの使用にはお勧めしません。
PHPアプリケーションのコードとアセットはボリュームのhtml
フォルダーにマップされ、MySQLデータベースはボリュームのmysql
フォルダーに保存されます。例えば:
apiVersion: v1
kind: Pod
metadata:
name: my-lamp-site
spec:
containers:
- name: mysql
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpasswd"
volumeMounts:
- mountPath: /var/lib/mysql
name: site-data
subPath: mysql
- name: php
image: php:7.0-apache
volumeMounts:
- mountPath: /var/www/html
name: site-data
subPath: html
volumes:
- name: site-data
persistentVolumeClaim:
claimName: my-lamp-site-data
拡張された環境変数でのsubPathの使用
Kubernetes v1.17 [stable]
subPathExpr
フィールドを使用して、downwart API環境変数からsubPath
ディレクトリ名を作成します。
subPath
プロパティとsubPathExpr
プロパティは相互に排他的です。
この例では、Pod
がsubPathExpr
を使用して、hostPath
ボリューム/var/log/pods
内にpod1
というディレクトリを作成します。
hostPath
ボリュームはdownwardAPI
からPod
名を受け取ります。
ホストディレクトリ/var/log/pods/pod1
は、コンテナ内の/logs
にマウントされます。
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
containers:
- name: container1
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
image: busybox
command: [ "sh", "-c", "while [ true ]; do echo 'Hello'; sleep 10; done | tee -a /logs/hello.txt" ]
volumeMounts:
- name: workdir1
mountPath: /logs
# The variable expansion uses round brackets (not curly brackets).
subPathExpr: $(POD_NAME)
restartPolicy: Never
volumes:
- name: workdir1
hostPath:
path: /var/log/pods
リソース
emptyDir
ボリュームの記憶媒体(DiskやSSDなど)は、kubeletのルートディレクトリ(通常は/var/lib/kubelet
)を保持するファイルシステムの媒体によって決定されます。
emptyDir
またはhostPath
ボリュームが消費する容量に制限はなく、コンテナ間またはPod間で隔離されることもありません。
リソース仕様を使用したスペースの要求については、リソースの管理方法を参照してください。
ツリー外のボリュームプラグイン
ツリー外ボリュームプラグインにはContainer Storage Interface(CSI)、およびFlexVolume(非推奨)があります。 これらのプラグインによりストレージベンダーは、プラグインのソースコードをKubernetesリポジトリに追加することなく、カスタムストレージプラグインを作成することができます。
以前は、すべてのボリュームプラグインが「ツリー内」にありました。 「ツリー内」のプラグインは、Kubernetesのコアバイナリとともにビルド、リンク、コンパイルされ、出荷されていました。 つまり、Kubernetesに新しいストレージシステム(ボリュームプラグイン)を追加するには、Kubernetesのコアコードリポジトリにコードをチェックインする必要があったのです。
CSIとFlexVolumeはどちらも、ボリュームプラグインをKubernetesコードベースとは独立して開発し、拡張機能としてKubernetesクラスターにデプロイ(インストール)することを可能にします。
ツリー外のボリュームプラグインの作成を検討しているストレージベンダーについては、ボリュームプラグインのFAQを参照してください。
csi
Container Storage Interface(CSI)は、コンテナオーケストレーションシステム(Kubernetesなど)の標準インターフェイスを定義して、任意のストレージシステムをコンテナワークロードに公開します。
詳細についてはCSI design proposalを参照してください。
CSI互換のボリュームドライバーがKubernetesクラスター上に展開されると、ユーザーはcsi
ボリュームタイプを使用して、CSIドライバーによって公開されたボリュームをアタッチまたはマウントすることができます。
csi
ボリュームはPodで3つの異なる方法によって使用することができます。
- PersistentVolumeClaimの参照を通して
- 一般的なエフェメラルボリューム(alpha機能)で
- ドライバーがそれをサポートしている場合は、CSIエフェメラルボリューム(beta機能)を使って
ストレージ管理者は、CSI永続ボリュームを構成するために次のフィールドを使用できます。
driver
: 使用するボリュームドライバーの名前を指定する文字列。 この値はCSI specで定義されたCSIドライバーがGetPluginInfoResponse
で返す値に対応していなければなりません。 これはKubernetesが呼び出すCSIドライバーを識別するために使用され、CSIドライバーコンポーネントがCSIドライバーに属するPVオブジェクトを識別するために使用されます。volumeHandle
: ボリュームを一意に識別する文字列。この値は、CSI specで定義されたCSIドライバーがCreateVolumeResponse
のvolume.id
フィールドに返す値に対応していなければなりません。この値はCSIボリュームドライバーのすべての呼び出しで、ボリュームを参照する際にvolume_id
として渡されます。readOnly
: ボリュームを読み取り専用として「ControllerPublished」(添付)するかどうかを示すオプションのブール値。デフォルトはfalseです。この値は、ControllerPublishVolumeRequest
のreadonly
フィールドを介してCSIドライバーに渡されます。fsType
: PVのVolumeMode
がFilesystem
の場合、このフィールドを使用して、ボリュームのマウントに使用する必要のあるファイルシステムを指定できます。ボリュームがフォーマットされておらず、フォーマットがサポートされている場合、この値はボリュームのフォーマットに使用されます。この値は、ControllerPublishVolumeRequest
、NodeStageVolumeRequest
、およびNodePublishVolumeRequest
のVolumeCapability
フィールドを介してCSIドライバーに渡されます。volumeAttributes
: ボリュームの静的プロパティを指定する、文字列から文字列へのマップ。このマップは、CSI specで定義されているように、CSIドライバーがCreateVolumeResponse
のvolume.attributes
フィールドで返すマップと一致しなければなりません。このマップはControllerPublishVolumeRequest
,NodeStageVolumeRequest
,NodePublishVolumeRequest
のvolume_context
フィールドを介してCSIドライバーに渡されます。controllerPublishSecretRef
: CSIControllerPublishVolume
およびControllerUnpublishVolume
呼び出しを完了するためにCSIドライバーに渡す機密情報を含むsecretオブジェクトへの参照。このフィールドはオプションで、secretが必要ない場合は空にすることができます。secretに複数のsecretが含まれている場合は、すべてのsecretが渡されます。nodeStageSecretRef
: CSINodeStageVolume
呼び出しを完了するために、CSIドライバーに渡す機密情報を含むsecretオブジェクトへの参照。このフィールドはオプションで、secretが必要ない場合は空にすることができます。secretに複数のsecretが含まれている場合、すべてのsecretが渡されます。nodePublishSecretRef
: CSINodePublishVolume
呼び出しを完了するために、CSIドライバーに渡す機密情報を含むsecretオブジェクトへの参照。このフィールドはオプションで、secretが必要ない場合は空にすることができます。secretオブジェクトが複数のsecretを含んでいる場合、すべてのsecretが渡されます。
CSI rawブロックボリュームのサポート
Kubernetes v1.18 [stable]
外部のCSIドライバーを使用するベンダーは、Kubernetesワークロードでrawブロックボリュームサポートを実装できます。
CSI固有の変更を行うことなく、通常どおり、rawブロックボリュームをサポートするPersistentVolume/PersistentVolumeClaimを設定できます。
CSIエフェメラルボリューム
Kubernetes v1.16 [beta]
Pod仕様内でCSIボリュームを直接構成できます。この方法で指定されたボリュームは一時的なものであり、Podを再起動しても持続しません。詳細についてはエフェメラルボリュームを参照してください。
CSIドライバーの開発方法の詳細についてはkubernetes-csiドキュメントを参照してください。
ツリー内プラグインからCSIドライバーへの移行
Kubernetes v1.17 [beta]
CSIMigration
機能を有効にすると、既存のツリー内プラグインに対する操作が、対応するCSIプラグイン(インストールおよび構成されていることが期待されます)に転送されます。
その結果、オペレーターは、ツリー内プラグインに取って代わるCSIドライバーに移行するときに、既存のストレージクラス、PersistentVolume、またはPersistentVolumeClaim(ツリー内プラグインを参照)の構成を変更する必要がありません。
サポートされている操作と機能には、プロビジョニング/削除、アタッチ/デタッチ、マウント/アンマウント、およびボリュームのサイズ変更が含まれます。
CSIMigration
をサポートし、対応するCSIドライバーが実装されているツリー内プラグインは、ボリュームのタイプにリストされています。
flexVolume
Kubernetes v1.23 [deprecated]
FlexVolumeは、ストレージドライバーとのインターフェースにexecベースのモデルを使用するツリー外プラグインインターフェースです。FlexVolumeドライバーのバイナリは、各ノード、場合によってはコントロールプレーンノードにも、あらかじめ定義されたボリュームプラグインパスにインストールする必要があります。
PodはflexVolume
ツリー内ボリュームプラグインを通してFlexVolumeドライバーと対話します。
詳細についてはFlexVolumeのREADMEを参照してください。
FlexVolumeは非推奨です。ツリー外のCSIドライバーを使用することは、外部ストレージをKubernetesと統合するための推奨される方法です。
FlexVolumeドライバーのメンテナーは、CSIドライバーを実装し、FlexVolumeドライバーのユーザーをCSIに移行するのを支援する必要があります。FlexVolumeのユーザーは、同等のCSIドライバーを使用するようにワークロードを移動する必要があります。
マウントの伝播
マウントの伝播により、コンテナによってマウントされたボリュームを、同じPod内の他のコンテナ、または同じノード上の他のPodに共有できます。
ボリュームのマウント伝播は、Container.volumeMounts
のmountPropagation
フィールドによって制御されます。その値は次のとおりです。
None
- このボリュームマウントは、ホストによってこのボリュームまたはそのサブディレクトリにマウントされる後続のマウントを受け取りません。同様に、コンテナによって作成されたマウントはホストに表示されません。これがデフォルトのモードです。このモードはLinuxカーネルドキュメントで説明されている
private
マウント伝播と同じです。HostToContainer
- このボリュームマウントは、このボリュームまたはそのサブディレクトリのいずれかにマウントされる後続のすべてのマウントを受け取ります。つまりホストがボリュームマウント内に何かをマウントすると、コンテナはそこにマウントされていることを確認します。
同様に同じボリュームに対して
Bidirectional
マウント伝搬を持つPodが何かをマウントすると、HostToContainer
マウント伝搬を持つコンテナはそれを見ることができます。このモードはLinuxカーネルドキュメントで説明されている
rslave
マウント伝播と同じです。Bidirectional
- このボリュームマウントは、HostToContainer
マウントと同じように動作します。さらに、コンテナによって作成されたすべてのボリュームマウントは、ホストと、同じボリュームを使用するすべてのPodのすべてのコンテナに伝播されます。このモードの一般的な使用例は、FlexVolumeまたはCSIドライバーを備えたPod、または
hostPath
ボリュームを使用してホストに何かをマウントする必要があるPodです。このモードはLinuxカーネルドキュメントで説明されている
rshared
マウント伝播と同じです。警告:Bidirectional
マウント伝搬は危険です。ホストオペレーティングシステムにダメージを与える可能性があるため、特権的なコンテナでのみ許可されています。 Linuxカーネルの動作に精通していることが強く推奨されます。 また、Pod内のコンテナによって作成されたボリュームマウントは、終了時にコンテナによって破棄(アンマウント)される必要があります。
構成
一部のデプロイメント(CoreOS、RedHat/Centos、Ubuntu)でマウント伝播が正しく機能する前に、以下に示すように、Dockerでマウント共有を正しく構成する必要があります。
Dockerのsystemd
サービスファイルを編集します。以下のようにMountFlags
を設定します。
MountFlags=shared
または、MountFlags=slave
があれば削除してください。その後、Dockerデーモンを再起動します。
sudo systemctl daemon-reload
sudo systemctl restart docker
次の項目
永続ボリュームを使用してWordPressとMySQLをデプロイする例に従ってください。