ローカル SSD の使用

このページでは、Kubernetes でのローカル SSD サポートの概要と、Google Kubernetes Engine(GKE)でローカル SSD を使用する方法について説明します。

概要

ローカル SSD は、クラスタ内のすべてのノードに高性能な一時ストレージを提供します。ローカル SSD は、標準的なディスクより高いスループットと低いレイテンシを実現します。ローカル SSD はローカル キャッシュと処理を行うワークロードに適しています。

クラスタのマシンタイプ制限とプロジェクトの割り当ての枠内で、ローカル SSD を使用したノードプールを作成できます。

  • ローカル SSD に書き込まれたデータはエフェメラルであり、ノードが削除、修復、アップグレードされた場合や、回復不能なエラーが発生した場合には保持されません。

  • ローカル SSD は 1 つのノードのみに接続され、ノード自体はエフェメラルになります。ワークロードはいつでも別のノードでスケジュールできます。

ローカル SSD の利点と制限の詳細については、Compute Engine ドキュメントのローカル SSD をご覧ください。

ローカル SSD を使用するクラスタの作成

Google Cloud Console または gcloud コマンドライン ツールを使用して、ローカル SSD を使用するようにクラスタを作成または更新できます。

Console

Cloud Console の GKE メニューから、ローカル SSD を使用するクラスタまたはノードプールを作成できます。

デフォルト プールでローカル SSD ディスクを使用するクラスタを作成するには:

  1. Cloud Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. [クラスタを作成] ボタンをクリックします。

  3. ナビゲーション パネルで、[ノードプール] の下にある [default-pool] をクリックします。

  4. [ノード数] に「2」と入力します。

  5. ナビゲーション パネルの [default-pool] の下の [ノード] をクリックします。

  6. [CPU プラットフォームと GPU] メニューを展開します。

  7. [ローカル SSD ディスク] に、必要な SSD の数を絶対数で入力します。

  8. [作成] をクリックします。

既存のクラスタでローカル SSD ディスクを使用したノードプールを作成する手順は次のとおりです。

  1. Cloud Console で Google Kubernetes Engine のメニューに移動します。

    Google Kubernetes Engine のメニューに移動

  2. 目的のクラスタを選択します。

  3. [編集] をクリックします。

  4. [ノードプール] で、[ノードプールを追加] をクリックします。

  5. [サイズ] に「1」と入力します。

  6. [ローカル SSD ディスク(ノード単位)] に、必要な SSD の数を絶対数で入力します。

  7. [保存] をクリックします。

gcloud

ローカル SSD を使用するクラスタまたはノードプールを gcloud で作成するには、--local-ssd count フラグを指定します。--local-ssd-count には、ノードごとに作成するローカル SSD の数を指定します。最大数は、マシンタイプとリージョンによって異なります。ノードが作成されると、ローカル SSD が自動的にフォーマットされ、マウント ポイント(最初のディスク用には /mnt/disks/ssd0、2 番目のディスク用には /mnt/disks/ssd1 など)でノードのファイル システムにマウントされます。

デフォルト プールがローカル SSD ディスクを使用するクラスタを作成するコマンドは次のとおりです。

gcloud container clusters create cluster-name \
  --num-nodes 2 \
  --local-ssd-count number-of-disks

既存のクラスタでローカル SSD ディスクを使用するノードプールを作成するには、次のコマンドを実行します。

gcloud container node-pools create pool-name \
  --cluster cluster-name \
  --num-nodes 1 \
  --local-ssd-count number-of-disks

以下を置き換えます。

  • cluster-name: クラスタの名前。
  • pool-name: 新しいノードプールの名前。
  • number-of-disks: 各ノードでプロビジョニングするローカル SSD ディスクの数。

ローカル SSD で一時ストレージを使用したノードプールの作成

バージョン 1.18 以降、一時ストレージにローカル SSD を使用するように GKE ノードプールを構成できます。

ローカル SSD で一時ストレージを使用してノードプールを作成するには、次のコマンドを実行します。

gcloud beta container node-pools create pool-name \
    --ephemeral-storage local-ssd-count=number-of-disks

以下を置き換えます。

  • pool-name: 新しいノードプールの名前。
  • number-of-disks: 各ノードでプロビジョニングするローカル SSD ディスクの数。

ノードプール内のノードは、cloud.google.com/gke-ephemeral-storage-local-ssd ラベルを使用して作成されます。次のコマンドを実行すると、ラベルが確認できます。

kubectl describe node node-name

Windows Server クラスタ用のローカル SSD のフォーマット

Windows Server ノードプールを実行するクラスタでローカル SSD を使用する場合は、ノードにログインしてディスクをフォーマットしてから使用する必要があります。次の例では、ローカル SSD ディスクが NTFS ファイル システムでフォーマットされています。ディスクにディレクトリを作成することもできます。この例では、ディレクトリはディスク D にあります。

PS C:\> Get-Disk | Where partitionstyle -eq 'raw' | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem ntfs -Confirm:$false
PS C:\> mkdir D:\test-ss

ローカル SSD の使用

次のセクションでは、GKE でローカル SSD を使用する方法について説明します。

