ボリューム スナップショットを使用して Persistent Disk ストレージをバックアップする


このページでは、ボリューム スナップショットを使用して Persistent Disk ストレージをバックアップおよび復元する方法について説明します。

概要については、Kubernetes のボリューム スナップショットについての記事をご覧ください。

要件

GKE でボリューム スナップショットを使用するには、次の要件を満たす必要があります。

  • スナップショットをサポートする CSI ドライバを使用します。in-tree の Persistent Disk ドライバはスナップショットをサポートしていません。スナップショットを作成して管理するには、基盤となる PersistentVolumeClaim(PVC)と同じ CSI ドライバを使用する必要があります。

  • コントロール プレーンのバージョン 1.17 以降を使用します。Compute Engine Persistent Disk の CSI ドライバを使用するには、VolumeSnapshot で GKE バージョン 1.17.6-gke.4 以降を使用します。

  • スナップショットに使用する既存の PersistentVolumeClaim が必要です。スナップショット ソースに使用する PersistentVolume は、CSI ドライバによって管理される必要があります。CSI ドライバを使用しているかどうかを確認するには、PersistentVolume 仕様の csi セクションで driver: pd.csi.storage.gke.io または filestore.csi.storage.gke.io が指定されているかをチェックします。以降のセクションで説明するように、PersistentVolume が CSI ドライバによって動的にプロビジョニングされていれば、CSI ドライバによって管理されています。

制限事項

Compute Engine でのディスク スナップショットの作成に関する制限はすべて GKE にも適用されます。

ベスト プラクティス

GKE で Persistent Disk Volume のスナップショットを使用する場合は、Compute Engine のディスク スナップショットのベスト プラクティスに従ってください。

始める前に

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

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

ボリューム スナップショットの作成と使用

このドキュメントの例では、次の作業を行う方法について説明します。

  1. PersistentVolumeClaimDeployment を作成する
  2. Deployment が使用する PersistentVolume にファイルを追加する
  3. VolumeSnapshotClass を作成してスナップショットを構成する
  4. PersistentVolume のボリューム スナップショットを作成する
  5. テストファイルを削除する
  6. 作成したスナップショットに PersistentVolume を復元する。
  7. 復元が機能していることを確認する

ボリューム スナップショットを使用するには、次の手順を完了する必要があります。

  1. VolumeSnapshotClass オブジェクトを作成して、スナップショットの CSI ドライバと削除ポリシーを指定します。
  2. VolumeSnapshot オブジェクトを作成して、既存の PersistentVolumeClaim のスナップショットをリクエストします。
  3. PersistentVolumeClaim 内の VolumeSnapshot を参照して、そのスナップショットにボリュームを復元するか、スナップショットを使用して新しいボリュームを作成します。

PersistentVolumeClaimDeployment を作成する

  1. PersistentVolumeClaim オブジェクトを作成するには、次のマニフェストを my-pvc.yaml として保存します。

    Persistent Disk

     apiVersion: v1
     kind: PersistentVolumeClaim
     metadata:
       name: my-pvc
     spec:
       storageClassName: standard-rwo
       accessModes:
       - ReadWriteOnce
       resources:
         requests:
           storage: 1Gi
    

    この例では、Compute Engine Persistent Disk の CSI ドライバとともにデフォルトでインストールされた standard-rwo ストレージ クラスを使用します。詳細については、Compute Engine Persistent Disk の CSI ドライバの使用に関する記事をご覧ください。

    spec.storageClassName には、サポートされている CSI ドライバを使用するストレージ クラスを指定できます。

  2. 次のようにマニフェストを適用します。

    kubectl apply -f my-pvc.yaml
    
  3. Deployment を作成するには、次のマニフェストを my-deployment.yaml として保存します。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: hello-app
    spec:
      selector:
        matchLabels:
          app: hello-app
      template:
        metadata:
          labels:
            app: hello-app
        spec:
          containers:
          - name: hello-app
            image: google/cloud-sdk:slim
            args: [ "sleep", "3600" ]
            volumeMounts:
            - name: sdk-volume
              mountPath: /usr/share/hello/
          volumes:
          - name: sdk-volume
            persistentVolumeClaim:
              claimName: my-pvc
    
  4. 次のようにマニフェストを適用します。

    kubectl apply -f my-deployment.yaml
    
  5. Deployment のステータスを確認します。

    kubectl get deployment hello-app
    

    Deployment の準備が完了するまでに時間がかかることがあります。次のような出力が表示されるまで、上記のコマンドを実行します。

    NAME        READY   UP-TO-DATE   AVAILABLE   AGE
    hello-app   1/1     1            1           2m55s
    

