1 - ボリューム

コンテナ内のディスク上のファイルは一時的なものであり、コンテナ内で実行する場合、重要なアプリケーションでいくつかの問題が発生します。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間で共有できることを意味します。

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の移行

FEATURE STATE: Kubernetes v1.17 [beta]

awsElasticBlockStoreCSIMigration機能を有効にすると、すべてのプラグイン操作が既存のツリー内プラグインからebs.csi.aws.comContainer Storage Interface(CSI)ドライバーにリダイレクトされます。 この機能を使用するには、AWS EBS CSIドライバーがクラスターにインストールされ、CSIMigrationCSIMigrationAWSのbeta機能が有効になっている必要があります。

AWS EBS CSIの移行の完了

FEATURE STATE: Kubernetes v1.17 [alpha]

awsElasticBlockStoreストレージプラグインがコントローラーマネージャーとkubeletによって読み込まれないようにするには、InTreePluginAWSUnregisterフラグをtrueに設定します。

azureDisk

azureDiskボリュームタイプは、MicrosoftAzureデータディスクをPodにマウントします。

詳細については、azureDiskボリュームプラグインを参照してください。

azureDisk CSIの移行

FEATURE STATE: Kubernetes v1.19 [beta]

azureDiskCSIMigration機能を有効にすると、すべてのプラグイン操作が既存のツリー内プラグインからdisk.csi.azure.comContainer Storage Interface(CSI)ドライバーにリダイレクトされます。 この機能を利用するには、クラスターにAzure Disk CSI Driverをインストールし、CSIMigrationおよびCSIMigrationAzureDisk機能を有効化する必要があります。

azureFile

azureFileボリュームタイプは、Microsoft Azureファイルボリューム(SMB 2.1および3.0)をPodにマウントします。

詳細についてはazureFile volume pluginを参照してください。

azureFile CSIの移行

FEATURE STATE: Kubernetes v1.21 [beta]

zureFileCSIMigration機能を有効にすると、既存のツリー内プラグインからfile.csi.azure.comContainer 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の移行

FEATURE STATE: Kubernetes v1.21 [beta]

CinderのCSIMigration機能は、Kubernetes1.21ではデフォルトで有効になっています。 既存のツリー内プラグインからのすべてのプラグイン操作をcinder.csi.openstack.orgContainer 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-configConfigMapはボリュームとしてマウントされ、そのlog_levelエントリに格納されているすべてのコンテンツは、パス/etc/config/log_levelのPodにマウントされます。 このパスはボリュームのmountPathlog_levelをキーとするpathから派生することに注意してください。

downwardAPI

downwardAPIボリュームは、アプリケーションへのdownward APIデータを利用できるようになります。ディレクトリをマウントし、要求されたデータをプレーンテキストファイルに書き込みます。

詳細についてはdownward API exampleを参照してください。

emptyDir

emptyDirボリュームはPodがノードに割り当てられたときに最初に作成され、そのPodがそのノードで実行されている限り存在します。 名前が示すようにemptyDirボリュームは最初は空です。 Pod内のすべてのコンテナはemptyDirボリューム内の同じファイルを読み書きできますが、そのボリュームは各コンテナで同じパスまたは異なるパスにマウントされることがあります。 何らかの理由でPodがノードから削除されると、emptyDir内のデータは永久に削除されます。

emptyDirのいくつかの用途は次の通りです。

  • ディスクベースのマージソートなどのスクラッチスペース
  • クラッシュからの回復のための長い計算のチェックポイント
  • Webサーバーコンテナがデータを提供している間にコンテンツマネージャコンテナがフェッチするファイルを保持する

環境に応じて、emptyDirボリュームは、ディスクやSSD、ネットワークストレージなど、ノードをバックアップするあらゆる媒体に保存されます。 ただし、emptyDir.mediumフィールドを"Memory"に設定すると、Kubernetesは代わりにtmpfs(RAMベースのファイルシステム)をマウントします。 tmpfsは非常に高速ですが、ディスクと違ってノードのリブート時にクリアされ、書き込んだファイルはコンテナのメモリー制限にカウントされることに注意してください。

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間で共有できることを意味します。

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の移行

FEATURE STATE: Kubernetes v1.17 [beta]

GCE PDのCSIMigration機能を有効にすると、すべてのプラグイン操作が既存のツリー内プラグインからpd.csi.storage.gke.ioContainer Storage Interface (CSI) Driverにリダイレクトされるようになります。 この機能を使用するには、クラスターにGCE PD CSI Driverがインストールされ、CSIMigrationCSIMigrationGCEのbeta機能が有効になっている必要があります。

GCE CSIの移行の完了

FEATURE STATE: Kubernetes v1.21 [alpha]

gcePersistentDiskストレージプラグインがコントローラーマネージャーとkubeletによって読み込まれないようにするには、InTreePluginGCEUnregisterフラグをtrueに設定します。

gitRepo(非推奨)

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ボリュームは、ファイルまたはディレクトリをホストノードのファイルシステムから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

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ブロックデバイスとして公開できます。

ローカルボリュームを使用する場合、volumeBindingModeWaitForFirstConsumerに設定した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>"

詳細については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の移行

FEATURE STATE: Kubernetes v1.23 [alpha]

RBDCSIMigration機能を有効にすると、既存のツリー内プラグインからrbd.csi.ceph.comCSIドライバーにすべてのプラグイン操作がリダイレクトされます。 この機能を使用するには、クラスターにCeph CSIドライバーをインストールし、CSIMigrationおよびcsiMigrationRBDフィーチャーゲートを有効にしておく必要があります。

secret

secretボリュームは、パスワードなどの機密情報をPodに渡すために使用します。 Kubernetes APIにsecretを格納し、Kubernetesに直接結合することなくPodが使用するファイルとしてマウントすることができます。 secretボリュームはtmpfs(RAM-backed filesystem)によってバックアップされるため、不揮発性ストレージに書き込まれることはありません。

詳細については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の移行

FEATURE STATE: Kubernetes v1.19 [beta]

vsphereVolumeCSIMigration機能を有効にすると、既存のツリー内プラグインからcsi.vsphere.vmware.comCSIドライバーにすべてのプラグイン操作がリダイレクトされます。 この機能を使用するには、クラスターにvSphere CSIドライバーがインストールされ、CSIMigrationおよびCSIMigrationvSphereフィーチャーゲートが有効になっていなければなりません。

また、vSphere vCenter/ESXiのバージョンが7.0u1以上、HWのバージョンがVM version 15以上であることが条件です。

vSphere CSIの移行の完了

FEATURE STATE: Kubernetes v1.19 [beta]

vsphereVolumeプラグインがコントローラーマネージャーとkubeletによって読み込まれないようにするには、InTreePluginvSphereUnregister機能フラグをtrueに設定する必要があります。すべてのワーカーノードにcsi.vsphere.vmware.comCSIドライバーをインストールする必要があります。

Portworx CSIの移行

FEATURE STATE: Kubernetes v1.23 [alpha]

PortworxのCSIMigration機能が追加されましたが、Kubernetes 1.23ではAlpha状態であるため、デフォルトで無効になっています。 すべてのプラグイン操作を既存のツリー内プラグインからpxd.portworx.comContainer 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の使用

FEATURE STATE: Kubernetes v1.17 [stable]

subPathExprフィールドを使用して、downwart API環境変数からsubPathディレクトリ名を作成します。 subPathプロパティとsubPathExprプロパティは相互に排他的です。

この例では、PodsubPathExprを使用して、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つの異なる方法によって使用することができます。