次のいずれかの方法でローカル SSD にアクセスできます。

  • hostpath ボリュームの使用。次の場合に推奨されます。

    • ワークロードで DaemonSet が使用される場合。
    • ワークロードで専用ノードプールが使用される場合。DaemonSet のすべてのインスタンスで、同じパスを使用してローカル SSD のすべてにアクセスする必要があります。
  • local PersistentVolumes の使用。これは、次の場合に推奨されます。

    • StatefulSet と volumeClaimTemplates を使用するワークロードの場合。
    • ノードプールを共有するワークロードの場合。各ローカル SSD は PersistentVolumeClaim(PVC)を通じて予約可能です。Pod 仕様では個別のホストパスが直接エンコードされません。
    • ポッドで同じローカル SSD に対するデータ グラビティが必要とされる場合。ポッドは常にローカルの PersistentVolume と同じノードにスケジュールされます。
  • 一時ストレージemptyDir Volume (GKE バージョン 1.18 ベータ版以降で利用可能)として使用する。これは、次の場合に推奨されます。

    • 高パフォーマンスの一時スクラッチ領域が必要なアプリケーション。

    この機能は、ローカル SSD にノード一時ストレージをマウントするノードプールを構成します。emptyDir を使用するポッドは、ローカル SSD を透過的に使用します。これは、そのノードプール内のすべてのノードのすべてのポッドに当てはまります。一部の Pod でローカル SSD emptyDir Volume を使用し、他のポッドで従来の emptyDir を使用することはできません。従来の emptyDir Volume を使用しないワークロードの場合は、これらのワークロードを別のノードプールにスケジュールします。

hostPath ボリュームの使用例

次の例は、Windows と Linux での hostPath ボリュームの使用方法を示しています。

Linux

3 つのローカル SSD を使用するノードプールを作成する場合、ホスト OS では /mnt/disks/ssd0/mnt/disks/ssd1/mnt/disks/ssd2 にディスクがマウントされます。Kubernetes コンテナは、オブジェクトの構成ファイルで定義されている hostPath パラメータに従ってディスクにアクセスします。

この Pod 構成ファイルの例では、ローカル SSD /mnt/disks/ssd0 を参照します。

apiVersion: v1
kind: Pod
metadata:
  name: "test-ssd"
spec:
  containers:
  - name: "shell"
    image: "ubuntu:14.04"
    command: ["/bin/sh", "-c"]
    args: ["echo 'hello world' > /test-ssd/test.txt && sleep 1 && cat /test-ssd/test.txt"]
    volumeMounts:
    - mountPath: "/test-ssd/"
      name: "test-ssd"
  volumes:
  - name: "test-ssd"
    hostPath:
      path: "/mnt/disks/ssd0"
  nodeSelector:
    cloud.google.com/gke-local-ssd: "true"

Windows

apiVersion: v1
kind: Pod
metadata:
  name: "test-ssd"
spec:
  containers:
  - name: "test"
    image: "mcr.microsoft.com/windows/servercore/iis"
    volumeMounts:
    - mountPath: "/test-ssd/"
      name: "test-ssd"
  volumes:
  - name: "test-ssd"
    hostPath:
      path: "d:\\test-ssd"
  nodeSelector:
    cloud.google.com/gke-local-ssd: "true"
    kubernetes.io/os: windows

ローカル PersistentVolumes の使用例

ローカル SSD を PersistentVolume として指定できます。

ローカル SSD から PersistentVolume を作成するには、PersistentVolume を手動で作成するか、ローカル Volume の静的プロビジョナーを実行します。

制限事項

  • 現在、ローカル PersistentVolumes ではクラスタの自動スケーリング動的プロビジョニングはサポートされていません。

  • GKE クラスタのアップグレードやノードの修復を行うと Compute Engine インスタンスが削除され、これによってローカル SSD のデータもすべて削除されます。

  • ローカル SSD を永続データに使用するクラスタやノードプールでは、ノードの自動アップグレードノードの自動修復を有効にしないでください。まずアプリケーション データをバックアップしてから、データを新しいクラスタやノードプールに復元する必要があります。

  • ノードの削除、アップグレード、修復、スケールダウンが行われても、ローカル PersistentVolume オブジェクトは自動的にクリーンアップされません。削除されたノードに関連付けられている古いローカル PersistentVolume オブジェクトを定期的にスキャンし、削除することをおすすめします。

PersistentVolume を手動で作成する

クラスタ内の各ノードで、ローカル SSD ごとに PersistentVolume を手動で作成できます。

特定ノードのローカル SSD を参照するには、PersistentVolume オブジェクトの nodeAffinity フィールドを使用します。たとえば、次の Linux の例では、ノード gke-test-cluster-default-pool-926ddf80-f166 上の /mnt/disks/ssd0 にマウントされたローカル SSD の PersistentVolume 仕様は次のようになります。

Linux

apiVersion: v1
kind: PersistentVolume
metadata:
  name: "example-local-pv"
spec:
  capacity:
    storage: 375Gi
  accessModes:
  - "ReadWriteOnce"
  persistentVolumeReclaimPolicy: "Retain"
  storageClassName: "local-storage"
  local:
    path: "/mnt/disks/ssd0"
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: "kubernetes.io/hostname"
          operator: "In"
          values: "gke-test-cluster-default-pool-926ddf80-f166"