ボリュームにテストファイルを追加する

  1. DeploymentPods を一覧表示します。

    kubectl get pods -l app=hello-app
    

    出力は次のようになります。

    NAME                         READY   STATUS    RESTARTS   AGE
    hello-app-6d7b457c7d-vl4jr   1/1     Running   0          2m56s
    
  2. Pod にテストファイルを作成します。

    kubectl exec POD_NAME \
        -- sh -c 'echo "Hello World!" > /usr/share/hello/hello.txt'
    

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

  3. ファイルが存在することを確認します。

    kubectl exec POD_NAME \
        -- sh -c 'cat /usr/share/hello/hello.txt'
    

    出力は次のようになります。

    Hello World!
    

VolumeSnapshotClass オブジェクトを作成する

VolumeSnapshotClass オブジェクトを作成して、ボリューム スナップショットの CSI ドライバと deletionPolicy を指定します。VolumeSnapshot オブジェクトの作成時に VolumeSnapshotClass オブジェクトを参照できます。

  1. 次のマニフェストを volumesnapshotclass.yaml として保存します。

    Persistent Disk

    バージョン 1.21 以降を実行しているクラスタには、v1 API バージョンを使用します。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshotClass
    metadata:
      name: my-snapshotclass
    driver: pd.csi.storage.gke.io
    deletionPolicy: Delete
    

    この例では以下の情報が表示されます。

    • driver フィールドは、スナップショットをプロビジョニングするために CSI ドライバによって使用されます。この例で、pd.csi.storage.gke.ioCompute Engine Persistent Disk の CSI ドライバを使用します。

    • deletionPolicy フィールドは、バインドされた VolumeSnapshot オブジェクトの削除時に、VolumeSnapshotContent オブジェクトとその基盤となるスナップショットを GKE でどのように処理するかを指示します。VolumeSnapshotContent オブジェクトと基盤となるスナップショットを削除するには、Delete を指定します。VolumeSnapshotContent とその基盤となるスナップショットを保持する場合は、Retain を指定します。

      カスタムのストレージ ロケーションを使用するには、storage-locations パラメータをスナップショット クラスに追加します。このパラメータを使用するには、クラスタでバージョン 1.21 以降を使用する必要があります。

      apiVersion: snapshot.storage.k8s.io/v1
      kind: VolumeSnapshotClass
      metadata:
        name: my-snapshotclass
      parameters:
        storage-locations: us-east2
      driver: pd.csi.storage.gke.io
      deletionPolicy: Delete
      
    • ディスク イメージを作成するには、parameters フィールドに次の行を追加します。

      parameters:
        snapshot-type: images
        image-family: IMAGE_FAMILY
      

      IMAGE_FAMILY は、目的のイメージ ファミリーの名前(preloaded-data など)に置き換えます。

  2. 次のようにマニフェストを適用します。

    kubectl apply -f volumesnapshotclass.yaml
    

VolumeSnapshot を作成する

VolumeSnapshot オブジェクトは、既存の PersistentVolumeClaim オブジェクトのスナップショットのリクエストです。VolumeSnapshot オブジェクトを作成すると、GKE はオブジェクトを自動的に作成し、VolumeSnapshotContent オブジェクト(PersistentVolume オブジェクトなどのクラスタ内のリソース)とバインドします。

  1. 次のマニフェストを volumesnapshot.yaml として保存します。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: my-snapshot
    spec:
      volumeSnapshotClassName: my-snapshotclass
      source:
        persistentVolumeClaimName: my-pvc
    
  2. 次のようにマニフェストを適用します。

    kubectl apply -f volumesnapshot.yaml
    

    Volume スナップショットを作成すると、GKE によって対応する VolumeSnapshotContent オブジェクトがクラスタ内に作成されます。このオブジェクトには、VolumeSnapshot オブジェクトのスナップショットとバインディングが格納されます。VolumeSnapshotContents オブジェクトを直接操作することはありません。

  3. GKE が VolumeSnapshotContents オブジェクトを作成したことを確認します。

    kubectl get volumesnapshotcontents
    

    出力は次のようになります。

    NAME                                               AGE
    snapcontent-cee5fb1f-5427-11ea-a53c-42010a1000da   55s
    