ストレージ管理者は、CSI永続ボリュームを構成するために次のフィールドを使用できます。

  • driver: 使用するボリュームドライバーの名前を指定する文字列。 この値はCSI specで定義されたCSIドライバーがGetPluginInfoResponseで返す値に対応していなければなりません。 これはKubernetesが呼び出すCSIドライバーを識別するために使用され、CSIドライバーコンポーネントがCSIドライバーに属するPVオブジェクトを識別するために使用されます。
  • volumeHandle: ボリュームを一意に識別する文字列。この値は、CSI specで定義されたCSIドライバーがCreateVolumeResponsevolume.idフィールドに返す値に対応していなければなりません。この値はCSIボリュームドライバーのすべての呼び出しで、ボリュームを参照する際にvolume_idとして渡されます。
  • readOnly: ボリュームを読み取り専用として「ControllerPublished」(添付)するかどうかを示すオプションのブール値。デフォルトはfalseです。この値は、ControllerPublishVolumeRequestreadonlyフィールドを介してCSIドライバーに渡されます。
  • fsType: PVのVolumeModeFilesystemの場合、このフィールドを使用して、ボリュームのマウントに使用する必要のあるファイルシステムを指定できます。ボリュームがフォーマットされておらず、フォーマットがサポートされている場合、この値はボリュームのフォーマットに使用されます。この値は、ControllerPublishVolumeRequestNodeStageVolumeRequest、およびNodePublishVolumeRequestVolumeCapabilityフィールドを介してCSIドライバーに渡されます。
  • volumeAttributes: ボリュームの静的プロパティを指定する、文字列から文字列へのマップ。このマップは、CSI specで定義されているように、CSIドライバーがCreateVolumeResponsevolume.attributesフィールドで返すマップと一致しなければなりません。このマップはControllerPublishVolumeRequest,NodeStageVolumeRequest,NodePublishVolumeRequestvolume_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ブロックボリュームのサポート

FEATURE STATE: Kubernetes v1.18 [stable]

外部のCSIドライバーを使用するベンダーは、Kubernetesワークロードでrawブロックボリュームサポートを実装できます。

CSI固有の変更を行うことなく、通常どおり、rawブロックボリュームをサポートするPersistentVolume/PersistentVolumeClaimを設定できます。

CSIエフェメラルボリューム

FEATURE STATE: Kubernetes v1.16 [beta]

Pod仕様内でCSIボリュームを直接構成できます。この方法で指定されたボリュームは一時的なものであり、Podを再起動しても持続しません。詳細についてはエフェメラルボリュームを参照してください。

CSIドライバーの開発方法の詳細についてはkubernetes-csiドキュメントを参照してください。

ツリー内プラグインからCSIドライバーへの移行

FEATURE STATE: Kubernetes v1.17 [beta]

CSIMigration機能を有効にすると、既存のツリー内プラグインに対する操作が、対応するCSIプラグイン(インストールおよび構成されていることが期待されます)に転送されます。 その結果、オペレーターは、ツリー内プラグインに取って代わるCSIドライバーに移行するときに、既存のストレージクラス、PersistentVolume、またはPersistentVolumeClaim(ツリー内プラグインを参照)の構成を変更する必要がありません。

サポートされている操作と機能には、プロビジョニング/削除、アタッチ/デタッチ、マウント/アンマウント、およびボリュームのサイズ変更が含まれます。

CSIMigrationをサポートし、対応するCSIドライバーが実装されているツリー内プラグインは、ボリュームのタイプにリストされています。

flexVolume

FEATURE STATE: Kubernetes v1.23 [deprecated]

FlexVolumeは、ストレージドライバーとのインターフェースにexecベースのモデルを使用するツリー外プラグインインターフェースです。FlexVolumeドライバーのバイナリは、各ノード、場合によってはコントロールプレーンノードにも、あらかじめ定義されたボリュームプラグインパスにインストールする必要があります。

PodはflexVolumeツリー内ボリュームプラグインを通してFlexVolumeドライバーと対話します。

詳細についてはFlexVolumeのREADMEを参照してください。

マウントの伝播

マウントの伝播により、コンテナによってマウントされたボリュームを、同じPod内の他のコンテナ、または同じノード上の他のPodに共有できます。

ボリュームのマウント伝播は、Container.volumeMountsmountPropagationフィールドによって制御されます。その値は次のとおりです。

  • None - このボリュームマウントは、ホストによってこのボリュームまたはそのサブディレクトリにマウントされる後続のマウントを受け取りません。同様に、コンテナによって作成されたマウントはホストに表示されません。これがデフォルトのモードです。

    このモードはLinuxカーネルドキュメントで説明されているprivateマウント伝播と同じです。

  • HostToContainer - このボリュームマウントは、このボリュームまたはそのサブディレクトリのいずれかにマウントされる後続のすべてのマウントを受け取ります。

    つまりホストがボリュームマウント内に何かをマウントすると、コンテナはそこにマウントされていることを確認します。

    同様に同じボリュームに対してBidirectionalマウント伝搬を持つPodが何かをマウントすると、HostToContainerマウント伝搬を持つコンテナはそれを見ることができます。

    このモードはLinuxカーネルドキュメントで説明されているrslaveマウント伝播と同じです。

  • Bidirectional - このボリュームマウントは、HostToContainerマウントと同じように動作します。さらに、コンテナによって作成されたすべてのボリュームマウントは、ホストと、同じボリュームを使用するすべてのPodのすべてのコンテナに伝播されます。

    このモードの一般的な使用例は、FlexVolumeまたはCSIドライバーを備えたPod、またはhostPathボリュームを使用してホストに何かをマウントする必要があるPodです。

    このモードはLinuxカーネルドキュメントで説明されているrsharedマウント伝播と同じです。

構成

一部のデプロイメント(CoreOS、RedHat/Centos、Ubuntu)でマウント伝播が正しく機能する前に、以下に示すように、Dockerでマウント共有を正しく構成する必要があります。

Dockerのsystemdサービスファイルを編集します。以下のようにMountFlagsを設定します。

MountFlags=shared

または、MountFlags=slaveがあれば削除してください。その後、Dockerデーモンを再起動します。

sudo systemctl daemon-reload
sudo systemctl restart docker

次の項目

永続ボリュームを使用してWordPressとMySQLをデプロイする例に従ってください。

2 - 永続ボリューム

このドキュメントではKubernetesの PersistentVolume について説明します。ボリュームを一読することをおすすめします。

概要

ストレージを管理することはインスタンスを管理することとは全くの別物です。PersistentVolumeサブシステムは、ストレージが何から提供されているか、どのように消費されているかをユーザーと管理者から抽象化するAPIを提供します。これを実現するためのPersistentVolumeとPersistentVolumeClaimという2つの新しいAPIリソースを紹介します。

PersistentVolume (PV)はストレージクラスを使って管理者もしくは動的にプロビジョニングされるクラスターのストレージの一部です。これはNodeと同じようにクラスターリソースの一部です。PVはVolumeのようなボリュームプラグインですが、PVを使う個別のPodとは独立したライフサイクルを持っています。このAPIオブジェクトはNFS、iSCSIやクラウドプロバイダー固有のストレージシステムの実装の詳細を捕捉します。

PersistentVolumeClaim (PVC)はユーザーによって要求されるストレージです。これはPodと似ています。PodはNodeリソースを消費し、PVCはPVリソースを消費します。Podは特定レベルのCPUとメモリーリソースを要求することができます。クレームは特定のサイズやアクセスモード(例えば、ReadWriteOnce、ReadOnlyMany、ReadWriteManyにマウントできます。詳しくはアクセスモードを参照してください)を要求することができます。

PersistentVolumeClaimはユーザーに抽象化されたストレージリソースの消費を許可する一方、ユーザーは色々な問題に対処するためにパフォーマンスといった様々なプロパティを持ったPersistentVolumeを必要とすることは一般的なことです。クラスター管理者はユーザーに様々なボリュームがどのように実装されているかを表に出すことなく、サイズやアクセスモードだけではない色々な点で異なった、様々なPersistentVolumeを提供できる必要があります。これらのニーズに応えるために StorageClass リソースがあります。

実例を含む詳細なチュートリアルを参照して下さい。

ボリュームと要求のライフサイクル

PVはクラスター内のリソースです。PVCはこれらのリソースの要求でありまた、クレームのチェックとしても機能します。PVとPVCの相互作用はこのライフサイクルに従います。

プロビジョニング

PVは静的か動的どちらかでプロビジョニングされます。

静的

クラスター管理者は多数のPVを作成します。それらはクラスターのユーザーが使うことのできる実際のストレージの詳細を保持します。それらはKubernetes APIに存在し、利用できます。

動的