Windows

apiVersion: v1
kind: PersistentVolume
metadata:
  name: ssd-local-pv
spec:
  capacity:
    storage: 375Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: "d:\\test-ssd"
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - gke-gke-cluster-windows-dds-2263bc7c-wq6m
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: ssd-local-claim
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: local-storage
  resources:
    requests:
      storage: 37Gi

これで、ディスクにアクセスする Pod を作成できるようになりました。Pod を Windows Server ノードに正しくスケジュールするには、ノードセレクタを Pod 仕様に追加する必要があります。

apiVersion: v1
kind: Pod
metadata:
  name: "test-ssd"
spec:
  containers:
  - name: "test"
    image: "mcr.microsoft.com/windows/servercore/iis"
    volumeMounts:
    - mountPath: "/test-ssd/"
      name: "test-ssd"
  volumes:
  - name: "test-ssd"
    persistentVolumeClaim:
      claimName: ssd-local-claim
  nodeSelector:
    cloud.google.com/gke-local-ssd: "true"
  tolerations:
  - key: "node.kubernetes.io/os"
    value: "windows"
    operator: "Equal"
    effect: "NoSchedule"

PersistentVolume を削除する場合は、手動でディスクからデータを消去する必要があります。

ローカル Volume の静的プロビジョナーを実行する

ローカル ボリュームの静的プロビジョナーを使用して、ローカル SSD の PersistentVolume を自動的に作成できます。プロビジョナーは、各ノードのローカル SSD の管理、それらの PersistentVolume の作成と削除、PersistentVolume の消去時のローカル SSD 上のデータのクリーンアップを行う DaemonSet です。

ローカル ボリュームの静的プロビジョナーを実行する手順は次のとおりです。

  1. gke.yaml 仕様を sig-storage-local-static-provisioner repo からダウンロードして、必要に応じて仕様の namespace フィールドを変更します。

    仕様には次の情報が含まれます。

    • プロビジョナーの ServiceAccount
    • 次を行う権限の ClusterRole と ClusterRoleBindings
      • PersistentVolume オブジェクトの作成と削除
      • Node オブジェクトの取得
    • GKE のプロビジョナー設定の ConfigMap
    • プロビジョナーを実行するための DaemonSet
  2. プロビジョナーをデプロイします。

    kubectl apply -f gke.yaml
    

プロビジョナーが正常に実行されると、クラスタ内の各ローカル SSD に PersistentVolume オブジェクトが作成されます。

遅延ボリューム バインディングを有効にする

スケジューリングを改善するには、volumeBindingMode: WaitForFirstConsumer も使用して StorageClass を作成することおすすめします。これにより、Pod のスケジューリング時点まで PersistentVolumeClaim(PVC)バインディングが遅延され、Pod を実行できる適切なノードからローカル SSD が選択されるようになります。この強化されたスケジューリング動作により、実行可能な Pod 用のノードの選択時に、どのノードに使用可能なローカル SSD があるかを踏まえて、Pod の CPU とメモリのリクエスト、ノード アフィニティ、Pod アフィニティと反アフィニティ、複数の PVC リクエストが考慮されます。

次の例では、遅延ボリュームのバインディング モードを使用します。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: "local-scsi"
provisioner: "kubernetes.io/no-provisioner"
volumeBindingMode: "WaitForFirstConsumer"

Windows Server ノードプールがあるクラスタを使用する場合は、StorageClass を作成する必要があります。デフォルトの StorageClass はファイル システム タイプとして ext4 を使用しますが、ext4 は Linux コンテナに対してのみ動作するからです。

次の storageclass-name という名前の YAML ファイルは、ファイル ストレージ タイプが NTFS の Compute Engine 永続ディスクを使用します。この StorageClass は、Windows クラスタを操作するときに使用できます。

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: storageclass-name
parameters:
  type: pd-standard
  fstype: NTFS
provisioner: kubernetes.io/gce-pd
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumer

遅延バインディングを使用して StorageClass を作成するには、YAML マニフェストをローカル ファイルに保存して、次のコマンドを使用してクラスタに適用します。

kubectl apply -f filename

emptyDir Volume として一時ストレージを使用する例

emptyDir Volume など、一時ストレージにローカル SSD を使用するように GKE ノードプールを構成できます。

次に、emptyDircloud.google.com/gke-ephemeral-storage-local-ssd のノードセレクタを使用するポッドの YAML ファイルの例を示します。Deployment や StatefulSet に対しても同様の手法を適用できます。

apiVersion: v1
kind: Pod
metadata:
  name: pod-name
spec:
  containers:
    - name: container-name
      image: "k8s.gcr.io/pause"
      resources:
        requests:
          ephemeral-storage: "400Gi"
      volumeMounts:
        - mountPath: /cache
          name: scratch-volume
  nodeSelector:
    cloud.google.com/gke-ephemeral-storage-local-ssd: "true"
  volumes:
    - name: scratch-volume
      emptyDir: {}

次のステップ