定義自訂備份與還原邏輯

在 Google Kubernetes Engine 叢集中啟用 GKE 備份代理程式後,GKE 備份會提供 CustomResourceDefinition,其中導入了新型 Kubernetes 資源:ProtectedApplication。

編寫 ProtectedApplication 包含三項活動:

在應用程式層級自訂備份和還原邏輯時,ProtectedApplication 資源可提供下列功能:

  • 更精細的備份和還原作業。如果沒有 ProtectedApplications,備份範圍就必須在 Namespace 層級定義 (選取 allNamespaces 或 selectedNamespaces)。 命名空間資源還原也適用類似的邏輯。建立 ProtectedApplication 資源後,您就能為 Namespace 中的部分資源提供名稱。然後在備份範圍中列出 selectedApplications,即可備份及還原該子集 (同樣適用於還原)。

  • 協調備份或還原程序的細微詳情,包括:

    • 備份時略過所選磁碟區。

    • 將應用程式拓撲納入備份和還原作業 (例如,只備份複製資料庫的一個執行個體,並用來還原多個執行個體)。

    • 在磁碟區建立快照前後,執行使用者定義的掛鉤。舉例來說,您可以使用這些掛鉤,在建立快照前排清並停止工作負載,然後再取消停止。

您可以使用 kubectl 建立 ProtectedApplication,就像其他 Kubernetes 資源一樣。這些都是選填。如果沒有 ProtectedApplication 資源,GKE 備份 會為備份範圍內的所有磁碟區建立磁碟區備份,產生的磁碟區備份會與當機一致,也就是說,系統會擷取在特定時間點寫入磁碟的所有內容 (即不會有部分寫入)。不過,部分應用程式可能會將資料保留在記憶體中,而不會排清至磁碟,因此應用程式是否能從當機一致性備份成功復原,取決於應用程式邏輯。

選取資源

建構 ProtectedApplication 資源的第一步,是找出要納入應用程式的相同 Namespace 中的其他資源。如果您在 BackupPlan 設定中提供 selectedApplications 範圍選項,系統就會備份或還原這組資源。

系統會使用標籤選取器來識別資源。因此,您必須使用相同標籤標示所有資源 (在每個資源中使用 metadata.label 欄位)。請注意,這也適用於控制器自動建立的資源。這些自動建立的資源會使用對應範本標示。請注意,您通常會重複使用現有的標籤,將產生的 Pods 和 PersistentVolumeClaims 與父項資源建立關聯。

使用時請考量下列事項:

  • 如要保護會建立子資源的資源,父項資源 (例如 StatefulSet、Deployment 或 DaemonSet) 和子資源 (例如 Pod 或 PersistentVolumeClaim) 都必須具有 ProtectedApplication 的 Selector 欄位中使用的標籤。
  • 如果 ProtectedApplication 參照的部分資源是由運算子自動建立,您也應在 ProtectedApplication 選取器中加入運算子的自訂資源。這有助於避免還原時發生競爭狀況,因為當運算子嘗試建立資源時,該資源同時會從備份還原。

以下範例說明如何將 app: nginx 標籤套用至 Deployment 以外的其他資源。

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 中的所有資源後,您可以選擇為這些資源的子集定義詳細的協調規則。這些規則可能只適用於兩種資源:部署和 StatefulSets,並在 ProtectedApplication 的 components 區段中參照。

元件總覽

設定元件時,請完成下列步驟:

  • 為這個元件選取備份和還原作業的基本策略。有三種策略可供選擇:

    • BackupAllRestoreAll:備份與元件所有執行個體相關聯的磁碟區,並從備份還原所有磁碟區。

    • BackupOneRestoreAll:僅備份元件中一個執行個體的磁碟區,並使用這些備份還原所有執行個體。

    • DumpAndLoad:在備份時將應用程式資料匯出至單一磁碟區,並在還原時將資料匯入應用程式。

  • 定義在備份期間 (以及可能在還原期間,視策略而定) 執行的 hook。所謂的「掛鉤」是指在特定容器中執行的指令。

  • 選取要備份的部分磁碟區。

執行掛鉤

在備份或還原程序的特定階段,GKE 備份服務會在容器中執行 Shell 指令,這就是所謂的「掛鉤」。

有四種不同的 Hook:

  • pre hooks:這些指令會在磁碟區備份前執行,通常會將記憶體中的所有資料清除至磁碟,然後暫停應用程式,以免發生新的磁碟寫入作業。這些 Hook 會用於 BackupAllRestoreAll 和 BackupOneRestoreAll 策略。

  • post hooks - 這些指令會在磁碟區備份程序中執行,時間點是磁碟區備份程序的 SNAPSHOTTING 步驟完成後 (UPLOADING 步驟之前)。一般來說,SNAPSHOTTING 步驟只需要幾秒鐘。 一般來說,這些事件應會解除應用程式的靜止狀態 (即允許正常處理程序和磁碟寫入作業繼續進行)。這些掛鉤用於 BackupAllRestoreAll、BackupOneRestoreAll 和 DumpAndLoad 策略。

  • dump hooks - 這些指令會在 DumpAndLoad 策略備份磁碟區之前執行,一般預期會將資料從應用程式匯出至指定的備份磁碟區。

  • load hooks:這些指令會在備份磁碟區還原後執行,適用於 DumpAndLoad 策略案例。一般來說,這些應用程式會將備份磁碟區中的資料匯入應用程式。

您可以為每種類型提供多個掛鉤,GKE 備份會按照您定義的順序執行。