ユーザーのPersistentVolumeClaimが管理者の作成したいずれの静的PVにも一致しない場合、クラスターはPVC用にボリュームを動的にプロビジョニングしようとする場合があります。 このプロビジョニングはStorageClassに基づいています。PVCはストレージクラスの要求が必要であり、管理者は動的プロビジョニングを行うためにストレージクラスの作成・設定が必要です。ストレージクラスを""にしたストレージ要求は、自身の動的プロビジョニングを事実上無効にします。

ストレージクラスに基づいたストレージの動的プロビジョニングを有効化するには、クラスター管理者がDefaultStorageClassアドミッションコントローラーをAPIサーバーで有効化する必要があります。 これは例えば、DefaultStorageClassがAPIサーバーコンポーネントの--enable-admission-pluginsフラグのコンマ区切りの順序付きリストの中に含まれているかで確認できます。 APIサーバーのコマンドラインフラグの詳細についてはkube-apiserverのドキュメントを参照してください。

バインディング

ユーザは、特定のサイズのストレージとアクセスモードを指定した上でPersistentVolumeClaimを作成します(動的プロビジョニングの場合は、すでに作られています)。マスター内のコントロールループは、新しく作られるPVCをウォッチして、それにマッチするPVが見つかったときに、それらを紐付けます。PVが新しいPVC用に動的プロビジョニングされた場合、コントロールループは常にPVをそのPVCに紐付けます。そうでない場合、ユーザーは常に少なくとも要求したサイズ以上のボリュームを取得しますが、ボリュームは要求されたサイズを超えている可能性があります。一度紐付けされると、どのように紐付けられたかに関係なくPersistentVolumeClaimの紐付けは排他的(決められた特定のPVとしか結びつかない状態)になります。PVCからPVへの紐付けは、PersistentVolumeとPersistentVolumeClaim間の双方向の紐付けであるClaimRefを使用した1対1のマッピングになっています。

一致するボリュームが存在しない場合、クレームはいつまでも紐付けされないままになります。一致するボリュームが利用可能になると、クレームがバインドされます。たとえば、50GiのPVがいくつもプロビジョニングされているクラスターだとしても、100Giを要求するPVCとは一致しません。100GiのPVがクラスターに追加されると、PVCを紐付けできます。

使用

Podは要求をボリュームとして使用します。クラスターは、要求を検査して紐付けられたボリュームを見つけそのボリュームをPodにマウントします。複数のアクセスモードをサポートするボリュームの場合、ユーザーはPodのボリュームとしてクレームを使う時にどのモードを希望するかを指定します。

ユーザーがクレームを取得し、そのクレームがバインドされると、バインドされたPVは必要な限りそのユーザーに属します。ユーザーはPodをスケジュールし、PodのvolumesブロックにpersistentVolumeClaimを含めることで、バインドされたクレームのPVにアクセスします。 書式の詳細はこちらを確認して下さい。

使用中のストレージオブジェクトの保護

使用中のストレージオブジェクト保護機能の目的はデータ損失を防ぐために、Podによって実際に使用されている永続ボリュームクレーム(PVC)と、PVCにバインドされている永続ボリューム(PV)がシステムから削除されないようにすることです。

ユーザーがPodによって実際に使用されているPVCを削除しても、そのPVCはすぐには削除されません。PVCの削除は、PVCがPodで使用されなくなるまで延期されます。また、管理者がPVCに紐付けられているPVを削除しても、PVはすぐには削除されません。PVがPVCに紐付けられなくなるまで、PVの削除は延期されます。

PVCの削除が保護されているかは、PVCのステータスがTerminatingになっていて、そしてFinalizersのリストにkubernetes.io/pvc-protectionが含まれているかで確認できます。

kubectl describe pvc hostpath
Name:          hostpath
Namespace:     default
StorageClass:  example-hostpath
Status:        Terminating
Volume:
Labels:        <none>
Annotations:   volume.beta.kubernetes.io/storage-class=example-hostpath
               volume.beta.kubernetes.io/storage-provisioner=example.com/hostpath
Finalizers:    [kubernetes.io/pvc-protection]

同様にPVの削除が保護されているかは、PVのステータスがTerminatingになっていて、そしてFinalizersのリストにkubernetes.io/pv-protectionが含まれているかで確認できます。

kubectl describe pv task-pv-volume
Name:            task-pv-volume
Labels:          type=local
Annotations:     <none>
Finalizers:      [kubernetes.io/pv-protection]
StorageClass:    standard
Status:          Terminating
Claim:
Reclaim Policy:  Delete
Access Modes:    RWO
Capacity:        1Gi
Message:
Source:
    Type:          HostPath (bare host directory volume)
    Path:          /tmp/data
    HostPathType:
Events:            <none>

再クレーム

ユーザーは、ボリュームの使用が完了したら、リソースの再クレームを許可するAPIからPVCオブジェクトを削除できます。PersistentVolumeの再クレームポリシーはそのクレームが解放された後のボリュームの処理をクラスターに指示します。現在、ボリュームは保持、リサイクル、または削除できます。

保持

Retainという再クレームポリシーはリソースを手動で再クレームすることができます。PersistentVolumeClaimが削除される時、PersistentVolumeは依然として存在はしますが、ボリュームは解放済みです。ただし、以前のクレームデータはボリューム上に残っているため、別のクレームにはまだ使用できません。管理者は次の手順でボリュームを手動で再クレームできます。

  1. PersistentVolumeを削除します。PVが削除された後も、外部インフラストラクチャー(AWS EBS、GCE PD、Azure Disk、Cinderボリュームなど)に関連付けられたストレージアセットは依然として残ります。
  2. ストレージアセットに関連するのデータを手動で適切にクリーンアップします。
  3. 関連するストレージアセットを手動で削除するか、同じストレージアセットを再利用したい場合、新しいストレージアセット定義と共にPersistentVolumeを作成します。

削除

Delete再クレームポリシーをサポートするボリュームプラグインの場合、削除するとPersistentVolumeオブジェクトがKubernetesから削除されるだけでなく、AWS EBS、GCE PD、Azure Disk、Cinderボリュームなどの外部インフラストラクチャーの関連ストレージアセットも削除されます。動的にプロビジョニングされたボリュームは、StorageClassの再クレームポリシーを継承します。これはデフォルトで削除です。管理者は、ユーザーの需要に応じてStorageClassを構成する必要があります。そうでない場合、PVは作成後に編集またはパッチを適用する必要があります。PersistentVolumeの再クレームポリシーの変更を参照してください。

リサイクル

