バックアップと復元のカスタム ロジックを定義する


Google Kubernetes Engine クラスタで Backup for GKE エージェントを有効にすると、Backup for GKE によって CustomResourceDefinition が提供されます。これにより、新しい種類の Kubernetes リソース ProtectedApplication が導入されます。

ProtectedApplication の作成では、次の 3 つの操作を行います。

ProtectedApplication リソースを使用すると、バックアップと復元のロジックをアプリケーション レベルでカスタマイズする際に、次の機能を使用できます。

  • より詳細なバックアップと復元。ProtectedApplications を使用しない場合は、バックアップのスコープを Namespace レベルで定義する必要があります(allNamespaces または selectedNamespaces を選択)。名前空間付きリソースの復元にも同様のロジックが適用されます。ProtectedApplication リソースを作成すると、Namespace 内のリソースのサブセットに名前を指定できます。その後、バックアップ スコープで selectedApplications をリストして、サブセットのバックアップと復元を行うこともできます(復元の場合も同様です)。

  • バックアップまたは復元のプロセスの詳細なオーケストレーション

    • バックアップ時に選択したボリュームをスキップします。

    • アプリケーション トポロジをバックアップと復元に組み込みます(たとえば、複製されたデータベースの 1 つのインスタンスのみをバックアップし、それを使用して複数のインスタンスを復元します)。

    • ボリュームのスナップショットの前後にユーザー定義のフックを実行します。たとえば、スナップショットを作成する前にワークロードをフラッシュして停止し、その後再開します。

他の Kubernetes リソースと同様に、kubectl を使用して ProtectedApplication を作成します。これらはすべて任意です。ProtectedApplication リソースが存在しない場合、Backup for GKE は、バックアップ スコープ内のすべてのボリュームに対してボリューム バックアップを作成します。その結果、ボリュームのバックアップがクラッシュ整合性を持ちます。特定の時点でディスクにフラッシュされたすべての書き込みがキャプチャされます(つまり、部分的な書き込みはありません)。ただし、一部のアプリケーションでは、ディスクにフラッシュされていないデータをメモリに保持することがあるため、アプリケーションがクラッシュ整合性のあるバックアップから正常に復元できるかどうかは、アプリケーション ロジックによって異なります。

リソースの選択

ProtectedApplication リソースを作成する最初のステップは、アプリケーションの一部として含める同じ Namespace 内のリソースを特定することです。これは、BackupPlan 構成で selectedApplications スコープ オプションを指定した場合にバックアップまたは復元されるリソースのセットです。

リソースはラベルセレクタを使用して識別されます。このため、すべてのリソースに同じラベルを付ける必要があります(各リソースの metadata.label フィールドを使用します)。これは、コントローラによって自動的に作成されるリソースにも適用されます。自動的に作成されたこれらのリソースには、対応するテンプレートによってラベルが設定されます。すでに使用しているラベルを再利用して、生成された PodsPersistentVolumeClaims を親リソースに関連付けるのが一般的です。次の例では、Deployment に加えて、他のリソースにも app: nginx ラベルを適用しています。

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-vars
  namespace: webserver
  labels:
    app: nginx
  data:
    ...
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-logs
  namespace: webserver
  labels:
    app: nginx
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 50Mi
  storageClassName: standard-rwo
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  namespace: webserver
  labels:
    app: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      volumes:
        - name: nginx-logs
          persistentVolumeClaim:
           claimName: nginx-logs
      containers:
      ...

選択したラベルをすべてのターゲット リソース(追加リソースの生成元となるテンプレートを含む)に適用すると、ProtectedApplication からそれらのリソースを参照できます。次に例を示します。

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: nginx
  namespace: webserver
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: nginx
  ...

オーケストレーション ルールを定義する

ProtectedApplication 内のすべてのリソースを特定したら、それらのリソースのサブセットに詳細なオーケストレーション ルールを定義できます。これらのルールは、DeploymentStatefulSet の 2 種類のリソースにのみ適用されます。これらは ProtectedApplicationcomponents セクションで参照されています。

コンポーネントの概要

