ボリューム

コンテナ内のディスク上のファイルは一時的なものであり、コンテナ内で実行する場合、重要なアプリケーションでいくつかの問題が発生します。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指定されたパスにファイルが存在する必要があります。
SocketUNIXソケットは、指定されたパスに存在する必要があります。
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をデプロイする例に従ってください。

最終更新 February 03, 2022 at 11:36 AM PST: fix word mistakes (070853a03d)