Definisci la logica personalizzata di backup e ripristino

Quando abiliti l'agente Backup per GKE nel cluster Google Kubernetes Engine, Backup per GKE fornisce una CustomResourceDefinition che introduce un nuovo tipo di risorsa Kubernetes: ProtectedApplication.

La composizione di un ProtectedApplication prevede tre attività:

Le risorse ProtectedApplication ti offrono queste funzionalità quando personalizzi la logica di backup e ripristino a livello di applicazione:

  • Operazioni di backup e ripristino più granulari. Senza ProtectedApplications, l'ambito dei backup deve essere definito a livello di Namespace (selezionando allNamespaces o selectedNamespaces). Una logica simile si applica al ripristino delle risorse con spazio dei nomi. La creazione di risorse ProtectedApplication ti consente di fornire un nome a un sottoinsieme delle risorse in un Namespace. Puoi quindi eseguire il backup e il ripristino di questo sottoinsieme elencando selectedApplications nell'ambito del backup (e analogamente per il ripristino).

  • Orchestrare i dettagli granulari del processo di backup o ripristino, tra cui:

    • Saltare i volumi selezionati durante il backup.

    • Incorporare la topologia dell'applicazione nel backup e nel ripristino (ad esempio, eseguire il backup di una sola istanza di un database replicato e utilizzarla per ripristinare più istanze).

    • Eseguire hook definiti dall'utente prima e dopo l'acquisizione degli snapshot dei volumi. Questi possono essere utilizzati, ad esempio, per scaricare e mettere in stato di quiescenza un carico di lavoro prima dell'acquisizione dello snapshot e per annullare lo stato di quiescenza in un secondo momento.

Puoi creare ProtectedApplication utilizzando kubectl come altre risorse Kubernetes. Sono completamente facoltative. Se le risorse ProtectedApplication non sono presenti, Backup per GKE crea backup dei volumi per tutti i volumi nell' ambito di un backup e i backup dei volumi risultanti saranno coerenti con gli arresti anomali - tutti gli scritture scaricate sul disco in un determinato momento verranno acquisite (ovvero, nessuna scrittura parziale). Tuttavia, alcune applicazioni potrebbero conservare i dati in memoria che non vengono scaricati sul disco, quindi la possibilità di ripristinare correttamente un'applicazione da un backup coerente con gli arresti anomali dipende dalla logica dell'applicazione.

Selezionare le risorse

Il primo passo per creare la risorsa ProtectedApplication è identificare le altre risorse nello stesso Namespace che vuoi includere nell'applicazione. Questo è il set di risorse di cui verrà eseguito il backup o il ripristino se fornisci l' selectedApplications nella configurazione di BackupPlan.

Le risorse vengono identificate utilizzando un selettore di etichette. Ciò richiede di etichettare tutte le risorse (utilizzando il campo metadata.label in ogni risorsa) con la stessa etichetta. Tieni presente che questo vale anche per le risorse create automaticamente dai controller. Queste risorse create automaticamente vengono etichettate utilizzando il modello corrispondente. Tieni presente che è comune riutilizzare la stessa etichetta che utilizzi già per associare Pods e PersistentVolumeClaims generati alla risorsa principale.

Le considerazioni sull'utilizzo includono quanto segue:

  • Se vuoi proteggere le risorse che creano risorse secondarie, sia le risorse principali (come StatefulSet, Deployment o DaemonSet) sia le risorse secondarie (come Pod o PersistentVolumeClaim) devono avere l'etichetta utilizzata nel campo Selector di ProtectedApplication.
  • Se alcune delle risorse a cui fa riferimento ProtectedApplication vengono create automaticamente da un operatore, devi includere anche le risorse personalizzate dell'operatore nel selettore ProtectedApplication. In questo modo eviti una race condition in fase di ripristino che può verificarsi quando l'operatore tenta di creare una risorsa mentre viene ripristinata contemporaneamente dal backup.

Il seguente esempio mostra come applicare l'etichetta app: nginx alle altre risorse oltre a 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:
      ...

Una volta applicata l'etichetta selezionata a tutte le risorse di destinazione (e ai modelli da cui vengono generate risorse aggiuntive), puoi fare riferimento a queste risorse da un ProtectedApplication. Ad esempio:

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

Definire le regole di orchestrazione

Una volta identificate tutte le risorse in ProtectedApplication, puoi scegliere di definire regole di orchestrazione dettagliate per un sottoinsieme di queste risorse. Queste regole possono essere applicate solo a due tipi di risorse: Deployment e StatefulSets e a cui si fa riferimento nella sezione components di ProtectedApplication.

Panoramica dei componenti

La configurazione di un componente prevede quanto segue:

Hook di esecuzione

Un hook è un comando shell che Backup per GKE esegue in un container in una fase specifica del processo di backup o ripristino.

