Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Cómo proteger los datos de tu StatefulSet con Backup for GKE

By Felipe MartinezJul 20, 20237 min read

Esta página también está disponible en English, Deutsch, Français, Italiano, 日本語 y Português.

Introducción

Los StatefulSets son un recurso potente de Kubernetes para gestionar aplicaciones con estado. Sin embargo, también pueden ser complejos y difíciles de respaldar, lo que puede derivar en pérdida de datos ante una falla.

El año pasado (2022), Google anunció una nueva funcionalidad complementaria para GKE llamada Backup for GKE. Se trata de una forma sencilla y nativa de la nube de proteger, gestionar y restaurar todas las aplicaciones y datos en contenedores.

En este artículo recorreremos los componentes de Backup for GKE y veremos cómo respaldar volúmenes de un StatefulSet de MySQL desplegado en un clúster de GKE.

Arquitectura

Backup for GKE consta de dos componentes principales:

  • Un servicio que se ejecuta en Google Cloud y expone una API REST basada en recursos. Este servicio funciona como el plano de control de Backup for GKE e incluye elementos de la consola de Google Cloud que interactúan con esa API.
  • Un agente que se ejecuta en cada clúster donde se realizan backups o restauraciones. El agente lleva a cabo las operaciones de backup y restauración en esos clústeres interactuando con la API de Backup for GKE.

El servicio de Backup for GKE se integra con la UI de GKE, la CLI de Google Cloud y APIs REST, ofreciendo flujos de trabajo consistentes para desarrollo y operaciones. En un backup se capturan dos tipos de datos:

  • Config backup: un conjunto de manifiestos de recursos de Kubernetes extraídos del API server del clúster que se está respaldando, que captura el estado del clúster.
  • Volume backups: un conjunto de respaldos de volúmenes que se corresponden con los recursos PersistentVolumeClaim presentes en el config backup.

Puedes elegir qué workloads quieres respaldar o restaurar, o hacerlo con todos. También puedes respaldar workloads de un clúster y restaurarlos en otro, y programar tus backups para que se ejecuten automáticamente, de modo que puedas reaccionar rápido y recuperar tus workloads ante un incidente.

Cómo hacerlo

En los próximos pasos crearemos un clúster zonal de GKE, desplegaremos un MySQL con estado en el clúster y probaremos tanto la creación del backup como la restauración de la base de datos.

Definir las variables

Para simplificar, vamos a crear algunas variables de entorno:

export PROJECT_ID=felipe-playground-378415
export REGION=us-east1
export LOCATION=us-east1-c
export CLUSTER=backup-for-gke
export BK_PLAN_ALL_NAMESPACES=mysql-bk-plan-all-ns
export RESTORE_PLAN_ALL_NAMESPACES=mysql-bk-plan-all-ns
export BK_ALL_NAMESPACES=mysql-bk-all-namespaces
export RESTORE_ALL_NAMESPACES=mysql-restore-all-namespaces

Crear el clúster de GKE

Definamos algunas variables para simplificar los comandos. Acuérdate de poner tu propio PROJECT_ID. Para este ejercicio crearemos un clúster zonal de GKE en la zona us-east1-c. Un clúster zonal tiene un único plano de control en una sola zona. Para workloads de producción, sin embargo, recomiendo usar clústeres regionales, ya que ofrecen mayor disponibilidad al ejecutar varias réplicas del plano de control en distintas zonas dentro de una misma región. Además, estamos usando todos los valores por defecto del clúster: VPC y subredes por defecto, número de nodos, service account por defecto, etc. No recomiendo dejar los valores por defecto en clústeres de producción.

Acuérdate de incluir el flag --addons=BackupRestore en tu comando para que también se desplieguen los controladores de backup y todos los CRDs.

gcloud container clusters create ${CLUSTER} \
    --release-channel stable \
    --zone ${LOCATION} \
    --node-locations ${LOCATION} \
    --project ${PROJECT_ID} \
    --addons=BackupRestore

Ahora conectémonos al clúster

gcloud container clusters get-credentials ${CLUSTER} \
--zone ${LOCATION} \
--project ${PROJECT_ID}

Instalar un StatefulSet

Ahora vamos a crear nuestro StatefulSet. Para este ejercicio elegí el operador de MySQL, que resulta bastante fácil y directo de instalar con Helm.

helm repo add mysql-operator https://mysql.github.io/mysql-operator/
helm repo update
helm install my-mysql-operator mysql-operator/mysql-operator \
   --namespace mysql-operator --create-namespace

Instalar MySQL

Instala MySQL con Helm. ¡No olvides cambiar la contraseña!

helm install mycluster mysql-operator/mysql-innodbcluster \
   --set tls.useSelfSigned=true \
   --set credentials.root.user=safeuser \
   --set credentials.root.password=notsupersafepassword \
   --set credentials.root.host="%"

Con el comando kubectl get pods,pvc deberías ver algo similar a esto

NAME                                    READY   STATUS    RESTARTS   AGE
pod/mycluster-0                         2/2     Running   0          23m
pod/mycluster-1                         2/2     Running   0          23m
pod/mycluster-2                         2/2     Running   0          23m
pod/mycluster-router-67585969f6-m9nd7   1/1     Running   0          22m

NAME                                        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/datadir-mycluster-0   Bound    pvc-d5214172-9b81-4d29-9bf0-9e0dcdc8f691   2Gi        RWO            standard-rwo   23m
persistentvolumeclaim/datadir-mycluster-1   Bound    pvc-df8e188a-51aa-4c4f-acb1-73daa72bc721   2Gi        RWO            standard-rwo   23m
persistentvolumeclaim/datadir-mycluster-2   Bound    pvc-defb5e6e-5946-4183-99d2-c168b05a3d6c   2Gi        RWO            standard-rwo   23m

