Define una lógica de copia de seguridad y restablecimiento personalizada


Cuando habilitas el agente de Copia de seguridad para GKE en tu clúster de Google Kubernetes Engine, este proporciona un CustomResourceDefinition que presenta un tipo nuevo de recurso de Kubernetes: ProtectedApplication.

La composición de un ProtectedApplication implica dos actividades:

Los recursos ProtectedApplication te proporcionan estas funciones cuando personalizan la lógica de copia de seguridad y restablecimiento a nivel de aplicación:

  • Operaciones de copia de seguridad y restablecimiento más detalladas Sin ProtectedApplications, el alcance de tus copias de seguridad debe definirse en el nivel Namespace (ya sea seleccionando allNamespaces o selectedNamespaces). Una lógica similar aplica a la restauración de recursos con espacio de nombres. La creación de recursos ProtectedApplication te permite proporcionar un nombre a un subconjunto de recursos en una Namespace. Luego, puedes crear una copia de seguridad y restablecer ese subconjunto mediante la enumeración de selectedApplications en el alcance de la copia de seguridad (y, de forma similar, para el restablecimiento).

  • Organizar detalles detallados del proceso de copia de seguridad o restablecimiento, incluidos los siguientes:

    • Se omiten los volúmenes seleccionados durante la creación de la copia de seguridad.

    • Incorporar la topología de la aplicación en la copia de seguridad y restablecimiento (por ejemplo, crear una copia de seguridad de una instancia de una base de datos replicada y usarla para restablecer varias instancias).

    • Ejecutar hooks definidos por el usuario antes y después de tomar instantáneas de los volúmenes. Estas se pueden usar, por ejemplo, para limpiar y desactivar la carga de trabajo antes de tomar la instantánea y dejar de activarla después.

Puedes crear ProtectedApplication a través de kubectl como otros recursos de Kubernetes. Son completamente opcionales. Si los recursos ProtectedApplication no están presentes, las copias de seguridad para GKE crean copias de seguridad de los volúmenes de todos los volúmenes dentro del alcance de una copia de seguridad, y las copias de seguridad de los volúmenes resultantes tendrán consistencia de fallas - Se capturarán todas las escrituras vacías en el disco en un momento determinado (es decir, sin escrituras parciales). Sin embargo, algunas aplicaciones pueden mantener los datos en la memoria que no se pasan al disco, por lo que si la aplicación puede recuperarse de forma correcta de una copia de seguridad coherente en función de una falla depende de la lógica de la aplicación.

Selecciona recursos

El primer paso para compilar tu recurso ProtectedApplication es identificar los otros recursos en el mismo Namespace que deseas incluir como parte de la aplicación. Este es el conjunto de recursos de los que se realizará una copia de seguridad o se restablecerá si proporcionas la opción de permiso selectedApplications en la configuración de BackupPlan.

Los recursos se identifican mediante un selector de etiquetas. Esto requiere que etiquetes todos tus recursos (mediante el campo metadata.label en cada recurso) con la misma etiqueta. Ten en cuenta que esto también se aplica a los recursos que los controladores crean de forma automática. Estos recursos creados automáticamente se etiquetan a través de su plantilla correspondiente. Ten en cuenta que es común reutilizar la misma etiqueta que ya usas para asociar Pods y PersistentVolumeClaims generados con su recurso superior. En el siguiente ejemplo, se muestra cómo puedes aplicar la etiqueta app: nginx a otros recursos además de 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 vez que hayas aplicado la etiqueta seleccionada a todos los recursos de destino (y las plantillas a partir de las que se generan los recursos adicionales), puedes hacer referencia a esos recursos desde una ProtectedApplication. Por ejemplo:

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

Define reglas de organización

Una vez que hayas identificado todos los recursos en tu ProtectedApplication, puedes definir reglas de organización detalladas para un subconjunto de estos. Estas reglas solo se pueden aplicar a dos tipos de recursos: Deployments y StatefulSets, y se hace referencia a ellos en la sección components del ProtectedApplication.