Esistono quattro tipi diversi di hook:

  • pre hooks : questi comandi vengono eseguiti immediatamente prima del backup dei volumi e in genere si prevede che scarichino tutti i dati in memoria sul disco e quindi mettano in stato di quiescenza l'applicazione in modo che non vengano eseguite nuove scritture su disco. Questi hook vengono utilizzati nelle strategie BackupAllRestoreAll e BackupOneRestoreAll.

  • post hooks : questi comandi vengono eseguiti durante il processo di backup del volume subito dopo il passaggio SNAPSHOTTING del processo di backup del volume (prima del passaggio UPLOADING). In genere, il passaggio SNAPSHOTTING richiede solo pochi secondi. In genere si prevede che annullino lo stato di quiescenza dell'applicazione (ovvero consentano l'elaborazione normale e le scritture su disco). Questi hook vengono utilizzati nelle strategie BackupAllRestoreAll, BackupOneRestoreAll e DumpAndLoad.

  • dump hooks : questi comandi vengono eseguiti prima del backup del volume nella strategia DumpAndLoad e in genere si prevede che esportino i dati dall'applicazione nel volume di backup designato.

  • load hooks : questi comandi vengono eseguiti al momento del ripristino dopo il ripristino del volume di backup nei casi di strategia DumpAndLoad. In genere si prevede che importino i dati dal volume di backup nell'applicazione.

Puoi fornire più di un hook per ogni tipo e Backup per GKE li eseguirà nell'ordine in cui li definisci.

Definisci gli hook come parte della sezione del componente della specifica ProtectedApplication. Tutte le definizioni degli hook hanno gli stessi campi disponibili:

  • name : un nome che assegni all'hook.

  • container : (facoltativo) il nome del container in cui eseguire il comando. Se non fornisci il container, Backup per GKE eseguirà l'hook nel primo container definito per i Pod di destinazione.

  • command : questo è il comando effettivo inviato al container, costruito come un array di parole. La prima parola dell'array è il percorso del comando e le parole successive sono gli argomenti da passare al comando.

  • timeoutSeconds : (facoltativo) il tempo prima dell'interruzione dell'esecuzione dell'hook. Se non fornisci questo valore, il valore predefinito è 30 secondi.

  • onError : (facoltativo) il comportamento adottato quando l'hook non riesce. Può essere impostato su Ignore o Fail (impostazione predefinita). Se imposti questo valore su Fail, quando un hook non riesce, il backup del volume non riuscirà. Se imposti questo valore su Ignore, gli errori di questo hook vengono ignorati.

Prima di applicare gli hook ProtectedApplication all'applicazione, devi testare il comando utilizzando kubectl exec per assicurarti che gli hook si comportino come previsto:

kubectl exec POD_NAME -- COMMAND

Sostituisci quanto segue:

  • POD_NAME: il nome del pod che contiene la risorsa ProtectedApplication.
  • COMMAND: l'array contenente il comando che vuoi eseguire nel container.

Selezionare un sottoinsieme di volumi di cui eseguire il backup

A volte, le applicazioni scrivono su volumi che non sono interessanti da ripristinare (ad esempio, determinati volumi di log o scratch). Puoi sopprimere il backup di questi volumi utilizzando un selettore di volumi.

Per utilizzare questa funzionalità, devi prima applicare un'etichetta comune alle risorse PersistentVolumeClaim dei volumi di cui vuoi eseguire il backup. Devi anche non includere questa etichetta nelle risorse PersistentVolumeClaim dei volumi di cui non vuoi eseguire il backup. Poi, includi una clausola volumeSelector nella definizione del componente come segue:

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

Se fornisci un volumeSelector per un componente, vengono sottoposti a backup e ripristinati solo i volumi le cui risorse PersistentVolumeClaim hanno l'etichetta specificata. Al momento del ripristino, gli altri volumi vengono sottoposti a provisioning come vuoti anziché ripristinati da un backup del volume.

Strategia: BackupAllRestoreAll

Questa è la strategia più semplice: esegue il backup di tutti i volumi del componente al momento del backup e li ripristina tutti dai backup dei volumi al momento del ripristino. È la scelta migliore quando l'applicazione non ha la replica tra Pods.

Questa strategia supporta i seguenti parametri:

  • backupPreHooks : (facoltativo) un elenco ordinato di hook eseguiti immediatamente prima del backup dei volumi. Questi comandi vengono eseguiti su tutti i Pods del componente.

  • backupPostHooks : (facoltativo) un elenco ordinato di hook eseguiti dopo che i backup dei volumi hanno raggiunto la fase UPLOADING. Questi comandi vengono eseguiti su tutti i Pods del componente.

  • volumeSelector : (facoltativo) la logica per la corrispondenza di un sottoinsieme di volumi di cui eseguire il backup.

Questo esempio crea una risorsa ProtectedApplication che mette in stato di quiescenza il file system prima di eseguire il backup del volume dei log e annulla lo stato di quiescenza dopo il backup:

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

Strategia: BackupOneAndRestoreAll