コンポーネントの構成では、次のことを行います。

  • このコンポーネントのバックアップと復元に関する基本的な戦略を選択します。次の 3 つの戦略があります。

    • BackupAllRestoreAll - コンポーネントのすべてのインスタンスに関連付けられたボリュームをバックアップし、すべてをバックアップから復元する

    • BackupOneRestoreAll - コンポーネントの 1 つのインスタンスのボリュームをバックアップし、そのバックアップを使用してすべてのインスタンスを復元する

    • DumpAndLoad - バックアップ時にアプリケーションから単一ボリュームにデータをエクスポートし、復元時にそのデータをアプリケーションにインポートする

  • バックアップ時に実行する実行フックを定義します(戦略によっては復元時にも実行します)。フックは、特定のコンテナで実行されるコマンドです。

  • バックアップするボリュームのサブセットを選択します

実行フック

フックは、バックアップまたは復元プロセスの特定のフェーズで Backup for GKE がコンテナ内で実行するシェルコマンドです。

フックには次の 4 種類があります。

  • pre hooks - このコマンドは、ボリュームがバックアップされる直前に実行されます。ディスクに新しい書き込みが発生しないよう、通常はメモリ内のデータをディスクにフラッシュしてから、アプリケーションを停止します。このフックは、BackupAllRestoreAll 戦略と BackupOneRestoreAll 戦略で使用されます。

  • post hooks - このコマンドは、ボリューム バックアップ プロセスの SNAPSHOTTING ステップの直後(UPLOADING ステップの前)のボリューム バックアップ プロセスで実行されます。通常、SNAPSHOTTING ステップにかかる時間は数秒です。通常、アプリケーションは停止解除状態になります(つまり、通常の処理とディスクの書き込みを続行します)。このフックは、BackupAllRestoreAllBackupOneRestoreAllDumpAndLoad の各戦略で使用されます。

  • dump hooks - このコマンドは、DumpAndLoad 戦略でボリュームがバックアップされる前に実行されます。通常、アプリケーションから指定のバックアップ ボリュームにデータをエクスポートします。

  • load hooks - このコマンドは、DumpAndLoad 戦略でバックアップ ボリュームが復元された後に実行されます。通常は、バックアップ ボリュームからアプリケーションにデータをインポートします。

タイプごとに複数のフックを指定することができ、Backup for GKE は定義された順序でこれらのフックを実行します。

フックは、ProtectedApplication 仕様のコンポーネント セクションの一部として定義します。フックの定義で使用できるフィールドは次のとおりです。

  • name - フックに割り当てた名前。

  • container - (省略可)コマンドを実行するコンテナの名前。コンテナを指定しない場合、Backup for GKE はターゲット Pod に定義された最初のコンテナでフックを実行します。

  • command - コンテナに送信される実際のコマンド。単語の配列として構成されます。配列の最初の単語はコマンドのパスで、以降はコマンドに渡される引数です。

  • timeoutSeconds - (省略可)フックの実行を中止するまでの時間。指定しない場合、デフォルトで 30 秒に設定されます。

  • onError - (省略可)フックが失敗したときの動作。Ignore または Fail(デフォルト)に設定できます。Fail に設定した場合、フックが失敗すると、ボリュームのバックアップも失敗します。Ignore に設定すると、このフックの失敗は無視されます。

フックが期待どおりに動作することを確認するには、ProtectedApplication フックをアプリケーションに適用する前に、kubectl exec を使用してコマンドをテストする必要があります。

kubectl exec POD_NAME -- COMMAND

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

  • POD_NAME: ProtectedApplication リソースを含む Pod の名前。
  • COMMAND: コンテナで実行するコマンドを含む配列(例: /sbin/fsfreeze, -f, /var/log/nginx)。

バックアップするボリュームのサブセットの選択

アプリケーションによっては、復元に関係のないボリュームに書き込みを行う場合があります(たとえば、特定のログやスクラッチ ボリュームなど)。これらのボリュームのバックアップを抑制するには、ボリューム セレクタを使用します。

この機能を使用するには、まずバックアップするボリュームに共通のラベルを適用し、バックアップしないボリュームでこのラベルを無効にします。次のように、コンポーネント定義に volumeSelector 句を含めます。

spec:
  ...
  components:
  ...
    strategy:
      ...
      volumeSelector:
        matchLabels:
          label_name: label_value

コンポーネントに volumeSelector を使用すると、指定されたラベルのボリュームのみがバックアップまたは復元されます。復元時に、他のボリュームはボリューム バックアップから復元されるのではなく、空のものとしてプロビジョニングされます。

戦略: BackupAllRestoreAll