¡Perfecto! Como siguiente paso vamos a configurar los recursos de Backup for GKE para nuestro clúster.

Backup for GKE incluye dos tipos de recursos de configuración y control:

  • BackupPlan: un recurso padre de los recursos Backup que representa una cadena de respaldos. Contiene la configuración del backup, incluyendo el clúster de origen, la selección de qué workloads respaldar y la región donde se almacenan los artefactos de Backup generados bajo este plan.
  • RestorePlan: ofrece una plantilla de restauración reutilizable. Contiene la configuración de la restauración, incluyendo el clúster destino donde quieres restaurar el backup, el plan de backup de origen, el alcance de la restauración, el manejo de conflictos y las reglas de sustitución.

Crear un Backup Plan para todos los namespaces

gcloud beta container backup-restore backup-plans create ${BK_PLAN_ALL_NAMESPACES} \
    --project=${PROJECT_ID} \
    --location=${REGION} \
    --cluster=projects/${PROJECT_ID}/locations/${LOCATION}/clusters/${CLUSTER} \
    --all-namespaces \
    --include-secrets \
    --include-volume-data

Crear un Restore Plan para todos los namespaces

gcloud beta container backup-restore restore-plans create ${RESTORE_PLAN_ALL_NAMESPACES}\
  --all-namespaces \
  --project=${PROJECT_ID} \
  --location=${REGION} \
  --backup-plan=projects/${PROJECT_ID}/locations/${REGION}/backupPlans/${BK_PLAN_ALL_NAMESPACES} \
  --cluster=projects/${PROJECT_ID}/locations/${LOCATION}/clusters/${CLUSTER} \
  --cluster-resource-conflict-policy=use-existing-version \
  --namespaced-resource-restore-mode=delete-and-restore \
  --volume-data-restore-policy=restore-volume-data-from-backup \
  --cluster-resource-restore-scope="storage.k8s.io/StorageClass","scheduling.k8s.io/PriorityClass"

Si los comandos anteriores se ejecutaron sin problemas, ya tenemos todos los planes listos.

Crear un backup para todos los namespaces

gcloud beta container backup-restore backups create ${BK_ALL_NAMESPACES} \
--project=${PROJECT_ID} \
--location=${REGION} \
--backup-plan=${BK_PLAN_ALL_NAMESPACES} \
--wait-for-completion

Esto puede tardar un rato según el tamaño de tus volúmenes, pero apenas termine deberías ver el siguiente mensaje.

Backup completed. Backup state: SUCCEEDED

Probar la restauración del backup

gcloud beta container backup-restore restores create ${RESTORE_ALL_NAMESPACES} \
  --project=${PROJECT_ID} \
  --location=${REGION} \
  --restore-plan=${RESTORE_PLAN_ALL_NAMESPACES} \
  --backup=projects/$PROJECT_ID/locations/${REGION}/backupPlans/${BK_PLAN_ALL_NAMESPACES}/backups/${BK_ALL_NAMESPACES} \
  --wait-for-completion

Restore Completed. Restore stat: SUCCEEDED

¡Y listo, funciona!

Backup for GKE también te permite respaldar un único bundle de aplicación creado mediante el CRD ProtectedApplication, pero eso lo dejamos para otro post.

IaC

A día de hoy (junio/2023) solo contamos con un recurso de Terraform para crear un GKE Backup Plan, llamado google_gke_backup_backup_plan, agregado en la versión 4.5.0 del provider de Google, como puedes ver aquí. Ojalá pronto haya más recursos disponibles.

Precios

Backup for GKE genera cargos en dos dimensiones: por un lado, una tarifa de gestión de backups de GKE basada en el número de pods de GKE protegidos y, por otro, una tarifa de almacenamiento de backups basada en la cantidad de datos (GB) almacenados. Ambas se calculan mensualmente, igual que la facturación de otras funcionalidades de GKE.

Por ejemplo, un cliente con un único backup plan en Iowa (us-central1) que respalda en promedio 20 pods durante un mes y almacena 200 GB de datos de backup en Iowa, pagaría 25,60 USD. Esos 25,60 USD se componen de 20 USD del mes por la gestión de backups de GKE (20 x 1,00 USD / pod-mes) y 5,60 USD por el almacenamiento del backup (200 * 0,028 USD / GB-mes).

A partir del 26 de junio de 2023 se introducirán nuevos cargos de salida de red para los backups que se almacenen en una región distinta a la de su clúster GKE de origen. Estos cargos se calcularán en función de la región de origen y destino y de la cantidad de bytes transferidos en cada operación de backup "cross-region"

Limpieza

Eliminar el clúster

gcloud container clusters delete ${CLUSTER} --project $PROJECT_ID --zone ${LOCATION}

No olvides eliminar también los backups y los planes.

# Eliminar backup
gcloud beta container backup-restore backups delete ${BK_ALL_NAMESPACES} \
  --location=${REGION} \
  --backup-plan=${BK_PLAN_ALL_NAMESPACES}
# Eliminar backup plan
gcloud beta container backup-restore backup-plans delete ${BK_PLAN_ALL_NAMESPACES} \
  --location=${REGION}
# Eliminar restore plan
gcloud beta container backup-restore restore-plans delete ${RESTORE_PLAN_ALL_NAMESPACES} \
  --location=${REGION}

¡Espero que disfrutes el recorrido y, si tienes alguna pregunta, no dudes en escribirme!