Questa strategia esegue il backup di una copia di un pod selezionato. Questa singola copia è l'origine per il ripristino di tutti i pod durante un ripristino. Questo metodo può contribuire a ridurre i costi di archiviazione e il tempo di backup. Questa strategia funziona in una configurazione ad alta affidabilità quando un componente viene sottoposto a deployment con un PersistentVolumeClaim primario e più PersistentVolumeClaims secondari.

Questa strategia supporta i seguenti parametri:

  • backupTargetName : (obbligatorio) specifica il Deployment o lo StatefulSet che vuoi utilizzare per eseguire il backup dei dati. Il pod migliore di cui eseguire il backup viene selezionato automaticamente. In una configurazione ad alta affidabilità, ti consigliamo di impostare questo valore su una delle repliche dell'applicazione.

  • backupPreHooks : (facoltativo) un elenco ordinato di hook eseguiti immediatamente prima del backup dei volumi. Questi comandi vengono eseguiti solo sul Pod di backup selezionato.

  • backupPostHooks : (facoltativo) un elenco ordinato di hook eseguiti dopo che i backup dei volumi hanno raggiunto la fase UPLOADING. Questi comandi vengono eseguiti solo sul Pod di backup selezionato.

  • volumeSelector : (facoltativo) la logica per la corrispondenza di un sottoinsieme di volumi di cui eseguire il backup.

Se un componente è configurato con più Deployment o StatefulSet, tutte le risorse devono avere la stessa struttura PersistentVolume, il che significa che devono rispettare queste regole:

  • Il numero di PersistentVolumeClaims utilizzati da tutti i Deployment o StatefulSet deve essere lo stesso.
  • Lo scopo di PersistentVolumeClaims nello stesso indice deve essere lo stesso. Per StatefulSet, l'indice è definito in volumeClaimTemplate. Per i Deployment, l'indice è definito in Volumes e tutti i volumi non permanenti vengono ignorati.
  • Se il componente dell'applicazione è costituito da Deployment, ogni Deployment deve avere esattamente una replica.

Tenendo conto di queste considerazioni, è possibile selezionare più set di volumi per il backup, ma verrà selezionato un solo volume da ogni set di volumi.

Questo esempio, presupponendo un'architettura di un StatefulSet primario e un StatefulSet secondario, mostra un backup dei volumi di un pod in StatefulSet secondario e poi un ripristino di tutti gli altri volumi:

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: [...]

Strategia: DumpAndLoad

Questa strategia utilizza un volume dedicato per i processi di backup e ripristino e richiede un PersistentVolumeClaim dedicato collegato a un componente che archivia i dati di dump.

Questa strategia supporta i seguenti parametri:

  • dumpTarget : (obbligatorio) specifica il Deployment o lo StatefulSet che vuoi utilizzare per eseguire il backup dei dati. Il pod migliore di cui eseguire il backup viene selezionato automaticamente. In una configurazione ad alta disponibilità, ti consigliamo di impostare questo valore su una delle repliche dell'applicazione.

  • loadTarget : (obbligatorio) specifica il Deployment o lo StatefulSet da utilizzare per caricare i dati. Il pod migliore di cui eseguire il backup viene selezionato automaticamente. La destinazione di caricamento non deve essere la stessa della destinazione di dump.

  • dumpHooks : (obbligatorio) un elenco ordinato di hook eseguiti per popolare il volume di backup dedicato. Questi comandi vengono eseguiti solo sul Pod di dump selezionato.

  • backupPostHooks : (facoltativo) un elenco ordinato di hook eseguiti dopo che i backup dei volumi hanno raggiunto la fase UPLOADING. Questi comandi vengono eseguiti solo sul Pod di dump selezionato.

  • loadHooks : (obbligatorio) un elenco ordinato di hook che vengono eseguiti per caricare i dati dal volume ripristinato dopo l'avvio dell'applicazione. Questi comandi vengono eseguiti solo sul Pod di caricamento selezionato.

  • volumeSelector : (obbligatorio) la logica per la corrispondenza di un singolo volume di cui eseguire il backup e il ripristino (il volume "dump"). Anche se deve corrispondere a un solo volume, devi configurarlo nello stesso modo in cui configuri il sottoinsieme di volumi di cui eseguire il backup utilizzato da altre strategie.

Se l'applicazione è costituita da Deployment, ogni Deployment deve avere esattamente una replica.

Questo esempio, presupponendo un'architettura di un StatefulSet primario e un StatefulSet secondario con PersistentVolumeClaims dedicati sia per StatefulSet primario che secondario, mostra una strategia 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

Verificare se un ProtectedApplication è pronto per il backup

Puoi verificare se un ProtectedApplication è pronto per un backup eseguendo il seguente comando:

kubectl describe protectedapplication APPLICATION_NAME

Sostituisci APPLICATION_NAME con il nome dell'applicazione.

Se è pronto, la descrizione dell'applicazione mostrerà lo stato Ready to backup come true, come in questo esempio:

% 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>

Passaggi successivi