Descripción general de los componentes

La configuración de un componente implica lo siguiente:

  • Selecciona una estrategia fundamental para saber cómo funcionarán la copia de seguridad y el restablecimiento de este componente. Hay tres estrategias disponibles:

    • BackupAllRestoreAll: Crea una copia de seguridad de los volúmenes asociados con todas las instancias del componente y restablécelos desde las copias de seguridad

    • BackupOneRestoreAll: Crea una copia de seguridad de los volúmenes desde una sola instancia del componente y usa esas copias de seguridad para restablecer todas las instancias

    • DumpAndLoad: exporta datos de la aplicación a un solo volumen en el momento de la copia de seguridad y, luego, importa esos datos a la aplicación en el momento del restablecimiento

  • Definir los hooks de ejecución para que se ejecuten durante la copia de seguridad (y posiblemente restablecer, según la estrategia). Un hook es un comando que se ejecuta en contenedores específicos.

  • Selecciona un subconjunto de volúmenes para crear una copia de seguridad.

Hooks de ejecución

Un hook es un comando de shell que realiza la copia de seguridad de GKE en un contenedor en una fase particular del proceso de copia de seguridad o restablecimiento.

Hay cuatro tipos diferentes de hooks:

  • pre hooks: Estos comandos se ejecutan justo antes de que se cree una copia de seguridad de los volúmenes y, por lo general, se espera que limpien los datos que están en la memoria en el disco y, luego, desactiva la aplicación para que no se realicen escrituras nuevas. Estos hooks se usan en las estrategias BackupAllRestoreAll y BackupOneRestoreAll.

  • post hooks: Estos comandos se ejecutan durante el proceso de copia de seguridad del volumen justo después del paso de INSTANTÁNEA del proceso de copia de seguridad del volumen (antes del paso de SUBIDA). Por lo general, el paso de INSTANTÁNEAS toma solo unos segundos. Por lo general, se espera que la aplicación esté inactiva (es decir, que permitan el procesamiento normal y las escrituras del disco). Estos hooks se usan en las estrategias BackupAllRestoreAll, BackupOneRestoreAll y DumpAndLoad.

  • dump hooks: Estos comandos se ejecutan antes de que se cree una copia de seguridad del volumen en la estrategia DumpAndLoad y, por lo general, se espera que exporten datos de la aplicación al volumen de copia de seguridad designado.

  • load hooks: Estos comandos se ejecutan en el momento del restablecimiento después de que el volumen de copia de seguridad se restablece en casos de estrategia DumpAndLoad. Por lo general, se espera que importen los datos del volumen de copia de seguridad a la aplicación.

Puedes proporcionar más de un hook por cada tipo, y Copia de seguridad para GKE los ejecutará en el orden en que los defines.

Defines hooks como parte de la sección de componentes de la especificación ProtectedApplication. Todas las definiciones de hook tienen los mismos campos disponibles:

  • name: Es el nombre que asignas al hook.

  • container: (opcional) nombre del contenedor para ejecutar comando. Si no proporcionas el contenedor, Copia de seguridad para GKE ejecutará el hook en el primer contenedor definido para los Pod de destino.

  • command: Este es el comando real que se envía al contenedor, construido como un arreglo de palabras. La primera palabra del arreglo es la ruta de acceso al comando y las palabras posteriores son los argumentos que se pasarán al comando.

  • timeoutSeconds: (Opcional) tiempo antes de que se anule la ejecución del hook. Si no proporcionas esto, el valor predeterminado es 30 segundos.

  • onError: Es el comportamiento (opcional) que se toma cuando falla el hook. Se puede establecer en Ignore o Fail (predeterminado). Si configuras esto como Fail, cuando un hook falla, la copia de seguridad del volumen fallará. Si estableces esto en Ignore, se ignoran las fallas de este hook.

Antes de aplicar los hooks ProtectedApplication a la aplicación, debes probar el comando mediante kubectl exec para asegurarte de que los hooks se comporten como se espera:

kubectl exec POD_NAME -- COMMAND

Reemplaza lo siguiente:

  • POD_NAME: el nombre del pod que contiene el recurso ProtectedApplication.
  • COMMAND: Es el array que contiene el comando que deseas ejecutar en el contenedor, por ejemplo, /sbin/fsfreeze, -f, /var/log/nginx.

Selecciona un subconjunto de volúmenes para crear una copia de seguridad

A veces, las aplicaciones escriben en volúmenes que no son interesantes para restablecer (por ejemplo, algunos volúmenes de registro o provisorios). Puedes suprimir la copia de seguridad de estos volúmenes con un selector de volúmenes.

Para usar esta función, primero debes aplicar una etiqueta común a los volúmenes que deseas crear una copia de seguridad y, luego, dejar esta etiquetadesactivado los volúmenes a los que no quieres hacer copia de seguridad. Luego, debes incluir una cláusula volumeSelector en la definición del componente de la siguiente manera:

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

Si proporcionas un volumeSelector para un componente, solo se creará una copia de seguridad y se restablecerán los volúmenes que tengan la etiqueta determinada. En el momento del restablecimiento, cualquier otro volumen se aprovisionará como vacío en lugar de restablecerse a partir de una copia de seguridad de volumen.

Estrategia: BackupAllRestoreAll

Esta es la estrategia más simple y crea una copia de seguridad de todos los volúmenes del componente en el momento de la copia de seguridad y los restablece desde las copias de seguridad de los volúmenes en el momento del restablecimiento. Es la mejor opción cuando tu aplicación no tiene replicación entre Pods.

Esta estrategia admite los siguientes parámetros:

  • backupPreHooks: Es una lista ordenada de hooks que se ejecutan justo antes de que se cree una copia de seguridad de los volúmenes (opcional). Estos comandos se ejecutan en todos los Pods del componente.

  • backupPostHooks (opcional): Es una lista ordenada de hooks que se ejecutan después de que las copias de seguridad de volumen llegan a la fase de CARGA. Estos comandos se ejecutan en todos los Pods del componente.

  • volumeSelector: (Opcional) lógica para hacer coincidir un subconjunto de volúmenes con copia de seguridad.

En este ejemplo, se crea un recurso ProtectedApplication que desactiva el sistema de archivos antes de crear una copia de seguridad del volumen de registros y lo vuelve a activar después de la copia de seguridad:

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1alpha2
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 ]

Estrategia: BackupOneAndRestoreAll

Esta estrategia crea una copia de seguridad de una copia de un Pod seleccionado. Esta única copia es la fuente para restablecer todos los pods durante un restablecimiento. Este método puede ayudar a reducir el costo de almacenamiento y el tiempo de creación de una copia de seguridad. Esta estrategia funciona en una configuración de alta disponibilidad cuando se implementa un componente con una PersistentVolumeClaim principal y varias PersistentVolumeClaims secundarias.

Esta estrategia admite los siguientes parámetros:

  • backupTargetName: Especifica qué Deployment o StatefulSet deseas usar para crear una copia de seguridad de los datos (obligatorio) Se selecciona automáticamente el mejor Pod para crear una copia de seguridad. En una configuración de alta disponibilidad, te recomendamos que establezcas esto en una de las réplicas de tu aplicación.

  • backupPreHooks: Es una lista ordenada de hooks que se ejecutan justo antes de que se cree una copia de seguridad de los volúmenes (opcional). Estos comandos se ejecutan solo en el Pod de copia de seguridad seleccionado.

  • backupPostHooks (opcional): Es una lista ordenada de hooks que se ejecutan después de que las copias de seguridad de volumen llegan a la fase de CARGA. Estos comandos se ejecutan solo en el Pod de copia de seguridad seleccionado.

  • volumeSelector: (Opcional) lógica para hacer coincidir un subconjunto de volúmenes con copia de seguridad.