基盤となるボリュームプラグインでサポートされている場合、Recycle再クレームポリシーはボリュームに対して基本的な削除(rm -rf /thevolume/*)を実行し、新しいクレームに対して再び利用できるようにします。

管理者はreferenceで説明するように、Kubernetesコントローラーマネージャーのコマンドライン引数を使用して、カスタムリサイクラーPodテンプレートを構成できます。カスタムリサイクラーPodテンプレートには、次の例に示すように、volumes仕様が含まれている必要があります。

apiVersion: v1
kind: Pod
metadata:
  name: pv-recycler
  namespace: default
spec:
  restartPolicy: Never
  volumes:
  - name: vol
    hostPath:
      path: /any/path/it/will/be/replaced
  containers:
  - name: pv-recycler
    image: "k8s.gcr.io/busybox"
    command: ["/bin/sh", "-c", "test -e /scrub && rm -rf /scrub/..?* /scrub/.[!.]* /scrub/*  && test -z \"$(ls -A /scrub)\" || exit 1"]
    volumeMounts:
    - name: vol
      mountPath: /scrub

ただし、カスタムリサイクラーPodテンプレートのvolumesパート内で指定された特定のパスは、リサイクルされるボリュームの特定のパスに置き換えられます。

永続ボリュームの予約

コントロールプレーンは、永続ボリュームクレームをクラスター内の一致する永続ボリュームにバインドできます。 ただし、永続ボリュームクレームを特定の永続ボリュームにバインドする場合、それらを事前にバインドする必要があります。

永続ボリュームクレームで永続ボリュームを指定することにより、その特定の永続ボリュームと永続ボリュームクレームの間のバインディングを宣言します。 永続ボリュームが存在し、そのclaimRefフィールドで永続ボリュームクレームを予約していない場合に永続ボリュームと永続ボリュームクレームがバインドされます。

バインディングは、ノードアフィニティを含むいくつかのボリュームの一致基準に関係なく発生します。 コントロールプレーンは、依然としてストレージクラス、アクセスモード、および要求されたストレージサイズが有効であることをチェックします。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: foo-pvc
  namespace: foo
spec:
  storageClassName: "" # 空の文字列を明示的に指定する必要があります。そうしないとデフォルトのストレージクラスが設定されてしまいます。
  volumeName: foo-pv
  ...

この方法は、永続ボリュームへのバインド特権を保証するものではありません。 他の永続ボリュームクレームが指定した永続ボリュームを使用できる場合、最初にそのストレージボリュームを予約する必要があります。 永続ボリュームのclaimRefフィールドに関連する永続ボリュームクレームを指定して、他の永続ボリュームクレームがその永続ボリュームにバインドできないようにしてください。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: foo-pv
spec:
  storageClassName: ""
  claimRef:
    name: foo-pvc
    namespace: foo
  ...

これは、既存の永続ボリュームを再利用する場合など、claimPolicyRetainに設定されている永続ボリュームを使用する場合に役立ちます。

永続ボリュームクレームの拡大

FEATURE STATE: Kubernetes v1.11 [beta]

PersistentVolumeClaim(PVC)の拡大はデフォルトで有効です。次のボリュームの種類で拡大できます。

  • gcePersistentDisk
  • awsElasticBlockStore
  • Cinder
  • glusterfs
  • rbd
  • Azure File
  • Azure Disk
  • Portworx
  • FlexVolumes
  • CSI

そのストレージクラスのallowVolumeExpansionフィールドがtrueとなっている場合のみ、PVCを拡大できます。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gluster-vol-default
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://192.168.10.100:8080"
  restuser: ""
  secretNamespace: ""
  secretName: ""
allowVolumeExpansion: true

PVCに対してさらに大きなボリュームを要求するには、PVCオブジェクトを編集してより大きなサイズを指定します。これによりPersistentVolumeを受け持つ基盤にボリュームの拡大がトリガーされます。クレームを満たすため新しくPersistentVolumeが作成されることはありません。代わりに既存のボリュームがリサイズされます。

CSIボリュームの拡張

FEATURE STATE: Kubernetes v1.16 [beta]

CSIボリュームの拡張のサポートはデフォルトで有効になっていますが、ボリューム拡張をサポートするにはボリューム拡張を利用できるCSIドライバーも必要です。詳細については、それぞれのCSIドライバーのドキュメントを参照してください。

ファイルシステムを含むボリュームのリサイズ

ファイルシステムがXFS、Ext3、またはExt4の場合にのみ、ファイルシステムを含むボリュームのサイズを変更できます。

ボリュームにファイルシステムが含まれる場合、新しいPodがPersistentVolumeClaimでReadWriteモードを使用している場合にのみ、ファイルシステムのサイズが変更されます。ファイルシステムの拡張は、Podの起動時、もしくはPodの実行時で基盤となるファイルシステムがオンラインの拡張をサポートする場合に行われます。

FlexVolumesでは、ドライバのRequiresFSResize機能がtrueに設定されている場合、サイズを変更できます。 FlexVolumeは、Podの再起動時にサイズ変更できます。

使用中の永続ボリュームクレームのリサイズ

FEATURE STATE: Kubernetes v1.15 [beta]

この場合、既存のPVCを使用しているPodまたはDeploymentを削除して再作成する必要はありません。使用中のPVCは、ファイルシステムが拡張されるとすぐにPodで自動的に使用可能になります。この機能は、PodまたはDeploymentで使用されていないPVCには影響しません。拡張を完了する前に、PVCを使用するPodを作成する必要があります。

他のボリュームタイプと同様、FlexVolumeボリュームは、Podによって使用されている最中でも拡張できます。

ボリューム拡張時の障害からの復旧

基盤ストレージの拡張に失敗した際には、クラスターの管理者はPersistent Volume Claim (PVC)の状態を手動で復旧し、リサイズ要求をキャンセルします。それをしない限り、リサイズ要求は管理者の介入なしにコントローラーによって継続的に再試行されます。

  1. PersistentVolumeClaim(PVC)にバインドされているPersistentVolume(PV)をRetain再クレームポリシーとしてマークします。
  2. PVCを削除します。PVはRetain再クレームポリシーを持っているため、PVCを再び作成したときにいかなるデータも失うことはありません。
  3. claimRefエントリーをPVスペックから削除して、新しいPVCがそれにバインドできるようにします。これによりPVはAvailableになります。
  4. PVより小さいサイズでPVCを再作成し、PVCのvolumeNameフィールドをPVの名前に設定します。これにより新しいPVCを既存のPVにバインドします。
  5. PVを再クレームポリシーを復旧することを忘れずに行ってください。

永続ボリュームの種類

PersistentVolumeの種類はプラグインとして実装されます。Kubernetesは現在次のプラグインに対応しています。

  • awsElasticBlockStore - AWS Elastic Block Store (EBS)
  • azureDisk - Azure Disk
  • azureFile - Azure File
  • cephfs - CephFS volume
  • cinder - Cinder (OpenStack block storage) (非推奨)
  • csi - Container Storage Interface (CSI)
  • fc - Fibre Channel (FC) storage
  • flexVolume - FlexVolume
  • flocker - Flocker storage
  • gcePersistentDisk - GCE Persistent Disk
  • glusterfs - Glusterfs volume
  • hostPath - HostPath volume (テスト用の単一ノードのみ。マルチノードクラスターでは動作しません。代わりにlocalボリュームを利用することを検討してください。)
  • iscsi - iSCSI (SCSI over IP) storage
  • local - ノードにマウントされたローカルストレージデバイス
  • nfs - Network File System (NFS) storage
  • photonPersistentDisk - Photon controller persistent disk (対応するクラウドプロバイダーが削除されたため、このボリュームタイプは機能しなくなりました。)
  • portworxVolume - Portworx volume
  • quobyte - Quobyte volume
  • rbd - Rados Block Device (RBD) volume
  • scaleIO - ScaleIO volume (非推奨)
  • storageos - StorageOS volume
  • vsphereVolume - vSphere VMDK volume

永続ボリューム

各PVには、仕様とボリュームのステータスが含まれているspecとstatusが含まれています。 PersistentVolumeオブジェクトの名前は、有効な DNSサブドメイン名である必要があります。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2

容量

通常、PVには特定のストレージ容量があります。これはPVのcapacity属性を使用して設定されます。容量によって期待される単位を理解するためには、Kubernetesのリソースモデルを参照してください。

現在、設定または要求できるのはストレージサイズのみです。将来の属性には、IOPS、スループットなどが含まれます。

ボリュームモード

FEATURE STATE: Kubernetes v1.18 [stable]

KubernetesはPersistentVolumesの2つのvolumeModesをサポートしています: FilesystemBlockです。
volumeModeは任意のAPIパラメーターです。
FilesystemvolumeModeパラメーターが省略されたときに使用されるデフォルトのモードです。

volumeMode: FilesystemであるボリュームはPodにマウントされてディレクトリになります。 ボリュームがブロックデバイスでデバイスが空の時、Kubernetesは初めてそれにマウントされる前にデバイスのファイルシステムを作成します。

volumeModeの値をBlockに設定してボリュームをRAWブロックデバイスとして使用します。
このようなボリュームは、ファイルシステムを持たないブロックデバイスとしてPodに提示されます。
このモードは、Podとボリュームの間のファイルシステムレイヤなしにボリュームにアクセスする可能な限り最速の方法をPodに提供するのに便利です。一方で、Pod上で実行しているアプリケーションはRAWブロックデバイスの扱い方を知っていなければなりません。
Pod内でvolumeMode: Blockとともにボリュームを使用する例としては、Raw Block Volume Supportを参照してください。

アクセスモード

PersistentVolumeは、リソースプロバイダーがサポートする方法でホストにマウントできます。次の表に示すように、プロバイダーにはさまざまな機能があり、各PVのアクセスモードは、その特定のボリュームでサポートされる特定のモードに設定されます。たとえば、NFSは複数の読み取り/書き込みクライアントをサポートできますが、特定のNFSのPVはサーバー上で読み取り専用としてエクスポートされる場合があります。各PVは、その特定のPVの機能を記述する独自のアクセスモードのセットを取得します。

アクセスモードは次の通りです。

ReadWriteOnce
ボリュームは単一のNodeで読み取り/書き込みとしてマウントできます
ReadOnlyMany
ボリュームは多数のNodeで読み取り専用としてマウントできます
ReadWriteMany
ボリュームは多数のNodeで読み取り/書き込みとしてマウントできます
ReadWriteOncePod
ボリュームは、単一のPodで読み取り/書き込みとしてマウントできます。クラスタ全体で1つのPodのみがそのPVCの読み取りまたは書き込みを行えるようにする場合は、ReadWriteOncePodアクセスモードを使用します。これは、CSIボリュームとKubernetesバージョン1.22以降でのみサポートされます。

これについてはブログIntroducing Single Pod Access Mode for PersistentVolumesに詳細が記載されています。

CLIではアクセスモードは次のように略されます。

  • RWO - ReadWriteOnce
  • ROX - ReadOnlyMany
  • RWX - ReadWriteMany

Important! ボリュームは、多数のモードをサポートしていても、一度に1つのアクセスモードでしかマウントできません。たとえば、GCEPersistentDiskは、単一NodeではReadWriteOnceとして、または多数のNodeではReadOnlyManyとしてマウントできますが、同時にマウントすることはできません。

ボリュームプラグイン ReadWriteOnce ReadOnlyMany ReadWriteMany
AWSElasticBlockStore - -
AzureFile
AzureDisk - -
CephFS
Cinder - -
CSI ドライバーに依存 ドライバーに依存 ドライバーに依存
FC -
FlexVolume ドライバーに依存
Flocker - -
GCEPersistentDisk -
Glusterfs
HostPath - -
iSCSI -
Quobyte
NFS
RBD -
VsphereVolume - - (Podが連結されている場合のみ)
PortworxVolume -
ScaleIO -
StorageOS - -

Class

PVはクラスを持つことができます。これはstorageClassName属性をストレージクラスの名前に設定することで指定されます。特定のクラスのPVは、そのクラスを要求するPVCにのみバインドできます。storageClassNameにクラスがないPVは、特定のクラスを要求しないPVCにのみバインドできます。

以前volume.beta.kubernetes.io/storage-classアノテーションは、storageClassName属性の代わりに使用されていました。このアノテーションはまだ機能しています。ただし、将来のKubernetesリリースでは完全に非推奨です。

再クレームポリシー

現在の再クレームポリシーは次のとおりです。

  • 保持 -- 手動再クレーム
  • リサイクル -- 基本的な削除 (rm -rf /thevolume/*)
  • 削除 -- AWS EBS、GCE PD、Azure Disk、もしくはOpenStack Cinderボリュームに関連するストレージアセットを削除

現在、NFSとHostPathのみがリサイクルをサポートしています。AWS EBS、GCE PD、Azure Disk、およびCinder volumeは削除をサポートしています。

マウントオプション

Kubernetes管理者は永続ボリュームがNodeにマウントされるときの追加マウントオプションを指定できます。

次のボリュームタイプがマウントオプションをサポートしています。

  • AWSElasticBlockStore
  • AzureDisk
  • AzureFile
  • CephFS
  • Cinder (OpenStackブロックストレージ)
  • GCEPersistentDisk
  • Glusterfs
  • NFS
  • Quobyte Volumes
  • RBD (Ceph Block Device)
  • StorageOS
  • VsphereVolume
  • iSCSI

マウントオプションは検証されないため、不正だった場合マウントは失敗します。

以前volume.beta.kubernetes.io/mount-optionsアノテーションがmountOptions属性の代わりに使われていました。このアノテーションはまだ機能しています。ただし、将来のKubernetesリリースでは完全に非推奨です。

ノードアフィニティ

PVはノードアフィニティを指定して、このボリュームにアクセスできるNodeを制限する制約を定義できます。PVを使用するPodは、ノードアフィニティによって選択されたNodeにのみスケジュールされます。

フェーズ

ボリュームは次のフェーズのいずれかです。

  • 利用可能 -- まだクレームに紐付いていない自由なリソース
  • バウンド -- クレームに紐付いている
  • リリース済み -- クレームが削除されたが、クラスターにまだクレームされている
  • 失敗 -- 自動再クレームに失敗

CLIにはPVに紐付いているPVCの名前が表示されます。

永続ボリューム要求

各PVCにはspecとステータスが含まれます。これは、仕様とクレームのステータスです。

PersistentVolumeClaimオブジェクトの名前は、有効な DNSサブドメイン名である必要があります。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

アクセスモード

クレームは、特定のアクセスモードでストレージを要求するときにボリュームと同じ規則を使用します。

ボリュームモード

クレームは、ボリュームと同じ規則を使用して、ファイルシステムまたはブロックデバイスとしてのボリュームの消費を示します。

リソース

Podと同様に、クレームは特定の量のリソースを要求できます。この場合、要求はストレージ用です。同じリソースモデルがボリュームとクレームの両方に適用されます。

セレクター

クレームでは、ラベルセレクターを指定して、ボリュームセットをさらにフィルター処理できます。ラベルがセレクターに一致するボリュームのみがクレームにバインドできます。セレクターは2つのフィールドで構成できます。

  • matchLabels - ボリュームはこの値のラベルが必要です
  • matchExpressions - キー、値のリスト、およびキーと値を関連付ける演算子を指定することによって作成された要件のリスト。有効な演算子は、In、NotIn、ExistsおよびDoesNotExistです。

matchLabelsmatchExpressionsの両方からのすべての要件はANDで結合されます。一致するには、すべてが一致する必要があります。

クラス

クレームは、storageClassName属性を使用してストレージクラスの名前を指定することにより、特定のクラスを要求できます。PVCにバインドできるのは、PVCと同じstorageClassNameを持つ、要求されたクラスのPVのみです。

PVCは必ずしもクラスをリクエストする必要はありません。storageClassName""に設定されているPVCは、クラスのないPVを要求していると常に解釈されるため、クラスのないPVにのみバインドできます(アノテーションがないか、""に等しい1つのセット)。storageClassNameのないPVCはまったく同じではなく、DefaultStorageClassアドミッションプラグインがオンになっているかどうかによって、クラスターによって異なる方法で処理されます。

  • アドミッションプラグインがオンになっている場合、管理者はデフォルトのStorageClassを指定できます。storageClassNameを持たないすべてのPVCは、そのデフォルトのPVにのみバインドできます。デフォルトのStorageClassの指定は、StorageClassオブジェクトでstorageclass.kubernetes.io/is-default-classアノテーションをtrueに設定することにより行われます。管理者がデフォルトを指定しない場合、クラスターは、アドミッションプラグインがオフになっているかのようにPVC作成をレスポンスします。複数のデフォルトが指定されている場合、アドミッションプラグインはすべてのPVCの作成を禁止します。
  • アドミッションプラグインがオフになっている場合、デフォルトのStorageClassの概念はありません。storageClassNameを持たないすべてのPVCは、クラスを持たないPVにのみバインドできます。この場合、storageClassNameを持たないPVCは、storageClassName""に設定されているPVCと同じように扱われます。

インストール方法によっては、インストール時にアドオンマネージャーによってデフォルトのストレージクラスがKubernetesクラスターにデプロイされる場合があります。

PVCがselectorを要求することに加えてStorageClassを指定する場合、要件はANDで一緒に結合されます。要求されたクラスのPVと要求されたラベルのみがPVCにバインドされます。

以前は、storageClassName属性の代わりにvolume.beta.kubernetes.io/storage-classアノテーションが使用されていました。このアノテーションはまだ機能しています。ただし、今後のKubernetesリリースではサポートされません。

ボリュームとしてのクレーム

Podは、クレームをボリュームとして使用してストレージにアクセスします。クレームは、そのクレームを使用するPodと同じ名前空間に存在する必要があります。クラスターは、Podの名前空間でクレームを見つけ、それを使用してクレームを支援しているPersistentVolumeを取得します。次に、ボリュームがホストとPodにマウントされます。

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

名前空間に関する注意

PersistentVolumeバインドは排他的であり、PersistentVolumeClaimは名前空間オブジェクトであるため、"多"モード(ROXRWX)でクレームをマウントすることは1つの名前空間内でのみ可能です。

Rawブロックボリュームのサポート

FEATURE STATE: Kubernetes v1.18 [stable]

次のボリュームプラグインは、必要に応じて動的プロビジョニングを含むrawブロックボリュームをサポートします。

  • AWSElasticBlockStore
  • AzureDisk
  • CSI
  • FC (Fibre Channel)
  • GCEPersistentDisk
  • iSCSI
  • Local volume
  • OpenStack Cinder
  • RBD (Ceph Block Device)
  • VsphereVolume

Rawブロックボリュームを使用した永続ボリューム

apiVersion: v1
kind: PersistentVolume
metadata:
  name: block-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  persistentVolumeReclaimPolicy: Retain
  fc:
    targetWWNs: ["50060e801049cfd1"]
    lun: 0
    readOnly: false

Rawブロックボリュームを要求する永続ボリュームクレーム

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: block-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Block
  resources:
    requests:
      storage: 10Gi

コンテナにRawブロックデバイスパスを追加するPod仕様

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-block-volume
spec:
  containers:
    - name: fc-container
      image: fedora:26
      command: ["/bin/sh", "-c"]
      args: [ "tail -f /dev/null" ]
      volumeDevices:
        - name: data
          devicePath: /dev/xvda
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: block-pvc

ブロックボリュームのバインド

ユーザーがPersistentVolumeClaim specのvolumeModeフィールドを使用してrawブロックボリュームの要求を示す場合、バインディングルールは、このモードをspecの一部として考慮しなかった以前のリリースとわずかに異なります。表にリストされているのは、ユーザーと管理者がrawブロックデバイスを要求するために指定可能な組み合わせの表です。この表は、ボリュームがバインドされるか、組み合わせが与えられないかを示します。静的にプロビジョニングされたボリュームのボリュームバインディングマトリクスはこちらです。

PVボリュームモード PVCボリュームモード 結果
未定義 未定義 バインド
未定義 ブロック バインドなし
未定義 ファイルシステム バインド
ブロック 未定義 バインドなし
ブロック ブロック バインド
ブロック ファイルシステム バインドなし
ファイルシステム ファイルシステム バインド
ファイルシステム ブロック バインドなし
ファイルシステム 未定義 バインド

ボリュームのスナップショットとスナップショットからのボリュームの復元のサポート

FEATURE STATE: Kubernetes v1.17 [beta]

ボリュームスナップショット機能は、CSIボリュームプラグインのみをサポートするために追加されました。詳細については、ボリュームのスナップショットを参照してください。

ボリュームスナップショットのデータソースからボリュームを復元する機能を有効にするには、apiserverおよびcontroller-managerでVolumeSnapshotDataSourceフィーチャーゲートを有効にします。

ボリュームスナップショットから永続ボリュームクレームを作成する

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: restore-pvc
spec:
  storageClassName: csi-hostpath-sc
  dataSource:
    name: new-snapshot-test
    kind: VolumeSnapshot
    apiGroup: snapshot.storage.k8s.io
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

ボリュームの複製

ボリュームの複製はCSIボリュームプラグインにのみ利用可能です。

PVCデータソースからのボリューム複製機能を有効にするには、apiserverおよびcontroller-managerでVolumeSnapshotDataSourceフィーチャーゲートを有効にします。

既存のPVCからの永続ボリュームクレーム作成

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: cloned-pvc
spec:
  storageClassName: my-csi-plugin
  dataSource:
    name: existing-src-pvc-name
    kind: PersistentVolumeClaim
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10Gi

可搬性の高い設定の作成

もし幅広いクラスターで実行され、永続ボリュームが必要となる構成テンプレートやサンプルを作成している場合は、次のパターンを使用することをお勧めします。

  • 構成にPersistentVolumeClaimオブジェクトを含める(DeploymentやConfigMapと共に)

  • ユーザーが設定をインスタンス化する際にPersistentVolumeを作成する権限がない場合があるため、設定にPersistentVolumeオブジェクトを含めない。

  • テンプレートをインスタンス化する時にストレージクラス名を指定する選択肢をユーザーに与える

    • ユーザーがストレージクラス名を指定する場合、persistentVolumeClaim.storageClassName フィールドにその値を入力する。これにより、クラスターが管理者によって有効にされたストレージクラスを持っている場合、PVCは正しいストレージクラスと一致する。
    • ユーザーがストレージクラス名を指定しない場合、persistentVolumeClaim.storageClassNameフィールドはnilのままにする。これにより、PVはユーザーにクラスターのデフォルトストレージクラスで自動的にプロビジョニングされる。多くのクラスター環境ではデフォルトのストレージクラスがインストールされているが、管理者は独自のデフォルトストレージクラスを作成することができる。
  • ツールがPVCを監視し、しばらくしてもバインドされないことをユーザーに表示する。これはクラスターが動的ストレージをサポートしない(この場合ユーザーは対応するPVを作成するべき)、もしくはクラスターがストレージシステムを持っていない(この場合ユーザーはPVCを必要とする設定をデプロイできない)可能性があることを示す。

    次の項目

リファレンス

3 - 投影ボリューム

このドキュメントでは、Kubernetesの投影ボリュームについて説明します。ボリュームに精通していることをお勧めします。

概要

ボリュームは、いくつかの既存の投影ボリュームソースを同じディレクトリにマップします。

現在、次のタイプのボリュームソースを投影できます。

すべてのソースは、Podと同じnamespaceにある必要があります。詳細はall-in-one volumeデザインドキュメントを参照してください。

secret、downwardAPI、およびconfigMapを使用した構成例

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - downwardAPI:
          items:
            - path: "labels"
              fieldRef:
                fieldPath: metadata.labels
            - path: "cpu_limit"
              resourceFieldRef:
                containerName: container-test
                resource: limits.cpu
      - configMap:
          name: myconfigmap
          items:
            - key: config
              path: my-group/my-config

構成例:デフォルト以外のアクセス許可モードが設定されたsecret

apiVersion: v1
kind: Pod
metadata:
  name: volume-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: all-in-one
      mountPath: "/projected-volume"
      readOnly: true
  volumes:
  - name: all-in-one
    projected:
      sources:
      - secret:
          name: mysecret
          items:
            - key: username
              path: my-group/my-username
      - secret:
          name: mysecret2
          items:
            - key: password
              path: my-group/my-password
              mode: 511

各投影ボリュームソースは、specのsourcesにリストされています。パラメーターは、2つの例外を除いてほぼ同じです。

  • secretについて、ConfigMapの命名と一致するようにsecretNameフィールドがnameに変更されました。
  • defaultModeはprojectedレベルでのみ指定でき、各ボリュームソースには指定できません。ただし上に示したように、個々の投影ごとにmodeを明示的に設定できます。

TokenRequestProjection機能が有効になっている場合、現在のサービスアカウントトークンを指定されたパスのPodに挿入できます。例えば:

apiVersion: v1
kind: Pod
metadata:
  name: sa-token-test
spec:
  containers:
  - name: container-test
    image: busybox
    volumeMounts:
    - name: token-vol
      mountPath: "/service-account"
      readOnly: true
  serviceAccountName: default
  volumes:
  - name: token-vol
    projected:
      sources:
      - serviceAccountToken:
          audience: api
          expirationSeconds: 3600
          path: token

この例のPodには、挿入されたサービスアカウントトークンを含む投影ボリュームがあります。このトークンはPodのコンテナがKubernetes APIサーバーにアクセスするために使用できます。このaudienceフィールドにはトークンの受信対象者が含まれています。トークンの受信者は、トークンのaudienceフィールドで指定された識別子で自分自身であるかを識別します。そうでない場合はトークンを拒否します。このフィールドはオプションで、デフォルトではAPIサーバーの識別子が指定されます。

expirationSecondsはサービスアカウントトークンが有効であると予想される期間です。 デフォルトは1時間で、最低でも10分(600秒)でなければなりません。 管理者は、APIサーバーに--service-account-max-token-expirationオプションを指定することで、その最大値を制限することも可能です。 pathフィールドは、投影ボリュームのマウントポイントへの相対パスを指定します。

SecurityContextの相互作用

サービスアカウントの投影ボリューム拡張でのファイル権限処理の提案により、正しい所有者権限が設定された投影ファイルが導入されました。

Linux

投影ボリュームがあり、PodのSecurityContextRunAsUserが設定されているLinux Podでは、投影されたファイルには、コンテナユーザーの所有権を含む正しい所有権が設定されます。

Windows

投影ボリュームを持ち、PodのSecurityContextRunAsUsernameを設定したWindows Podでは、Windowsのユーザーアカウント管理方法により所有権が強制されません。 Windowsは、ローカルユーザーとグループアカウントをセキュリティアカウントマネージャー(SAM)と呼ばれるデータベースファイルに保存し、管理します。 各コンテナはSAMデータベースの独自のインスタンスを維持し、コンテナの実行中はホストはそのインスタンスを見ることができません。 Windowsコンテナは、OSのユーザーモード部分をホストから分離して実行するように設計されており、そのため仮想SAMデータベースを維持することになります。 そのため、ホスト上で動作するkubeletには、仮想化されたコンテナアカウントのホストファイル所有権を動的に設定する機能がありません。 ホストマシン上のファイルをコンテナと共有する場合は、C:\以外の独自のボリュームマウントに配置することをお勧めします。

デフォルトでは、投影ボリュームファイルの例に示されているように、投影されたファイルには次の所有権があります。

PS C:\> Get-Acl C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt | Format-List

Path   : Microsoft.PowerShell.Core\FileSystem::C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt
Owner  : BUILTIN\Administrators
Group  : NT AUTHORITY\SYSTEM
Access : NT AUTHORITY\SYSTEM Allow  FullControl
         BUILTIN\Administrators Allow  FullControl
         BUILTIN\Users Allow  ReadAndExecute, Synchronize
Audit  :
Sddl   : O:BAG:SYD:AI(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200a9;;;BU)

これは、ContainerAdministratorのようなすべての管理者ユーザーが読み取り、書き込み、および実行アクセス権を持ち、非管理者ユーザーが読み取りおよび実行アクセス権を持つことを意味します。

4 - CSI Volume Cloning

このドキュメントではKubernetesで既存のCSIボリュームの複製についてのコンセプトを説明します。このページを読む前にあらかじめボリュームについてよく理解していることが望ましいです。

イントロダクション

CSIのボリューム複製機能は、ユーザーがボリュームの複製を作成することを示すdataSourceフィールドで既存のPVCを指定するためのサポートを追加します。

複製は既存のKubernetesボリュームの複製として定義され、標準のボリュームと同じように使用できます。唯一の違いは、プロビジョニング時に「新しい」空のボリュームを作成するのではなく、バックエンドデバイスが指定されたボリュームの正確な複製を作成することです。

複製の実装は、Kubernetes APIの観点からは新しいPVCの作成時に既存のPVCをdataSourceとして指定する機能を追加するだけです。ソースPVCはバインドされており、使用可能でなければなりません(使用中ではありません)。

この機能を使用する場合、ユーザーは次のことに注意する必要があります:

  • 複製のサポート(VolumePVCDataSource)はCSIドライバーのみです。
  • 複製のサポートは動的プロビジョニングのみです。
  • CSIドライバーはボリューム複製機能を実装している場合としていない場合があります。
  • PVCは複製先のPVCと同じ名前空間に存在する場合にのみ複製できます(複製元と複製先は同じ名前空間になければなりません)。
  • 複製は同じストレージクラス内でのみサポートされます。
    • 宛先ボリュームは、ソースと同じストレージクラスである必要があります。
    • デフォルトのストレージクラスを使用でき、仕様ではstorageClassNameを省略できます。
  • 複製は同じVolumeMode設定を使用する2つのボリューム間でのみ実行できます(ブロックモードのボリュームを要求する場合、ソースもブロックモードである必要があります)。

プロビジョニング

複製は同じ名前空間内の既存のPVCを参照するdataSourceを追加すること以外は他のPVCと同様にプロビジョニングされます。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
    name: clone-of-pvc-1
    namespace: myns
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: cloning
  resources:
    requests:
      storage: 5Gi
  dataSource:
    kind: PersistentVolumeClaim
    name: pvc-1

このyamlの作成結果は指定された複製元であるpvc-1と全く同じデータを持つclone-of-pvc-1という名前の新しいPVCです。

使い方

新しいPVCが使用可能になると、複製されたPVCは他のPVCと同じように利用されます。またこの時点で新しく作成されたPVCは独立したオブジェクトであることが期待されます。元のdataSource PVCを考慮せず個別に利用、複製、スナップショット、削除できます。これはまた複製元が新しく作成された複製にリンクされておらず、新しく作成された複製に影響を与えずに変更または削除できることを意味します。

5 - VolumeSnapshotClass

このドキュメントでは、KubernetesにおけるVolumeSnapshotClassのコンセプトについて説明します。
関連する項目として、Volumeのスナップショットストレージクラスも参照してください。

イントロダクション

StorageClassはVolumeをプロビジョンするときに、ストレージの"クラス"に関する情報を記述する方法を提供します。それと同様に、VolumeSnapshotClassではVolumeSnapshotをプロビジョンするときに、ストレージの"クラス"に関する情報を記述する方法を提供します。

VolumeSnapshotClass リソース

VolumeSnapshotClassdriverdeletionPolicyparametersフィールドを含み、それらは、そのクラスに属するVolumeSnapshotが動的にプロビジョンされるときに使われます。

VolumeSnapshotClassオブジェクトの名前は重要であり、それはユーザーがどのように特定のクラスをリクエストできるかを示したものです。管理者は初めてVolumeSnapshotClassオブジェクトを作成するときに、その名前と他のパラメーターをセットし、そのオブジェクトは一度作成されるとそのあと更新することができません。

管理者は、バインド対象のクラスを1つもリクエストしないようなVolumeSnapshotのために、デフォルトのVolumeSnapshotClassを指定することができます。

apiVersion: snapshot.storage.k8s.io/v1beta1
kind: VolumeSnapshotClass
metadata:
  name: csi-hostpath-snapclass
driver: hostpath.csi.k8s.io
deletionPolicy: Delete
parameters:

Driver

VolumeSnapshotClassは、VolumeSnapshotをプロビジョンするときに何のCSIボリュームプラグインを使うか決定するためのdriverフィールドを持っています。このフィールドは必須となります。

DeletionPolicy

VolumeSnapshotClassにはdeletionPolicyがあります。これにより、バインドされている VolumeSnapshotオブジェクトが削除されるときに、VolumeSnapshotContentがどうなるかを設定することができます。VolumeSnapshotのdeletionPolicyは、RetainまたはDeleteのいずれかです。このフィールドは指定しなければなりません。

deletionPolicyがDeleteの場合、元となるストレージスナップショットは VolumeSnapshotContentオブジェクトとともに削除されます。deletionPolicyがRetainの場合、元となるスナップショットとVolumeSnapshotContentの両方が残ります。

Parameters

VolumeSnapshotClassは、そのクラスに属するVolumeSnapshotを指定するパラメータを持っています。 driverに応じて様々なパラメータを使用できます。

6 - ボリュームの動的プロビジョニング(Dynamic Volume Provisioning)

ボリュームの動的プロビジョニングにより、ストレージ用のボリュームをオンデマンドに作成することができます。 動的プロビジョニングなしでは、クラスター管理者はクラウドプロバイダーまたはストレージプロバイダーに対して新規のストレージ用のボリュームとPersistentVolumeオブジェクトを作成するように手動で指示しなければなりません。動的プロビジョニングの機能によって、クラスター管理者がストレージを事前にプロビジョンする必要がなくなります。その代わりに、ユーザーによってリクエストされたときに自動でストレージをプロビジョンします。

バックグラウンド

ボリュームの動的プロビジョニングの実装はstorage.k8s.ioというAPIグループ内のStorageClassというAPIオブジェクトに基づいています。クラスター管理者はStorageClassオブジェクトを必要に応じていくつでも定義でき、各オブジェクトはボリュームをプロビジョンするVolumeプラグイン (別名プロビジョナー)と、プロビジョンされるときにプロビジョナーに渡されるパラメータを指定します。 クラスター管理者はクラスター内で複数の種類のストレージ(同一または異なるストレージシステム)を定義し、さらには公開でき、それらのストレージはパラメータのカスタムセットを持ちます。この仕組みにおいて、エンドユーザーはストレージがどのようにプロビジョンされるか心配する必要がなく、それでいて複数のストレージオプションから選択できることを保証します。

StorageClassに関するさらなる情報はStorage Classを参照ください。

動的プロビジョニングを有効にする

動的プロビジョニングを有効にするために、クラスター管理者はユーザーのために1つまたはそれ以上のStorageClassを事前に作成する必要があります。StorageClassオブジェクトは、動的プロビジョニングが実行されるときに、どのプロビジョナーが使用されるべきか、またどのようなパラメーターをプロビジョナーに渡すべきか定義します。StorageClassオブジェクトの名前は、有効なDNSサブドメイン名である必要があります。

下記のマニフェストでは標準的な永続化ディスクをプロビジョンする"slow"というStorageClassを作成します。

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

下記のマニフェストではSSDを使った永続化ディスクをプロビジョンする"fast"というStorageClassを作成します。

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

動的プロビジョニングの使用

ユーザーはPersistentVolumeClaimリソース内でStorageClassを含むことで、動的にプロビジョンされたStorageをリクエストできます。Kubernetes v1.6以前では、この機能はvolume.beta.kubernetes.io/storage-classアノテーションを介して使うことができました。しかしこのアノテーションではv1.6から廃止になりました。その代わりユーザーは現在ではPersistentVolumeClaimオブジェクトのstorageClassNameを使う必要があります。このフィールドの値は、管理者によって設定されたStorageClassの名前と一致しなければなりません(下記のセクションも参照ください)。

"fast"というStorageClassを選択するために、例としてユーザーは下記のPersistentVolumeClaimを作成します。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim1
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast
  resources:
    requests:
      storage: 30Gi

このリソースによってSSDのような永続化ディスクが自動的にプロビジョンされます。このリソースが削除された時、そのボリュームは削除されます。

デフォルトの挙動

動的プロビジョニングは、もしStorageClassが1つも指定されていないときに全てのPersistentVolumeClaimが動的にプロビジョンされるようにクラスター上で有効にできます。クラスター管理者は、下記を行うことによりこのふるまいを有効にできます。

管理者はStorageClassに対してstorageclass.kubernetes.io/is-default-classアノテーションをつけることで、デフォルトのStorageClassとしてマーキングできます。 デフォルトのStorageClassがクラスター内で存在し、かつユーザーがPersistentVolumeClaimリソースでstorageClassNameを指定しなかった場合、DefaultStorageClassという管理コントローラーはstorageClassNameフィールドの値をデフォルトのStorageClassを指し示すように自動で追加します。

注意点として、クラスター上では最大1つしかデフォルト のStorageClassが指定できず、storageClassNameを明示的に指定しないPersistentVolumeClaimは作成することもできません。

トポロジーに関する注意

マルチゾーンクラスター内では、Podは単一のリージョン内のゾーンをまたいでしか稼働できません。シングルゾーンのStorageバックエンドはPodがスケジュールされるゾーン内でプロビジョンされる必要があります。これはVolume割り当てモードを設定することにより可能となります。

7 - ストレージ容量

ストレージ容量は、Podが実行されるノードごとに制限があったり、大きさが異なる可能性があります。たとえば、NASがすべてのノードからはアクセスできなかったり、初めからストレージがノードローカルでしか利用できない可能性があります。

FEATURE STATE: Kubernetes v1.19 [alpha]

このページでは、Kubernetesがストレージ容量を追跡し続ける方法と、スケジューラーがその情報を利用して、残りの未作成のボリュームのために十分なストレージ容量へアクセスできるノード上にどのようにPodをスケジューリングするかについて説明します。もしストレージ容量の追跡がなければ、スケジューラーは、ボリュームをプロビジョニングするために十分な容量のないノードを選択してしまい、スケジューリングの再試行が複数回行われてしまう恐れがあります。

ストレージ容量の追跡は、Container Storage Interface(CSI)向けにサポートされており、CSIドライバーのインストール時に有効にする必要があります

API

この機能には、以下の2つのAPI拡張があります。

  • CSIStorageCapacityオブジェクト: このオブジェクトは、CSIドライバーがインストールされた名前空間に生成されます。各オブジェクトには1つのストレージクラスに対する容量の情報が含まれ、そのストレージに対してどのノードがアクセス権を持つかが定められています。

  • CSIDriverSpec.StorageCapacityフィールド: trueに設定すると、Kubernetesのスケジューラーが、CSIドライバーを使用するボリュームに対してストレージ容量を考慮するようになります。

スケジューリング

ストレージ容量の情報がKubernetesのスケジューラーで利用されるのは、以下のすべての条件を満たす場合です。

  • CSIStorageCapacityフィーチャーゲートがtrueである
  • Podがまだ作成されていないボリュームを使用する時
  • そのボリュームが、CSIドライバーを参照し、volume binding modeWaitForFirstConsumerを使うStorageClassを使用している
  • ドライバーに対するCSIDriverオブジェクトのStorageCapacityがtrueに設定されている

その場合、スケジューラーはPodに対して、十分なストレージ容量が利用できるノードだけを考慮するようになります。このチェックは非常に単純で、ボリュームのサイズと、CSIStorageCapacityオブジェクトに一覧された容量を、ノードを含むトポロジーで比較するだけです。

volume binding modeがImmediateのボリュームの場合、ストレージドライバーはボリュームを使用するPodとは関係なく、ボリュームを作成する場所を決定します。次に、スケジューラーはボリュームが作成された後、Podをボリュームが利用できるノードにスケジューリングします。

CSI ephemeral volumesの場合、スケジューリングは常にストレージ容量を考慮せずに行われます。このような動作になっているのは、このボリュームタイプはノードローカルな特別なCSIドライバーでのみ使用され、そこでは特に大きなリソースが必要になることはない、という想定に基づいています。

再スケジューリング

WaitForFirstConsumerボリュームがあるPodに対してノードが選択された場合は、その決定はまだ一時的なものです。次のステップで、CSIストレージドライバーに対して、選択されたノード上でボリュームが利用可能になることが予定されているというヒントを使用してボリュームの作成を要求します。

Kubernetesは古い容量の情報をもとにノードを選択する場合があるため、実際にはボリュームが作成できないという可能性が存在します。その場合、ノードの選択がリセットされ、KubernetesスケジューラーはPodに割り当てるノードを再び探します。

制限

ストレージ容量を追跡することで、1回目の試行でスケジューリングが成功する可能性が高くなります。しかし、スケジューラーは潜在的に古い情報に基づいて決定を行う可能性があるため、成功を保証することはできません。通常、ストレージ容量の情報が存在しないスケジューリングと同様のリトライの仕組みによって、スケジューリングの失敗に対処します。

スケジューリングが永続的に失敗する状況の1つは、Podが複数のボリュームを使用する場合で、あるトポロジーのセグメントで1つのボリュームがすでに作成された後、もう1つのボリュームのために十分な容量が残っていないような場合です。この状況から回復するには、たとえば、容量を増加させたり、すでに作成されたボリュームを削除するなどの手動での対応が必要です。この問題に自動的に対処するためには、まだ追加の作業が必要となっています。

ストレージ容量の追跡を有効にする

ストレージ容量の追跡はアルファ機能であり、CSIStorageCapacityフィーチャーゲートstorage.k8s.io/v1alpha1 API groupを有効にした場合にのみ、有効化されます。詳細については、--feature-gatesおよび--runtime-config kube-apiserverパラメータを参照してください。

Kubernetesクラスターがこの機能をサポートしているか簡単に確認するには、以下のコマンドを実行して、CSIStorageCapacityオブジェクトを一覧表示します。

kubectl get csistoragecapacities --all-namespaces

クラスターがCSIStorageCapacityをサポートしていれば、CSIStorageCapacityのリストが表示されるか、次のメッセージが表示されます。

No resources found

もしサポートされていなければ、代わりに次のエラーが表示されます。

error: the server doesn't have a resource type "csistoragecapacities"

クラスター内で機能を有効化することに加えて、CSIドライバーもこの機能をサポートしている必要があります。詳細については、各ドライバーのドキュメントを参照してください。

次の項目