1. Introdução
Neste codelab, você faz backup de um cluster de alta disponibilidade (HA) para repositório de objetos compatível com S3 para o AlloyDB Omni usando o orquestrador RPM.
Este codelab usa o cluster do codelab Implantar um cluster de alta disponibilidade do AlloyDB Omni em VMs do GCE usando o orquestrador RPM para criar um cluster de alta disponibilidade em máquinas virtuais (VMs) do Compute Engine. Neste codelab, você vai adicionar um servidor de repositório de objetos compatível com S3 a uma das VMs. Você usa o servidor de repositório de objetos para o cluster de alta disponibilidade fazer backup dos dados e restaurar o cluster do servidor.

Pré-requisitos
- Ter um projeto do Google Cloud com o faturamento ativado.
- Os papéis do IAM listados no codelab de alta disponibilidade.
- Conhecimento básico de comandos do Linux e SQL.
O que você vai aprender
- Como instalar e executar um repositório de objetos compatível com S3 para backups.
- Como criar um plano de backup que grava backups em um armazenamento compatível com S3.
- Como criar um backup sob demanda.
- Como restaurar um cluster de um backup e para um momento específico.
O que é necessário
- Os URLs dos repositórios de software do AlloyDB Omni e da coleção Ansible do orquestrador. Para receber os URLs, preencha o formulário de inscrição do AlloyDB Omni. Para mais informações, consulte a Visão geral do AlloyDB Omni usando RPM. Você vai usar os URLs no codelab de alta disponibilidade.
- Um cluster de alta disponibilidade do AlloyDB Omni do codelab Implantar um cluster de alta disponibilidade do AlloyDB Omni em VMs do GCE usando o orquestrador RPM.
- Um terminal com acesso ao Google Cloud e um Cloud Shell.
2. Configuração e requisitos
- Nesta etapa, você vai criar um cluster de alta disponibilidade usando o codelab Implantar um cluster de alta disponibilidade do AlloyDB Omni em VMs do GCE usando o orquestrador RPM. Siga as etapas a seguir. Se você já tiver um cluster do codelab, siga para a próxima etapa.
- Observação: não execute a etapa "Limpar recursos" nesta fase. Você vai realizar essa etapa no final deste codelab.
- Volte a este codelab
3. Conectar ao cluster e adicionar dados de amostra
Nesta etapa, você carrega as configurações do cluster na VM de controle. Em seguida, conecte-se ao cluster e adicione uma tabela com dados de amostra.
- Se você não estiver conectado à VM de controle, faça isso no Cloud Shell:
As variáveisgcloud compute ssh "$CLUSTER-control" --zone="$ZONE" --project="$PROJECT"CLUSTER,ZONEePROJECTvêm da etapa Preparar as VMs para a implantação do codelab Implantar um cluster de alta disponibilidade do AlloyDB Omni em VMs do GCE usando o orquestrador RPM. Se o Cloud Shell não tiver essas variáveis, defina-as novamente. - Na VM de controle, mude para seu diretório inicial e carregue as variáveis de ambiente. Em seguida, adicione o nome do cluster e o usuário SSH ao arquivo de ambiente:
Verifique se a saída mostracd ~ source /tmp/cluster.conf cat >> ~/.codelab.env <<EOF export CLUSTER="$cluster" export SSH_USER="$service_account" EOF source ~/.codelab.env env | grep -E '^(CLUSTER|SSH_USER|VIRTUAL_IP)='CLUSTER,SSH_USEReVIRTUAL_IP. Observação:se você se conectar à VM de controle novamente mais tarde, executecd ~esource ~/.codelab.envantes de continuar. - Adicione as configurações de conexão ao arquivo de ambiente. Quando o comando
readpedir a senha, digite a senha do usuáriopostgres. Você define essa senha na etapa Inicializar o cluster do AlloyDB Omni do codelab Implantar um cluster de alta disponibilidade do AlloyDB Omni em VMs do GCE usando o orquestrador RPM.cat >> ~/.codelab.env <<'EOF' export PATH="/usr/pgsql-18/bin:$PATH" export PGHOST="$VIRTUAL_IP" export PGUSER="postgres" EOF read -rsp "Password of the postgres user: " PGPASSWORD; echo printf 'export PGPASSWORD=%q\n' "$PGPASSWORD" >> ~/.codelab.env source ~/.codelab.env env | grep -E '^(PGHOST|PGUSER|PGPASSWORD)=' - Crie uma tabela e adicione 1.000 linhas:
psql <<'SQL' CREATE TABLE public.orders ( id integer PRIMARY KEY, item text NOT NULL, created_at timestamptz NOT NULL DEFAULT pg_catalog.now() ); INSERT INTO public.orders (id, item) SELECT g, 'item-' || g FROM pg_catalog.generate_series(1, 1000) AS g; SQL - Conte as linhas:
Verifique se a saída retornapsql -c "SELECT pg_catalog.count(*) FROM public.orders;"1000.
4. Instalar e executar o repositório de objetos compatível com S3
Nesta etapa, você vai escrever um playbook do Ansible que instala um servidor MinIO na VM de controle. O playbook também cria o bucket e o usuário para os backups e garante que as VMs de banco de dados possam se conectar ao MinIO. Execute todos os comandos desta etapa na VM de controle.
- Na VM de controle, adicione as configurações de armazenamento ao arquivo de ambiente. Os comandos
opensslcriam senhas aleatórias. Verifique se a saída mostra o nome e o endereço IP interno da VM de controle, por exemplo,MD=http://metadata.google.internal/computeMetadata/v1/instance S3_IP=$(curl -s -H "Metadata-Flavor: Google" "$MD/network-interfaces/0/ip") cat >> ~/.codelab.env <<EOF export S3_IP="$S3_IP" export S3_HOST="$CLUSTER-control" export S3_BUCKET="alloydb-backups" export S3_REGION="us-east-1" export MINIO_ROOT_USER="s3admin" export MINIO_ROOT_PASSWORD="$(openssl rand -hex 16)" export S3_ACCESS_KEY_ID="alloydb-backup" export S3_SECRET_ACCESS_KEY="$(openssl rand -hex 16)" export MINIO_URL="https://github.com/minio/minio/releases/download/RELEASE.2024-05-10T01-41-38Z/minio.linux-amd64.RELEASE.2024-05-10T01-41-38Z" export MC_URL="https://github.com/minio/mc/releases/download/RELEASE.2024-05-09T17-04-24Z/mc.linux-amd64.RELEASE.2024-05-09T17-04-24Z" EOF source ~/.codelab.env echo "$S3_HOST $S3_IP"my-cluster-control 10.1.0.2. As VMs de banco de dados usam esse nome do host e endereço IP para se conectar ao MinIO. O servidor de metadados da VM fornece o endereço IP. Para mais informações, consulte a documentação de metadados da VM.Os valoresMINIO_URLeMC_URLsão os URLs de download do servidor MinIO e do cliente MinIO (mc). - Instale a coleção
community.cryptodo Ansible necessária na VM de controle:ansible-galaxy collection install community.crypto - Crie o playbook
s3_server.yaml: A variávelcat > s3_server.yaml <<EOF - name: Install and run MinIO on the control VM hosts: localhost connection: local become: true gather_facts: false tasks: - name: Create MinIO directories ansible.builtin.file: path: "{{ item }}" state: directory mode: "0755" loop: - /var/lib/minio/data - /var/lib/minio/certs - name: Download MinIO server and client ansible.builtin.get_url: url: "{{ item.url }}" dest: "{{ item.dest }}" mode: "0755" loop: - url: "$MINIO_URL" dest: /usr/local/bin/minio - url: "$MC_URL" dest: /usr/local/bin/mc - name: Generate MinIO TLS private key community.crypto.openssl_privatekey: path: /var/lib/minio/certs/private.key size: 2048 mode: "0600" - name: Generate MinIO certificate signing request community.crypto.openssl_csr_pipe: privatekey_path: /var/lib/minio/certs/private.key common_name: "$S3_HOST" subject_alt_name: - "DNS:$S3_HOST" - "DNS:$S3_BUCKET.$S3_HOST" - "DNS:localhost" - "IP:127.0.0.1" - "IP:$S3_IP" register: minio_csr - name: Generate self-signed MinIO TLS certificate community.crypto.x509_certificate: path: /var/lib/minio/certs/public.crt csr_content: "{{ minio_csr.csr }}" privatekey_path: /var/lib/minio/certs/private.key provider: selfsigned selfsigned_not_after: "+365d" mode: "0644" - name: Create MinIO systemd service unit ansible.builtin.copy: dest: /etc/systemd/system/minio.service mode: "0600" content: | [Unit] Description=MinIO Object Storage After=network.target [Service] Environment="MINIO_ROOT_USER=$MINIO_ROOT_USER" Environment="MINIO_ROOT_PASSWORD=$MINIO_ROOT_PASSWORD" Environment="MINIO_DOMAIN=$S3_HOST" ExecStart=/usr/local/bin/minio server /var/lib/minio/data --certs-dir /var/lib/minio/certs Restart=on-failure [Install] WantedBy=multi-user.target - name: Start and enable MinIO service ansible.builtin.systemd_service: name: minio daemon_reload: true state: started enabled: true - name: Add storage host names to /etc/hosts on the control VM ansible.builtin.lineinfile: path: /etc/hosts line: "$S3_IP $S3_HOST $S3_BUCKET.$S3_HOST" state: present - name: Wait for MinIO health endpoint ansible.builtin.uri: url: "https://$S3_HOST:9000/minio/health/live" ca_path: /var/lib/minio/certs/public.crt status_code: 200 register: minio_health until: minio_health.status == 200 retries: 6 delay: 5 - name: Create backup bucket and user in MinIO ansible.builtin.command: argv: "{{ item }}" loop: - - /usr/local/bin/mc - --insecure - alias - set - s3repo - "https://$S3_HOST:9000" - "$MINIO_ROOT_USER" - "$MINIO_ROOT_PASSWORD" - - /usr/local/bin/mc - --insecure - mb - --ignore-existing - "s3repo/$S3_BUCKET" - - /usr/local/bin/mc - --insecure - admin - user - add - s3repo - "$S3_ACCESS_KEY_ID" - "$S3_SECRET_ACCESS_KEY" - - /usr/local/bin/mc - --insecure - admin - policy - attach - s3repo - readwrite - --user - "$S3_ACCESS_KEY_ID" become: false no_log: true - name: Configure database VMs for MinIO hosts: primary_instance_nodes become: true gather_facts: false vars: ansible_user: $SSH_USER ansible_ssh_private_key_file: $HOME/ssh-key-cluster-sa tasks: - name: Set SELinux to permissive mode ansible.builtin.command: cmd: setenforce 0 - name: Add storage host names to /etc/hosts ansible.builtin.lineinfile: path: /etc/hosts line: "$S3_IP $S3_HOST $S3_BUCKET.$S3_HOST" state: present - name: Verify storage host resolution ansible.builtin.getent: database: hosts key: "$S3_BUCKET.$S3_HOST" - name: Verify connection to MinIO ansible.builtin.uri: url: "https://$S3_HOST:9000/minio/health/live" validate_certs: false status_code: 200 EOFMINIO_DOMAINpermite que o MinIO aceite solicitações de estilo de host virtual. O orquestrador RPM usa o usuárioalloydb-backuppara gravar os backups. A políticareadwriteé uma política integrada do MinIO. - Execute o playbook:
Verifique se a saídaansible-playbook s3_server.yaml -i deployment_spec.yamlPLAY RECAPmostrafailed=0paralocalhoste para cada VM de banco de dados. - Verifique se o bucket existe:
Verifique se a saída mostra o bucketmc --insecure ls s3repoalloydb-backups/.
5. Criar um plano de backup
Um plano de backup contém o local de armazenamento, a programação e o período de retenção dos backups de um cluster. Nesta etapa, você vai criar um plano de backup para o bucket do MinIO.
- Na VM de controle, crie os playbooks de backup e de status. Você usa o playbook de backup para os recursos
Secret,BackupPlaneBackup. Você usa o playbook de status para mostrar o status de um recurso.cat > backup.yaml <<EOF - name: Manage AlloyDB Omni backups hosts: localhost roles: - role: google.alloydbomni_orchestrator.backup EOF cat > status.yaml <<EOF - name: Get resource status hosts: localhost roles: - role: google.alloydbomni_orchestrator.status EOF - Crie um recurso
Secretpara as credenciais do S3. Em seguida, aplique o recurso: Os nomes das chaves na seçãoS3_KEY_ID_B64=$(printf '%s' "$S3_ACCESS_KEY_ID" | base64 -w 0) S3_KEY_B64=$(printf '%s' "$S3_SECRET_ACCESS_KEY" | base64 -w 0) cat > s3_secret.yaml <<EOF Secret: metadata: name: s3-backup-secret spec: type: Opaque data: access-key-id: "$S3_KEY_ID_B64" access-key: "$S3_KEY_B64" EOF ansible-playbook backup.yaml -i deployment_spec.yaml \ -e resource_spec=s3_secret.yamldataprecisam seraccess-key-ideaccess-key. É necessário aplicar o recursoSecretantes do recursoBackupPlan. - Crie e aplique o recurso
BackupPlan: O valorcat > backup_plan.yaml <<EOF BackupPlan: metadata: name: s3-backup-plan spec: dbclusterRef: $CLUSTER backupLocation: type: S3 s3Options: bucket: $S3_BUCKET key: /backups endpoint: https://$S3_HOST:9000 region: $S3_REGION secretRef: name: s3-backup-secret caBundle: - | $(sed 's/^/ /' /var/lib/minio/certs/public.crt) EOF ansible-playbook backup.yaml -i deployment_spec.yaml \ -e resource_spec=backup_plan.yamlkeyé o caminho dos backups no bucket. Esse caminho precisa começar com uma barra (/). O campocaBundlecontém o certificado de CA codificado em PEM que valida o certificado do servidor de armazenamento do S3. - Verifique se o plano de backup está pronto:
Verifique se o campoansible-playbook status.yaml -i deployment_spec.yaml \ -e resource_type=BackupPlan -e resource_name=s3-backup-planphasemostraReady. Se a fase não forReady, aguarde um minuto e execute o comando novamente. - Quando um plano de backup é criado, o orquestrador do RPM inicia automaticamente um backup completo inicial. Verifique se esse backup inicial foi concluído antes de criar um backup on demand:
Verifique se a fase inicial de backup foi concluída.ansible-playbook status.yaml -i deployment_spec.yaml \ -e resource_type=Backup
6. Criar um backup on demand
Nesta etapa, você vai criar um backup sob demanda do cluster.
- Na VM de controle, crie o recurso
Backup. Em seguida, aplique o recurso: O campocat > create_backup.yaml <<EOF Backup: metadata: name: s3-backup-1 spec: backupPlanRef: s3-backup-plan dbclusterRef: $CLUSTER EOF ansible-playbook backup.yaml -i deployment_spec.yaml \ -e resource_spec=create_backup.yamlbackupPlanRefé o nome do plano de backup. O campodbclusterRefé o nome do cluster. - Verifique se o backup foi concluído:
Verifique se o campoansible-playbook status.yaml -i deployment_spec.yaml \ -e resource_type=Backup -e resource_name=s3-backup-1phasemostraSucceeded. Se a fase não forSucceeded, aguarde um minuto e execute o comando novamente. - Verifique se os arquivos de backup estão no bucket:
Verifique se a saída mostra uma pastamc --insecure tree "s3repo/$S3_BUCKET"backupque contém uma pastadb.
7. Restaurar o cluster de um backup
O orquestrador de RPM restaura um cluster no local. Nesta etapa, você vai excluir uma tabela e restaurá-la do backup. Depois, é possível restaurar o cluster para um momento específico.
Atenção:uma operação de restauração substitui todos os dados do cluster de banco de dados.
Restaurar a partir de um backup
- Na VM de controle, exclua a tabela
orders. Em seguida, conte as linhas: Verifique se o segundo comando falha com um erro. A mensagem de erro mostra que a relação não existe. Por exemplo, "ERROR: table "orders" does not exist"psql -c "DROP TABLE public.orders;" psql -c "SELECT pg_catalog.count(*) FROM public.orders;" - Crie o playbook de restauração:
cat > restore.yaml <<EOF - name: Restore AlloyDB Omni cluster hosts: localhost roles: - role: google.alloydbomni_orchestrator.restore EOF - Crie um recurso
Restorepara o backups3-backup-1. Em seguida, aplique o recurso:cat > restore_backup.yaml <<EOF Restore: metadata: name: s3-restore-1 spec: sourceDBCluster: $CLUSTER backup: s3-backup-1 EOF ansible-playbook restore.yaml -i deployment_spec.yaml \ -e resource_spec=restore_backup.yaml - Verifique se a operação de restauração foi concluída:
Verifique se o campoansible-playbook status.yaml -i deployment_spec.yaml \ -e resource_type=Restore -e resource_name=s3-restore-1phasemostraProvisionSucceeded. Se a fase não forProvisionSucceeded, aguarde um minuto e execute o comando novamente. - Conte as linhas na tabela restaurada:
Verifique se a saída mostrapsql -c "SELECT pg_catalog.count(*) FROM public.orders;"1000.
(Opcional) Restaurar para um momento específico
Uma restauração pontual usa um backup e o registro prévio de escrita (WAL) arquivado. É possível restaurar o cluster para qualquer momento na janela de recuperação do plano de backup.
Regras para o tempo de destino
Você precisa seguir todas as regras para escolher o valor e o formato do tempo de destino:
- Use o formato RFC 3339 em UTC:
YYYY-MM-DDThh:mm:ssZ. Por exemplo,2026-06-19T14:30:00Zé 14:30:00 UTC em 19 de junho de 2026. A letraTsepara a data e a hora. A letraZmostra o UTC. - Use um tempo no passado.
- Use um horário depois do valor
begindo camporecoveryWindowdo CRDBackupPlan.
Para mostrar a hora atual no formato RFC 3339, execute este comando:
date -u +%Y-%m-%dT%H:%M:%SZ
Para mudar um horário local para esse formato, adicione o ajuste de UTC do horário local ao comando date. Por exemplo, o comando a seguir muda 16:30:00 em 19 June 2026 em UTC+02:00:
date -u -d "2026-06-19 16:30:00 +0200" +%Y-%m-%dT%H:%M:%SZ
O comando retorna 2026-06-19T14:30:00Z.
Restaurar para um horário gravado
Neste procedimento, você adiciona linhas à tabela e registra um horário. Ao registrar um horário, você marca o momento exato em que o banco de dados está completamente intacto (com exatamente 1.500 linhas). Em seguida,exclua as linhas e restaure o cluster para o horário registrado.
- Adicione 500 linhas à tabela:
psql <<'SQL' INSERT INTO public.orders (id, item) SELECT g, 'item-' || g FROM pg_catalog.generate_series(1001, 1500) AS g; SQL - Registre o horário. A tabela tem 1.500 linhas no momento.
Verifique se a saída mostra uma hora no formatosleep 5 PITR_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) echo "export PITR_TIME=$PITR_TIME" >> ~/.codelab.env echo "$PITR_TIME" sleep 5YYYY-MM-DDThh:mm:ssZ, por exemplo,2026-10-05T11:16:02Z. - Exclua linhas da tabela para simular uma exclusão acidental de dados. Em seguida, inicie um novo arquivo do WAL:
Verifique se a consultapsql -c "DELETE FROM public.orders WHERE id > 1000;" psql -c "SELECT pg_catalog.count(*) FROM public.orders;" psql -c "SELECT pg_catalog.pg_switch_wal();"countmostra1000. A funçãopg_switch_walfaz com que o servidor inicie um novo arquivo WAL. Em seguida, o servidor pode arquivar o arquivo WAL que contém suas mudanças. - Verifique se o período de recuperação do plano de backup contém o horário gravado:
Verifique se o valortest -n "$PITR_TIME" || { echo "PITR_TIME is not set. Run step 2 again."; exit 1; } echo "$PITR_TIME" ansible-playbook status.yaml -i deployment_spec.yaml \ -e resource_type=BackupPlan -e resource_name=s3-backup-planPITR_TIMEestá depois do valorbegindo camporecoveryWindow. - Crie um recurso
Restorepara o tempo gravado. Em seguida, aplique o recurso:cat > restore_pitr.yaml <<EOF Restore: metadata: name: s3-restore-pitr spec: sourceDBCluster: $CLUSTER pointInTime: "$PITR_TIME" EOF ansible-playbook restore.yaml -i deployment_spec.yaml \ -e resource_spec=restore_pitr.yaml - Verifique se a operação de restauração foi concluída:
Verifique se o campoansible-playbook status.yaml -i deployment_spec.yaml \ -e resource_type=Restore -e resource_name=s3-restore-pitrphasemostraProvisionSucceeded. Se a fase não forProvisionSucceeded, aguarde um minuto e execute o comando novamente. - Conte as linhas:
Verifique se a saída mostrapsql -c "SELECT pg_catalog.count(*) FROM public.orders;"1500.
8. Limpeza
Para evitar cobranças na sua conta do Google Cloud, exclua os recursos deste codelab e do codelab Implantar um cluster de alta disponibilidade do AlloyDB Omni em VMs do GCE usando o RPM Orchestrator. Primeiro, exclua os recursos de backup, depois o cluster e o ambiente de computação.
- Na VM de controle, crie o playbook de exclusão:
cat > delete.yaml <<EOF - name: Delete AlloyDB Omni resources hosts: localhost roles: - role: google.alloydbomni_orchestrator.delete EOF - Liste os backups:
Verifique se a saída mostra o backupansible-playbook status.yaml -i deployment_spec.yaml -e resource_type=Backups3-backup-1. - Exclua o backup do
s3-backup-1:ansible-playbook delete.yaml -i deployment_spec.yaml \ -e resource_type=Backup -e resource_name=s3-backup-1 - Exclua o plano de backup:
ansible-playbook delete.yaml -i deployment_spec.yaml \ -e resource_type=BackupPlan -e resource_name=s3-backup-plan - Exclua o cluster e o ambiente de computação usando a etapa Limpar recursos do codelab Implantar um cluster de alta disponibilidade do AlloyDB Omni em VMs do GCE usando o orquestrador RPM. O servidor MinIO e os backups nele estão na VM de controle. Ao excluir o ambiente de computação, você exclui o servidor e os backups.
9. Parabéns
Parabéns! Você fez backup de um cluster de alta disponibilidade (HA) para repositório de objetos compatível com S3 para o AlloyDB Omni usando o orquestrador RPM. Em seguida, você restaurou o cluster dos backups.
O que vimos
- Como instalar e executar o MinIO como repositório de objetos compatível com S3.
- Como criar um plano de backup e um backup sob demanda.
- Como restaurar um cluster de um backup e para um momento específico.
Para mais informações, consulte as seguintes páginas: