ローカル SSD を使用する raw ブロック ストレージをプロビジョニングして使用する


このページでは、Google Kubernetes Engine(GKE)クラスタにローカル SSD ストレージをプロビジョニングする方法と、クラスタ内のノードにアタッチされたローカル SSD を使用する raw ブロック ストレージのデータを消費するようにワークロードを構成する方法について説明します。

このローカル SSD オプションを使用すると、基盤となるストレージをより詳細に管理でき、Pod 用の独自のノードレベルのキャッシュを構築して、アプリケーションのパフォーマンスを向上させることができます。このオプションはカスタマイズすることも可能で、その場合は必要に応じて DaemonSet を実行して RAID を構成し、ディスクをフォーマットして、ローカル SSD ディスクにファイル システムをインストールします。

GKE での raw ブロック アクセスに対するローカル SSD のサポートの詳細については、ローカル SSD についてをご覧ください。

始める前に

作業を始める前に、次のことを確認してください。

  • Google Kubernetes Engine API を有効にします。
  • Google Kubernetes Engine API の有効化
  • このタスクに Google Cloud CLI を使用する場合は、gcloud CLI をインストールして初期化します。すでに gcloud CLI をインストールしている場合は、gcloud components update を実行して最新のバージョンを取得します。

ローカル SSD を使用する raw ブロック ストレージを持つクラスタまたはノードプールを作成する

--local-nvme-ssd-block オプションを指定して gcloud CLI を使用し、ローカル SSD を使用する raw ブロック ストレージを持つクラスタを作成します。

クラスタまたはノードプールを作成するために実行する gcloud CLI コマンドは、使用しているマシンタイプが属しているマシンシリーズの世代によって異なります。たとえば、N1 マシンタイプと N2 マシンタイプはそれぞれ第 1 世代と第 2 世代のマシンシリーズに属していますが、C3 マシンタイプは第 3 世代のマシンシリーズに属しています。

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

第 1 世代または第 2 世代

第 1 世代または第 2 世代のマシンシリーズのマシンタイプを使用する場合は、--local-nvme-ssd-block count=NUMBER_OF_DISKS オプションを指定してクラスタを作成します。このオプションは、各ノードにアタッチするローカル SSD ディスクの数を指定します。最大数は、マシンタイプとリージョンによって異なります

クラスタを作成するには、次の手順を実施します。

gcloud container clusters create CLUSTER_NAME \
    --local-nvme-ssd-block count=NUMBER_OF_DISKS \
    --machine-type=MACHINE_TYPE \
    --release-channel CHANNEL_NAME

次のように置き換えます。

  • CLUSTER_NAME: クラスタの名前。
  • NUMBER_OF_DISKS: 各ノードでプロビジョニングするローカル SSD ディスクの数。ディスクの最大数はマシンタイプとリージョンによって異なります
  • MACHINE_TYPE: 使用する第 1 世代または第 2 世代のマシンタイプ。デフォルトの e2-medium タイプではローカル SSD を使用できないため、このフィールドを指定する必要があります。
  • CHANNEL_NAME: 1.25.3-gke.1800 より後の GKE バージョンを含むリリース チャンネル

第 3 世代

第 3 世代のマシンシリーズのマシンタイプを使用する場合、count フィールドを指定せずに --local-nvme-ssd-block オプションを使用してクラスタを作成します。GKE は、VM シェイプに基づいてクラスタのローカル SSD 容量を自動的にプロビジョニングします。最大数は、マシンタイプとリージョンによって異なります

gcloud container clusters create CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --cluster-version CLUSTER_VERSION \
    --local-nvme-ssd-block

次のように置き換えます。

  • CLUSTER_NAME: クラスタの名前。
  • MACHINE_TYPE: 使用する第 3 世代のマシンシリーズのマシンタイプ。
  • CLUSTER_VERSION: 第 3 世代のマシンシリーズのマシンタイプでローカル SSD をサポートする GKE クラスタ バージョン

ローカル SSD を使用するノードプールを作成する

第 1 世代または第 2 世代

raw ブロック アクセス用にローカル SSD ディスクを使用するノードプールを作成するには、次のコマンドを実行します。

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --local-nvme-ssd-block count=NUMBER_OF_DISKS

次のように置き換えます。

  • POOL_NAME: 新しいノードプールの名前。
  • CLUSTER_NAME: クラスタの名前。
  • MACHINE_TYPE: 使用する第 1 世代または第 2 世代のマシンタイプ。ローカル SSD はデフォルトの e2-medium タイプでは使用できないため、このフィールドを指定する必要があります。
  • NUMBER_OF_DISKS: 各ノードでプロビジョニングするローカル SSD ディスクの数。ディスクの最大数はマシンタイプとリージョンによって異なります

第 3 世代

第 3 世代のマシンシリーズのマシンタイプを使用する場合、count フィールドを指定せずに --local-nvme-ssd-block オプションを使用してクラスタを作成します。

gcloud container node-pools create POOL_NAME \
    --cluster=CLUSTER_NAME \
    --machine-type=MACHINE_TYPE \
    --node-version NODE_VERSION \
    --local-nvme-ssd-block

次のように置き換えます。

  • POOL_NAME: 新しいノードプールの名前。
  • CLUSTER_NAME: クラスタの名前。
  • MACHINE_TYPE: 使用する第 3 世代のマシンシリーズのマシンタイプ。
  • NODE_VERSION: 第 3 世代のマシンシリーズのマシンタイプでローカル SSD をサポートする GKE ノードプールのバージョン

ノードプール内のノードは cloud.google.com/gke-local-nvme-ssd=true ラベル付きで作成されます。ラベルは、次のコマンドを実行して確認できます。

kubectl describe node NODE_NAME

ノードプールにアタッチされたローカル SSD ごとに、ホスト OS は、順序を表すフォルダの下のディスクにアクセスするためのシンボリック リンク(シムリンク)とユニバーサルな固有識別子(UUID)を使用するシンボリック リンクを作成します。たとえば、--local-nvme-ssd-block オプションを使用して 3 つのローカル SSD を使用するノードプールを作成する場合、ホスト OS はディスクに次のシンボリック リンクを作成します。

  • /dev/disk/by-id/google-local-ssd-block0
  • /dev/disk/by-id/google-local-ssd-block1
  • /dev/disk/by-id/google-local-ssd-block2

それに応じて、ホスト OS はディスク用の UUID を使用して次のシンボリック リンクも作成します。

  • /dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID1
  • /dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID2
  • /dev/disk/by-uuid/google-local-ssds-nvme-block/local-ssd-GENERATED_UUID3

これにより、固有識別子を使用してディスクに確実にアクセスできるようになります。

ローカル SSD ボリュームにアクセスする

次の例は、ローカル SSD を使用する raw ブロック ストレージにアクセスする方法を示しています。

ローカル PersistentVolumes

ローカル SSD ボリュームは、PersistentVolume を使用して Pod としてマウントできます。

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

ローカル PersistentVolumes の制限事項

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

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

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

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

PersistentVolume を手動で作成する

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

特定ノードのローカル SSD を参照するには、PersistentVolume オブジェクトの nodeAffinity フィールドを使用します。次の例は、Linux を実行するノードのローカル SSD の PersistentVolume 仕様を示しています。

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"

この例では、ローカル SSD ディスクが RAID 用に手動で構成され、フォーマットされて、ノード gke-test-cluster-default-pool-926ddf80-f166/mnt/disks/ssd0 にマウントされます。nodeAffinity フィールドは、ローカル SSD が RAID 用に手動で構成されているノードにワークロードを割り当てるために使用されます。クラスタにノードが 1 つしかない場合、またはすべてのノードで RAID を構成している場合、nodeAffinity フィールドは必要ありません。

対応する PersistenVolumeClaim の仕様は次のようになります。

  kind: PersistentVolumeClaim
  apiVersion: v1
  metadata:
    name: ssd-local-claim
  spec:
    accessModes:
    - ReadWriteOnce
    storageClassName: local-storage
    resources:
      requests:
        storage: 37Gi

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

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

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

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

  1. DaemonSet を使用して RAID を構成し、ディスクをフォーマットします。

    1. gke-daemonset-raid-disks.yaml 仕様をダウンロードします。
    2. RAID ディスクの DaemonSet をデプロイします。DaemonSet は、すべてのローカル SSD ディスクに RAID 0 アレイを設定し、デバイスを ext4 ファイルシステムにフォーマットします。

      kubectl create -f gke-daemonset-raid-disks.yaml
      
  2. gke-nvme-ssd-block-raid.yaml 仕様をダウンロードし、必要に応じて仕様の namespace フィールドを変更します。

    この仕様には、次のリソースが含まれています。

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

    kubectl create -f gke-nvme-ssd-block-raid.yaml
    

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

  4. 次の PersistentVolumeClaim マニフェストを provisioner-pvc-example.yaml として保存します。

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: PVC_NAME
    spec:
      accessModes:
      - ReadWriteOnce
      resources:
        requests:
          storage: 50Gi
      storageClassName: nvme-ssd-block
    

    PVC_NAME は、PersistentVolumeClaim の名前に置き換えます。

  5. PersistentVolumeClaim を作成します。

    kubectl create -f provisioner-pvc-example.yaml
    
  6. 次の Pod マニフェストを provisioner-pod-example.yaml として保存します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: POD_NAME
    spec:
      containers:
      - name: "shell"
        image: "ubuntu:14.04"
        command: ["/bin/sh", "-c"]
        args: ["echo 'hello world' > /cache/test.txt && sleep 1 && cat /cache/test.txt && sleep 3600"]
        volumeMounts:
        - mountPath: /cache
          name: local-ssd-storage
      volumes:
      - name: local-ssd-storage
        persistentVolumeClaim:
          claimName: PVC_NAME
    

    POD_NAME は、Pod の名前に置き換えます。

  7. Pod を作成します。

    kubectl create -f provisioner-pod-example.yaml
    

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

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

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

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

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

kubectl apply -f filename

トラブルシューティング

トラブルシューティングの手順については、GKE のストレージのトラブルシューティングをご覧ください。

次のステップ