Volume スナップショットのコンテンツが作成されると、VolumeSnapshotClass で指定した CSI ドライバによって、対応するストレージ システムにスナップショットが作成されます。GKE がストレージ システムにスナップショットを作成し、クラスタ上の VolumeSnapshot オブジェクトにバインドすると、スナップショットが使用できるようになります。ステータスを確認するには、次のコマンドを実行します。

kubectl get volumesnapshot \
  -o custom-columns='NAME:.metadata.name,READY:.status.readyToUse'

スナップショットを使用できる場合は、出力は次のようになります。

NAME               READY
my-snapshot        true

テストファイルを削除します。

  1. 作成したテストファイルを削除します。

    kubectl exec POD_NAME \
        -- sh -c 'rm /usr/share/hello/hello.txt'
    
  2. ファイルが存在していないことを確認します。

    kubectl exec POD_NAME \
        -- sh -c 'cat /usr/share/hello/hello.txt'
    

    出力は次のようになります。

    cat: /usr/share/hello/hello.txt: No such file or directory
    

ボリューム スナップショットを復元する

PersistentVolumeClaimVolumeSnapshot を参照して、既存のボリュームのデータで新しいボリュームをプロビジョニングできます。また、ボリュームをスナップショットでキャプチャした状態に復元することもできます。

PersistentVolumeClaimVolumeSnapshot を参照するには、PersistentVolumeClaimdataSource フィールドを追加します。VolumeSnapshotContents がディスク イメージとスナップショットのどちらを参照する場合も、同じプロセスが使用されます。

この例では、新しい PersistentVolumeClaim で作成した VolumeSnapshot を参照して、新しいクレームを使用するように Deployment を更新します。

  1. 次のようなディスクまたはイメージのスナップショットを使用していることを確認します。

    • ディスクのスナップショット: スナップショットの作成の頻度が高く、復元の頻度は低い。
    • イメージのスナップショット: スナップショットの作成の頻繁が低く、復元の頻度は高い。また、イメージのスナップショットは、ディスクのスナップショットよりも作成に時間がかかることがあります。

    詳細については、スナップショット頻度の上限をご覧ください。スナップショットのタイプを把握していると、問題のトラブルシューティングに役立ちます。

    VolumeSnapshot を調べます。

    kubectl describe volumesnapshot SNAPSHOT_NAME
    

    volumeSnapshotClassName フィールドには、スナップショット クラスを指定します。

    kubectl describe volumesnapshotclass SNAPSHOT_CLASS_NAME
    

    snapshot-type パラメータで snapshots または images を指定します。指定しない場合のデフォルトは snapshots です。

    スナップショット クラスが存在しない場合(たとえば、スナップショットが静的に作成された場合)、VolumeSnapshotContents を調べます。sh kubectl describe volumesnapshotcontents SNAPSHOT_CONTENTS_NAME 出力のスナップショット ハンドルの形式を見れば、スナップショットのタイプがわかります。 * projects/PROJECT_NAME/global/snapshots/SNAPSHOT_NAME: ディスクのスナップショット

    • projects/PROJECT_NAME/global/images/IMAGE_NAME: イメージのスナップショット
  1. 次のマニフェストを pvc-restore.yaml として保存します。

    Persistent Disk

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: pvc-restore
    spec:
      dataSource:
        name: my-snapshot
        kind: VolumeSnapshot
        apiGroup: snapshot.storage.k8s.io
      storageClassName: standard-rwo
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
    
  2. 次のようにマニフェストを適用します。

    kubectl apply -f pvc-restore.yaml
    
  3. 新しい PersistentVolumeClaim を使用するように my-deployment.yaml ファイルを更新します。

    ...
    volumes:
    - name: my-volume
      persistentVolumeClaim:
        claimName: pvc-restore
    
  4. 更新されたマニフェストを適用します。

    kubectl apply -f my-deployment.yaml
    

スナップショットが正常に復元されたことを確認する

  1. 更新された Deployment 用に GKE が作成する新しい Pod の名前を取得します。

     kubectl get pods -l app=hello-app
    

テストファイルが存在することを確認します。

   kubectl exec NEW_POD_NAME \
       -- sh -c 'cat /usr/share/hello/hello.txt'