您可以在 ProtectedApplication 規格的元件部分定義掛鉤。所有掛鉤定義都有相同的可用欄位:

  • name:您為掛鉤指定的名稱。

  • container - (選用) 要在其中執行指令的容器名稱。如未提供容器,GKE 備份會在為目標 Pod 定義的第一個容器中執行掛鉤。

  • command:這是傳送至容器的實際指令,以字詞陣列的形式建構。陣列中的第一個字是指令的路徑,後續的字則是要傳遞給指令的引數。

  • timeoutSeconds - (選用) 終止執行掛鉤前經過的時間。如未提供此值,則預設為 30 秒。

  • onError - (選用) 掛鉤失敗時採取的行為。可以設為 Ignore 或 Fail (預設值)。 如果將此值設為 Fail,當 Hook 失敗時,磁碟區備份作業也會失敗。如果將此值設為 Ignore,系統會忽略這個掛鉤的失敗情形。

將 ProtectedApplication 鉤子套用至應用程式前,請先使用 kubectl exec 測試指令,確保鉤子運作正常:

kubectl exec POD_NAME -- COMMAND

更改下列內容:

  • POD_NAME:包含 ProtectedApplication 資源的 Pod 名稱。
  • COMMAND:陣列,包含要在容器中執行的指令。

選取要備份的磁碟區子集

有時,應用程式會寫入不需還原的磁碟區 (例如特定記錄或暫存磁碟區)。您可以使用磁碟區選取器,抑制這些磁碟區的備份。

如要使用這項功能,請先將通用標籤套用至要備份的磁碟區資源。PersistentVolumeClaim此外,如要避免備份特定卷冊的 PersistentVolumeClaim 資源,請務必將這個標籤關閉。然後在元件定義中加入 volumeSelector 子句,如下所示:

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

如果為元件提供 volumeSelector,則只有 PersistentVolumeClaim 資源具有指定標籤的磁碟區會備份及還原。還原時,系統會將其他磁碟區佈建為空白磁碟區,而不是從磁碟區備份還原。

策略:BackupAllRestoreAll

這是最簡單的策略,會在備份時備份所有元件磁碟區,並在還原時從磁碟區備份還原所有元件。如果應用程式在 Pods 之間沒有任何複製作業,這是最佳選擇。

這項策略支援下列參數:

  • backupPreHooks - (選用) hook 的排序清單,會在備份磁碟區前執行。這些指令會在元件中的所有 Pods 上執行。

  • backupPostHooks - (選用) hook 的排序清單,會在磁碟區備份達到 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-deployment"]
    strategy:
      type: BackupAllRestoreAll
      backupAllRestoreAll:
        backupPreHooks:
        - name: freeze
          container: nginx
          command:
          - bash
          - "-c"
          - |
            # Add application logic to flush data to disk before snapshot
            # and freeze the application from further changes.
            echo "Freezing the application"

            # Return 0 on successful freeze of application, and non-zero
            # for errors
            exit 0
        backupPostHooks:
        - name: unfreeze
          container: nginx
          command:
          - bash
          - "-c"
          - |
            # Add application logic to unfreeze the application.
            echo "Unfreezing the application"

            # Return 0 on successful freeze of application, and non-zero
            # for errors
            exit 0

策略:BackupOneAndRestoreAll

這項策略會備份所選 Pod 的一個副本。還原時,系統會根據這個副本還原所有 Pod。這個方法有助於降低儲存費用和縮短備份時間。在高可用性設定中,當元件部署一個主要 PersistentVolumeClaim 和多個次要 PersistentVolumeClaims 時,這項策略會運作。

這項策略支援下列參數:

  • backupTargetName - (必要) 指定要用來備份資料的 Deployment 或 StatefulSet。系統會自動選取最適合備份的 Pod。在高可用性設定中,建議您將此值設為其中一個應用程式副本。

  • backupPreHooks - (選用) 掛鉤 的已排序的清單,會在磁碟區備份前執行。這些指令只會在選取的備份 Pod 上執行。

  • backupPostHooks - (選用) hook 的排序清單,會在磁碟區備份達到 UPLOADING 階段後執行。這些指令只會在所選備份 Pod 上執行。

  • volumeSelector - (選用) 用於比對要備份的磁碟區子集邏輯。

如果元件設定了多個 Deployment 或 StatefulSet,所有資源都必須具有相同的 PersistentVolume 結構,也就是必須遵守下列規則:

  • 所有 Deployment 或 StatefulSet 使用的 PersistentVolumeClaims 數量必須相同。
  • 相同索引中的 PersistentVolumeClaims 必須具有相同用途。如果是 StatefulSet,索引會在 volumeClaimTemplate 中定義。如果是 Deployment,索引會定義在 Volumes 中,且系統會略過所有非持續性磁碟區。
  • 如果應用程式元件包含部署項目,則每個部署項目都只能有一個副本。

考量到這些因素,您可以選取多個磁碟區組進行備份,但每個磁碟區組只能選取一個磁碟區。

假設架構為一個主要 StatefulSet 和一個次要 StatefulSet,以下範例會顯示次要 StatefulSet 中一個 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 - (選用) hook 的排序清單,會在磁碟區備份達到 UPLOADING 階段後執行。這些指令只會在所選傾印 Pod 上執行。

  • loadHooks - (必要) hook 的排序清單,應用程式啟動後會執行這些 hook,從還原的磁碟區載入資料。這些指令只會在所選負載 Pod 上執行。

  • volumeSelector - (必要) 將單一磁碟區與備份和還原 (「dump」磁碟區) 比對的邏輯。雖然這項設定只能與單一磁碟區相符,但設定方式與其他策略使用的備份磁碟區子集相同。

如果應用程式包含部署項目,每個部署項目都只能有一個副本。

假設架構為一個主要 StatefulSet 和一個次要 StatefulSet,且主要和次要 StatefulSet 都有專屬的 PersistentVolumeClaims,以下範例顯示 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>

後續步驟