Si un componente se configura con varios Deployments o StatefulSets, todos los recursos deben tener la misma estructura de PersistentVolume, lo que significa que deben seguir estas reglas:

  • La cantidad de PersistentVolumeClaims que usan todos los Deployments o StatefulSets debe ser la misma.
  • El propósito de PersistentVolumeClaims en el mismo índice debe ser el mismo. Para los StatefulSets, el índice se define en la volumeClaimTemplate. Para los Deployments, el índice se define en Volumes y se omiten los volúmenes no persistentes.
  • Si el componente de la aplicación consiste en Deployments, cada Deployment debe tener exactamente una réplica.

Según estas consideraciones, se pueden seleccionar varios conjuntos de volúmenes para la copia de seguridad, pero solo se seleccionará un volumen de cada conjunto de volúmenes.

En este ejemplo, si suponemos que se usa una arquitectura de un StatefulSet principal y un StatefulSet secundario, se muestra una copia de seguridad de los volúmenes de un pod en el StatefulSet secundario y, luego, un restablecimiento a todos los demás volúmenes:

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1alpha2
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: [...]

Estrategia: DumpAndLoad

Esta estrategia usa un volumen dedicado para los procesos de copia de seguridad y restablecimiento, y requiere una PersistentVolumeClaim dedicada adjunta a un componente que almacena datos de volcado.

Esta estrategia admite los siguientes parámetros:

  • dumpTarget: Especifica qué Deployment o StatefulSet deseas usar para crear una copia de seguridad de los datos (obligatorio) Se selecciona automáticamente el mejor Pod para crear una copia de seguridad. En una configuración de alta disponibilidad, te recomendamos que establezcas una de tus réplicas de la aplicación.

  • loadTarget: Especifica qué Deployment o StatefulSet se debe usar para cargar los datos (obligatorio). Se selecciona automáticamente el mejor Pod para crear una copia de seguridad. El objetivo de carga no tiene que ser el mismo que el objetivo de volcado.

  • dumpHooks: Es una lista ordenada de hooks que se ejecutan para propagar el volumen de copia de seguridad dedicado (obligatorio). Estos comandos solo se ejecutan en el volcado Pod seleccionado.

  • backupPostHooks (opcional): Es una lista ordenada de hooks que se ejecutan después de que las copias de seguridad de volumen llegan a la fase de CARGA. Estos comandos se ejecutan solo en el volcado Pod seleccionado.

  • loadHooks: Es una lista ordenada de hooks que se ejecutan para cargar los datos del volumen restablecido después de que se inicia la aplicación (obligatorio). Estos comandos se ejecutan solo en la carga Pod seleccionada.

  • volumeSelector: (obligatorio) la lógica para hacer coincidir un solo volumen con la copia de seguridad y el restablecimiento (el volumen de volcado). Aunque solo debe coincidir con un solo volumen, debes configurarlo de la misma manera que lo haces en el subconjunto de volúmenes para copia de seguridad que usan otras estrategias.

Si la aplicación consiste en Deployments, cada Deployment debe tener exactamente una réplica.

En este ejemplo, si suponemos que se usa una arquitectura de un StatefulSet principal y un StatefulSet secundario con PersistentVolumeClaims dedicado para los StatefulSets principales y secundarios, se muestra una estrategia de DumpAndLoad:

kind: ProtectedApplication
apiVersion: gkebackup.gke.io/v1alpha2
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

Verifica si una ProtectedApplication está lista para la creación de una copia de seguridad

A fin de verificar si una ProtectedApplication está lista para la creación de una copia de seguridad, ejecuta el siguiente comando:

kubectl describe protectedapplication APPLICATION_NAME

Reemplaza APPLICATION_NAME por el nombre de la aplicación.

Si está lista, la descripción de la aplicación mostrará el estado Ready to backup como true, como en este ejemplo:

% kubectl describe protectedapplication nginx
Name:         nginx
Namespace:    default
API Version:  gkebackup.gke.io/v1alpha2
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>

¿Qué sigue?