最もシンプルな戦略で、バックアップ時にはコンポーネントのすべてのボリュームがバックアップされ、復元時にはそのすべてがボリュームのバックアップから復元されます。これは、アプリケーションで Pods 間のレプリケーションがない場合に最適です。

この戦略は、次のパラメータをサポートしています。

  • backupPreHooks - (省略可)ボリュームがバックアップされる直前に実行されるフックの順序付きリスト。これらのコマンドは、コンポーネント内のすべての Pods で実行されます。

  • backupPostHooks - (省略可)ボリュームのバックアップが UPLOADING フェーズに達した後に実行されるフックの順序付きリスト。これらのコマンドは、コンポーネント内のすべての Pods で実行されます。

  • volumeSelector - (省略可)バックアップするボリュームのサブセットを照合するロジック。

この例では、ログボリュームをバックアップする前にファイル システムを停止し、バックアップの後に停止する ProtectedApplication リソースを作成します。

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: nginx
  namespace: sales
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: nginx
  components:
  - name: nginx-app
    resourceKind: Deployment
    resourceNames: ["nginx"]
    strategy:
      type: BackupAllRestoreAll
      backupAllRestoreAll:
        backupPreHooks:
        - name: fsfreeze
          container: nginx
          command: [ /sbin/fsfreeze, -f, /var/log/nginx ]
        backupPostHooks:
        - name: fsunfreeze
          container: nginx
          command: [ /sbin/fsfreeze, -u, /var/log/nginx ]

戦略: BackupOneAndRestoreAll

この戦略では、選択した Pod のコピーを 1 つバックアップします。この単一コピーは、復元中にすべての Pod を復元するソースです。この方法は、ストレージ費用を削減しバックアップ時間を短縮するのに役立ちます。この戦略は、1 つのプライマリ PersistentVolumeClaim と複数のセカンダリ PersistentVolumeClaims でコンポーネントがデプロイされている場合に、高可用性構成で機能します。

この戦略は、次のパラメータをサポートしています。

  • backupTargetName - (必須)データのバックアップに使用する Deployment または StatefulSet を指定します。バックアップに最適な Pod が自動的に選択されます。高可用性構成の場合は、これをアプリケーション レプリカのいずれかに設定することをおすすめします。

  • backupPreHooks - (省略可)ボリュームがバックアップされる直前に実行されるフックの順序付きリスト。これらのコマンドは、選択したバックアップ Pod でのみ実行されます。

  • backupPostHooks - (省略可)ボリュームのバックアップが UPLOADING フェーズに達した後に実行されるフックの順序付きリスト。これらのコマンドは、選択したバックアップ Pod でのみ実行されます。

  • volumeSelector - (省略可)バックアップするボリュームのサブセットを照合するロジック。

コンポーネントが複数の Deployment または StatefulSet で構成されている場合は、すべてのリソースが同じ PersistentVolume 構造になっている必要があります。つまり、次のルールに従う必要があります。

  • すべての Deployment または StatefulSet で使用される PersistentVolumeClaims の数は同じである必要があります。
  • 同じインデックス内の PersistentVolumeClaims の目的は同じである必要があります。StatefulSet で、インデックスは volumeClaimTemplate で定義されます。Deployment で、インデックスは Volumes で定義され、非永続ボリュームはスキップされます。
  • アプリケーション コンポーネントが Deployment で構成されている場合、各 Deployment には 1 つのレプリカが必要です。

これらの考慮事項を前提に、バックアップには複数のボリューム セットを選択できますが、各ボリューム セットから選択されるボリュームは 1 つだけです。

この例は、1 つのプライマリ StatefulSet とセカンダリ StatefulSet のアーキテクチャを想定し、セカンダリ StatefulSet に 1 つの Pod のボリュームのバックアップがあり、その後、他のすべてのボリュームに復元されることを示しています。

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: mariadb
  namespace: mariadb
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: mariadb
  components:
  - name: mariadb
    resourceKind: StatefulSet
    resourceNames: ["mariadb-primary", "mariadb-secondary"]
    strategy:
      type: BackupOneRestoreAll
      backupOneRestoreAll:
        backupTargetName: mariadb-secondary
        backupPreHooks:
        - name: quiesce
          container: mariadb
          command: [...]
        backupPostHooks:
        - name: unquiesce
          container: mariadb
          command: [...]

