Introdução
StatefulSets são um recurso poderoso do Kubernetes para gerenciar aplicações com estado. Por outro lado, também podem ser complexos e difíceis de incluir em rotinas de backup, o que pode resultar em perda de dados em caso de falha.
No ano passado (2022), o Google anunciou um novo add-on para o GKE chamado Backup For GKE: uma forma simples e nativa da nuvem de proteger, gerenciar e restaurar todas as aplicações em containers e seus dados.
Neste artigo, vamos percorrer os componentes do Backup For GKE e ver como fazer backup dos volumes de um StatefulSet MySQL rodando em um cluster GKE.
Arquitetura
O Backup for GKE é formado por dois componentes principais:
- Um serviço que roda no Google Cloud e expõe uma API REST baseada em recursos. Esse serviço atua como o control plane do Backup for GKE e inclui elementos da interface do console do Google Cloud que se comunicam com essa API.
- Um agente que roda em todo cluster onde os backups ou restaurações acontecem. O agente executa as operações de backup e restauração nesses clusters interagindo com a API do Backup for GKE.
O serviço Backup for GKE se integra à interface do GKE, à CLI do Google Cloud e às APIs REST, oferecendo fluxos consistentes para desenvolvimento e operações. Um backup captura dois tipos de dados:
- Config backup: um conjunto de manifestos de recursos do Kubernetes extraídos do API server do cluster que está sendo copiado, capturando o estado do cluster.
- Volume backups: um conjunto de backups de volume que correspondem aos recursos
PersistentVolumeClaimpresentes no config backup.
Você pode escolher quais workloads quer copiar ou restaurar, ou então copiar e restaurar todos de uma vez. Dá para fazer backup dos workloads de um cluster e restaurá-los em outro. Também é possível agendar os backups para rodarem automaticamente, garantindo uma resposta rápida e a recuperação dos workloads em caso de incidente.
Passo a passo
Nas próximas etapas, vamos criar um cluster GKE zonal, implantar um MySQL com estado e testar tanto a criação do backup quanto a restauração do nosso banco.
Definir as variáveis
Para facilitar, vamos criar algumas variáveis de ambiente:
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
Criar o cluster GKE
Vamos definir algumas variáveis para simplificar os comandos. Lembre-se de colocar o seu próprio PROJECT_ID. Para este exercício, vamos criar um cluster GKE zonal na zona us-east1-c. Um cluster zonal tem um único control plane em uma única zona. Para workloads de produção, recomendo clusters regionais, que oferecem mais disponibilidade rodando várias réplicas do control plane em diferentes zonas de uma mesma região. Também estamos usando todos os valores padrão do cluster, como VPC e subnets padrão, número de nós, conta de serviço padrão etc. Não recomendo manter os valores padrão em clusters de produção.
Não esqueça de incluir a flag --addons=BackupRestore no comando para que os controllers de backup e todas as CRDs também sejam implantados.
gcloud container clusters create ${CLUSTER} \
--release-channel stable \
--zone ${LOCATION} \
--node-locations ${LOCATION} \
--project ${PROJECT_ID} \
--addons=BackupRestore
Agora vamos conectar ao cluster:
gcloud container clusters get-credentials ${CLUSTER} \
--zone ${LOCATION} \
--project ${PROJECT_ID}
Instalar um StatefulSet
Agora vamos criar nosso StatefulSet. Para este exercício, escolhi o operator do MySQL, que é bem fácil e direto de instalar via 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 o MySQL
Instale o MySQL com Helm — e não esqueça de trocar a senha!
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="%"
Rodando kubectl get pods,pvc, você deve ver algo parecido com isto:
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
Perfeito! No próximo passo, vamos configurar os recursos do Backup for GKE para o nosso cluster.
O Backup for GKE inclui dois tipos de recursos de configuração e controle:
BackupPlan: um recurso pai dos recursosBackup, que representam uma cadeia de backups. Ele contém a configuração do backup, incluindo o cluster de origem, a seleção de quais workloads copiar e a região onde os artefatos deBackupgerados por esse plano ficam armazenados.RestorePlan: oferece um template reutilizável de restauração. Esse recurso contém a configuração da restauração, incluindo o cluster de destino, o plano de backup de origem, o escopo da restauração, o tratamento de conflitos e as regras de substituição.
Criar um plano de backup para todos os 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
Criar um plano de restauração para todos os 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"
Se os comandos acima rodaram sem problemas, todos os planos já estão configurados.
Criar um backup para todos os 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
Isso pode demorar um pouco, dependendo do tamanho dos seus volumes, mas você verá a mensagem abaixo assim que terminar.
Backup completed. Backup state: SUCCEEDED
Testar a restauração do 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
Funcionou redondo!
O Backup for GKE também permite copiar um único bundle de aplicação criado pela CRD ProtectedApplication, mas isso fica para outro post.
IaC
Hoje (jun/2023), só existe um recurso do Terraform para criar um GKE Backup Plan, chamado google_gke_backup_backup_plan, adicionado na versão 4.5.0 do provider do Google, como você pode ver aqui. Esperamos que mais recursos cheguem em breve.
Preços
O Backup for GKE cobra em duas frentes: primeiro, há uma taxa de gerenciamento de backup do GKE, baseada no número de pods do GKE protegidos; segundo, há uma taxa de armazenamento de backup, baseada no volume de dados (GB) armazenado. As duas taxas são calculadas mensalmente, do mesmo jeito que outras cobranças de funcionalidades do GKE.
Por exemplo: um cliente com um único plano de backup em Iowa (us-central1) que faz backup de uma média de 20 pods em um mês, armazenando 200 GB de dados de backup em Iowa, pagaria US$ 25,60. Esses US$ 25,60 incluem US$ 20 no mês pelo gerenciamento de backup do GKE (20 x US$ 1,00 / pod-mês) e US$ 5,60 pelo armazenamento de backup (200 x US$ 0,028 / GB-mês).
A partir de 26/06/2023, passam a valer novas cobranças de saída de rede para backups armazenados em uma região diferente do cluster GKE de origem. Essas cobranças levam em conta as regiões de origem e destino e o número de bytes transferidos em cada operação de backup "entre regiões".
Limpeza
Excluir o cluster:
gcloud container clusters delete ${CLUSTER} --project $PROJECT_ID --zone ${LOCATION}
E não esqueça de excluir também os backups e os planos.
# Excluir backup
gcloud beta container backup-restore backups delete ${BK_ALL_NAMESPACES} \
--location=${REGION} \
--backup-plan=${BK_PLAN_ALL_NAMESPACES}
# Excluir plano de backup
gcloud beta container backup-restore backup-plans delete ${BK_PLAN_ALL_NAMESPACES} \
--location=${REGION}
# Excluir plano de restauração
gcloud beta container backup-restore restore-plans delete ${RESTORE_PLAN_ALL_NAMESPACES} \
--location=${REGION}
Espero que curta o processo e, se tiver qualquer dúvida, é só me chamar!
No geral, o Backup for GKE é uma ferramenta poderosa para proteger os dados dos seus StatefulSets. Se você usa StatefulSets no Kubernetes, vale considerar o Backup for GKE para manter seus dados a salvo.
Recursos:
Pricing | Google Kubernetes Engine (GKE) | Google Cloud \ Review pricing for GKE\ cloud.google.com