NEW_POD_NAME は、GKE が作成した新しい Pod の名前に置き換えます。

出力は次のようになります。

   Hello World!

既存のスナップショットをインポートする

現在のクラスタの外部で作成された既存のボリューム スナップショットを使用して、VolumeSnapshotContents オブジェクトを手動でプロビジョニングできます。たとえば、別のクラスタに作成された別の Google Cloud リソースのスナップショットで GKE のボリュームを更新できます。

  1. スナップショットの名前を探します。

    Google Cloud コンソール

    https://console.cloud.google.com/compute/snapshots に移動します。

    Google Cloud CLI

    次のコマンドを実行します。

    gcloud compute snapshots list
    

    出力は次のようになります。

    NAME                                           DISK_SIZE_GB  SRC_DISK                                                     STATUS
    snapshot-5e6af474-cbcc-49ed-b53f-32262959a0a0  1             us-central1-b/disks/pvc-69f80fca-bb06-4519-9e7d-b26f45c1f4aa READY
    
  2. 次の VolumeSnapshot マニフェストを restored-snapshot.yaml として保存します。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshot
    metadata:
      name: restored-snapshot
    spec:
      volumeSnapshotClassName: my-snapshotclass
      source:
        volumeSnapshotContentName: restored-snapshot-content
    
  3. 次のようにマニフェストを適用します。

    kubectl apply -f restored-snapshot.yaml
    
  4. 次の VolumeSnapshotContent マニフェストを restored-snapshot-content.yaml として保存します。snapshotHandle フィールドは、プロジェクト ID とスナップショット名に置き換えます。双方向のバインディングを有効にするには、volumeSnapshotRef.namevolumeSnapshotRef.namespace の両方が、以前に作成した VolumeSnapshot を参照している必要があります。

    apiVersion: snapshot.storage.k8s.io/v1
    kind: VolumeSnapshotContent
    metadata:
      name: restored-snapshot-content
    spec:
      deletionPolicy: Retain
      driver: pd.csi.storage.gke.io
      source:
        snapshotHandle: projects/PROJECT_ID/global/snapshots/SNAPSHOT_NAME
      volumeSnapshotRef:
        kind: VolumeSnapshot
        name: restored-snapshot
        namespace: default
    
  5. 次のようにマニフェストを適用します。

    kubectl apply -f restored-snapshot-content.yaml
    
  6. 次の PersistentVolumeClaim マニフェストを restored-pvc.yaml として保存します。Kubernetes ストレージ コントローラは、restored-snapshot という名前の VolumeSnapshot を探し、データソースとして PersistentVolume を見つけるか、動的に作成しようとします。その後、Pod でこの PVC を使用して、復元されたデータにアクセスできます。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: restored-pvc
    spec:
      dataSource:
        name: restored-snapshot
        kind: VolumeSnapshot
        apiGroup: snapshot.storage.k8s.io
      storageClassName: standard-rwo
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 1Gi
    
  7. 次のようにマニフェストを適用します。

    kubectl apply -f restored-pvc.yaml
    
  8. 次の Pod マニフェストを restored-pod.yaml として保存し、PersistentVolumeClaim を参照します。CSI ドライバが PersistentVolume をプロビジョニングし、スナップショットで更新します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: restored-pod
    spec:
      containers:
      - name: busybox
        image: busybox
        args:
        - sleep
        - "3600"
        volumeMounts:
        - name: source-data
          mountPath: /demo/data
      volumes:
      - name: source-data
        persistentVolumeClaim:
          claimName: restored-pvc
          readOnly: false
    
  9. 次のようにマニフェストを適用します。

    kubectl apply -f restored-pod.yaml
    
  10. ファイルが復元されたことを確認します。

    kubectl exec restored-pod -- sh -c 'cat /demo/data/hello.txt'
    

クリーンアップ

このページで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、次の操作を行います。

  1. VolumeSnapshot を削除します。

    kubectl delete volumesnapshot my-snapshot
    
  2. VolumeSnapshotClass を削除します。

    kubectl delete volumesnapshotclass my-snapshotclass
    
  3. Deployment を削除します。

    kubectl delete deployments hello-app
    
  4. PersistentVolumeClaim オブジェクトを削除します。

    kubectl delete pvc my-pvc pvc-restore
    

次のステップ