戦略: DumpAndLoad

この戦略では、バックアップと復元のプロセスに専用のボリュームが使用されます。ダンプデータを格納するコンポーネントには、専用の PersistentVolumeClaim が接続されている必要があります。

この戦略は、次のパラメータをサポートしています。

  • dumpTarget - (必須)データのバックアップに使用する Deployment または StatefulSet を指定します。バックアップに最適な Pod が自動的に選択されます。高可用性構成の場合は、これをアプリケーション レプリカのいずれかに設定することをおすすめします。

  • loadTarget - (必須)データの読み込みに使用する Deployment または StatefulSet を指定します。バックアップに最適な Pod が自動的に選択されます。読み込みターゲットは、ダンプ ターゲットと同じにする必要はありません。

  • dumpHooks - (必須)専用のバックアップ ボリュームを設定するために実行されるフックの順序付きリスト。これらのコマンドは、選択したダンプ Pod に対してのみ実行されます。

  • backupPostHooks - (省略可)ボリュームのバックアップが UPLOADING フェーズに達した後に実行されるフックの順序付きリスト。これらのコマンドは、選択したダンプ Pod でのみ実行されます。

  • loadHooks - (必須)アプリケーションの起動後に復元されたボリュームからデータを読み込むために実行されるフックの順序付きリスト。これらのコマンドは、選択した読み込み Pod でのみ実行されます。

  • volumeSelector - (必須)1 つのボリューム(ダンプ ボリューム)をバックアップおよび復元に一致させるためのロジック。一致させるボリュームは 1 つだけですが、この構成は、他の戦略で使用されるバックアップするボリュームのサブセットと同じ方法で行います。

アプリケーションが Deployment で構成されている場合、各 Deployment には 1 つのレプリカが必要です。

この例では、プライマリ StatefulSet とセカンダリ StatefulSet の両方に専用の PersistentVolumeClaims を持つ 1 つのプライマリ StatefulSet とセカンダリ StatefulSet のアーキテクチャを想定し、DumpAndLoad の戦略を示しています。

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1
metadata:
  name: mariadb
  namespace: mariadb
spec:
  resourceSelection:
    type: Selector
    selector:
      matchLabels:
        app: mariadb
  components:
  - name: mariadb-dump
    resourceKind: StatefulSet
    resourceNames: ["mariadb-primary", "mariadb-secondary"]
    strategy:
      type: DumpAndLoad
      dumpAndLoad:
        loadTarget: mariadb-primary
        dumpTarget: mariadb-secondary
        dumpHooks:
        - name: db_dump
          container: mariadb
          command:
          - bash
          - "-c"
          - |
            mysqldump -u root --all-databases > /backup/mysql_backup.dump
        loadHooks:
        - name: db_load
          container: mariadb
          command:
          - bash
          - "-c"
          - |
            mysql -u root < /backup/mysql_backup.sql
        volumeSelector:
          matchLabels:
            gkebackup.gke.io/backup: dedicated-volume

ProtectedApplication がバックアップの準備ができているかどうかを確認する

次のコマンドを実行して、ProtectedApplication がバックアップの準備ができているかどうかを確認できます。

kubectl describe protectedapplication APPLICATION_NAME

APPLICATION_NAME は、アプリケーションの名前に置き換えます。

準備ができると、次の例のように、アプリケーションの説明には Ready to backup ステータスが true として表示されます。

% kubectl describe protectedapplication nginx
Name:         nginx
Namespace:    default
API Version:  gkebackup.gke.io/v1
Kind:         ProtectedApplication
Metadata:
  UID:               90c04a86-9dcd-48f2-abbf-5d84f979b2c2
Spec:
  Components:
    Name:           nginx
    Resource Kind:  Deployment
    Resource Names:
      nginx
    Strategy:
      Backup All Restore All:
        Backup Pre Hooks:
          Command:
             /sbin/fsfreeze
             -f
             /var/log/nginx
          Container:         nginx
          Name:              freeze
        Backup Post Hooks:
          Command:
             /sbin/fsfreeze
             -u
             /var/log/nginx
          Container:         nginx
          Name:              unfreeze
      Type:                  BackupAllRestoreAll
  Resource Selection:
    Selector:
      Match Labels:
        app:        nginx
    Type:           Selector
 Status:
  Ready To Backup:  true 
Events:             <none>

次のステップ