Implantar um servidor da Web recuperável com snapshots de discos permanentes

Last reviewed 2021-08-04 UTC

O documento descreve como implantar uma topologia de failover frio para um servidor da Web usando um grupo de instâncias gerenciadas e snapshots de disco permanente. Este documento é destinado a arquitetos e pessoas que trabalham em equipes operacionais e administrativas.

Você cria um grupo de instâncias gerenciadas que executa uma única VM com um disco permanente que armazena dados. Os snapshots programados do disco permanente minimizam a perda de dados em um cenário de failover. Um balanceamento de carga de aplicativo externo direciona os usuários para a VM executada no grupo gerenciado de instâncias, conforme mostrado no diagrama a seguir:

Um balanceamento de carga de aplicativo externo direciona os usuários para uma única VM que é executada em um grupo de instâncias gerenciadas, e uma política de recursos cria snapshots regulares de um disco permanente conectado à VM.

Se houver uma falha na instância, o grupo de instâncias gerenciadas tentará recriar a VM na mesma zona. Se a falha estiver no nível da zona, o Cloud Monitoring ou semelhante pode informar que há um problema e você criar manualmente outro grupo de instâncias gerenciadas em outra zona ou região. Em qualquer um dos cenários de failover, a plataforma usa o snapshot do disco permanente mais recente para criar um disco de substituição e anexá-lo à nova VM no grupo de instâncias.

Neste documento, você usa o endereço IP externo da VM ou o balanceador de carga para visualizar uma página básica no servidor da Web. Essa abordagem permite testar o padrão de failover frio se você não tiver um nome de domínio registrado e sem nenhuma alteração de DNS. Em um ambiente de produção, crie e configure uma zona e um registro do Cloud DNS que sejam resolvidos para o endereço IP externo atribuído ao balanceador de carga.

Esse padrão equilibra a diferença de custos da execução de várias VMs ou discos permanentes regionais com a manutenção de um determinado nível de proteção de dados. Os custos são menores quando você executa uma VM e um disco permanente, mas há o risco de perda de dados. Os snapshots de discos permanentes só são capturados em um intervalo definido.

Veja na tabela a seguir algumas diferenças de alto nível nas opções de proteção de dados para abordagens recuperáveis que usam discos permanentes regionais ou snapshots de discos permanentes. Para mais informações, consulte Opções de alta disponibilidade usando discos permanentes.

Discos permanentes regionais Snapshots de discos permanentes
Perda de dados: objetivo de ponto de recuperação (RPO) Zero para uma única falha, como interrupção sustentada em uma zona ou rede desconectada. Qualquer dado desde o último snapshot foi tirado, que normalmente é de uma hora ou mais.

A possível perda de dados depende da programação de snapshot que controla a frequência com que os snapshots são tirados.
Objetivo de tempo de recuperação (RTO). Tempo de implantação de uma nova VM, além de vários segundos para que o disco permanente regional seja reanexado. O tempo de implantação de uma nova VM e o tempo para criar um novo disco permanente a partir do snapshot mais recente.

O tempo de criação do disco depende do tamanho dele e pode levar dezenas de minutos ou horas.
Custo O custo de armazenamento é o dobro, já que o disco permanente regional é replicado continuamente para outra zona. Você paga apenas pela quantidade de espaço de snapshot consumido.
Para mais informações, consulte Preços de discos e imagens.

Objetivos

  • Crie um grupo de instâncias gerenciadas para executar uma VM com um disco permanente.
  • Configure uma programação de snapshot para tirar snapshots regulares do disco permanente.
  • Crie um modelo de instância e um script de inicialização.
  • Criar e configurar um balanceador de carga de aplicativo externo.
  • Teste o failover do servidor da Web frio com um grupo de instâncias gerenciadas de substituição.

Custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Antes de começar

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Compute Engine API.

    Enable the API

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. Make sure that billing is enabled for your Google Cloud project.

  9. Enable the Compute Engine API.

    Enable the API

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init
  12. É possível executar a Google Cloud CLI no console do Google Cloud sem instalá-la. Para executar a gcloud CLI no console do Google Cloud, use o Cloud Shell.

prepare o ambiente

Nesta seção, você define algumas variáveis para os locais e nomes de recursos. Essas variáveis são usadas pelos comandos da Google Cloud CLI à medida que você implanta os recursos.

Neste documento, salvo indicação em contrário, você insere todos os comandos no Cloud Shell ou no ambiente de desenvolvimento local.

  1. Substitua PROJECT_ID pelo seu código do projeto: Se necessário, forneça seu próprio sufixo de nome para recursos, como app.

    Especifique uma região, como us-central1, e duas zonas nessa região, como us-central1-a e us-central1-f. Essas zonas definem onde o disco permanente inicial e o grupo de instâncias gerenciadas são implantados e onde é possível fazer failover manualmente, se necessário.

    PROJECT_ID=PROJECT_ID
    NAME_SUFFIX=app
    REGION=us-central1
    ZONE1=us-central1-a
    ZONE2=us-central1-f
    

Criar uma VPC e uma sub-rede

Para fornecer acesso à rede às VMs, crie uma nuvem privada virtual (VPC, na sigla em inglês) e uma sub-rede. Como o grupo de instâncias gerenciadas funciona entre zonas dentro de uma única região, somente uma sub-rede é criada. Para mais informações sobre as vantagens do modo de sub-rede personalizada para gerenciar intervalos de endereços IP em uso no ambiente, consulte Usar redes VPC de modo personalizado.

  1. Crie a VPC com um modo de sub-rede personalizado:

    gcloud compute networks create network-$NAME_SUFFIX \
        --subnet-mode=custom
    

    Se você vir um prompt do Cloud Shell, autorize essa primeira solicitação para fazer chamadas de API.

  2. Crie uma sub-rede na nova VPC. Defina seu próprio intervalo de endereços, como 10.1.0.0/20, que caiba no intervalo da rede:

    gcloud compute networks subnets create subnet-$NAME_SUFFIX-$REGION \
        --network=network-$NAME_SUFFIX \
        --range=10.1.0.0/20 \
        --region=$REGION
    

Crie regras de firewall

  1. Crie regras de firewall para permitir tráfego da Web e verificações de integridade para o balanceador de carga e os grupos gerenciados de instâncias:

    gcloud compute firewall-rules create allow-http-$NAME_SUFFIX \
        --network=network-$NAME_SUFFIX \
        --direction=INGRESS \
        --priority=1000 \
        --action=ALLOW \
        --rules=tcp:80 \
        --source-ranges=0.0.0.0/0 \
        --target-tags=http-server
    
    gcloud compute firewall-rules create allow-health-check-$NAME_SUFFIX \
        --network=network-$NAME_SUFFIX \
        --action=allow \
        --direction=ingress \
        --source-ranges=130.211.0.0/22,35.191.0.0/16 \
        --target-tags=allow-health-check \
        --rules=tcp:80
    

    A regra HTTP permite o tráfego para qualquer VM em que a tag http-server seja aplicada e de qualquer origem usando o intervalo 0.0.0.0/0. Para a regra da verificação de integridade, os intervalos padrão do Google Cloud estão configurados para permitir que a plataforma verifique corretamente a integridade dos recursos.

  2. Para permitir o tráfego SSH para a configuração inicial de uma imagem de VM de base, defina o escopo da regra de firewall para o ambiente usando o parâmetro --source-range. Talvez seja necessário trabalhar com a equipe de rede para determinar quais intervalos de origem sua organização usa.

    Substitua IP_ADDRESS_SCOPE pelos seus próprios escopos de endereços IP:

    gcloud compute firewall-rules create allow-ssh-$NAME_SUFFIX \
        --network=network-$NAME_SUFFIX \
        --direction=INGRESS \
        --priority=1000 \
        --action=ALLOW \
        --rules=tcp:22 \
        --source-ranges=IP_ADDRESS_SCOPE
    
  3. Depois de criar as regras de firewall, verifique se as três regras foram adicionadas:

    gcloud compute firewall-rules list \
        --project=$PROJECT_ID \
        --filter="NETWORK=network-$NAME_SUFFIX"
    

    O exemplo de saída a seguir mostra que as três regras foram criadas corretamente:

    NAME                    NETWORK      DIRECTION  PRIORITY  ALLOW
    allow-health-check-app  network-app  INGRESS    1000      tcp:80
    allow-http-app          network-app  INGRESS    1000      tcp:80
    allow-ssh-app           network-app  INGRESS    1000      tcp:22
    

Criar e configurar uma imagem de VM base

Para criar VMs idênticas que podem ser implantadas sem outras configurações, use uma imagem de VM personalizada. Essa imagem captura a configuração do SO e do Apache e é usada para criar cada VM no grupo gerenciado de instâncias nas próximas etapas.

Você usa um disco permanente para armazenar os dados do aplicativo. Neste documento, você usa um site Apache básico para exibir o aplicativo. Posteriormente neste documento, você criará uma programação de snapshot anexada a esse disco permanente para criar snapshots de discos automatizados.

Na VM, crie um arquivo index.html básico no disco permanente e monte-o em /var/www/example.com. Um arquivo de configuração do Apache em /etc/apache2/sites-available/example.com.conf disponibiliza conteúdo da Web a partir do local do disco permanente ativado.

No diagrama a seguir, veja a página HTML básica exibida pelo Apache que está armazenada no disco permanente.

A VM tem uma página HTML básica armazenada no disco permanente com um arquivo de configuração do Apache para carregar a partir do local do disco ativado.

Crie esse ambiente nas etapas a seguir.

  1. Crie um SSD de 10 GiB. Entenda suas necessidades de armazenamento e os custos associados ao pagamento pelo espaço provisionado, não pelo consumido. Para mais informações, consulte preços do disco permanente.

    gcloud compute disks create disk-$NAME_SUFFIX \
        --zone $ZONE1 \
        --size=10 \
        --type=pd-ssd
    
  2. Crie uma VM base com um disco permanente anexado:

    gcloud compute instances create vm-base-$NAME_SUFFIX \
        --zone=$ZONE1 \
        --machine-type=n1-standard-1 \
        --subnet=subnet-$NAME_SUFFIX-$REGION \
        --tags=http-server \
        --image=debian-10-buster-v20210721 \
        --image-project=debian-cloud \
        --boot-disk-size=10GB \
        --boot-disk-type=pd-balanced \
        --boot-disk-device-name=vm-base-$NAME_SUFFIX \
        --disk=mode=rw,name=disk-$NAME_SUFFIX,device-name=disk-$NAME_SUFFIX
    

    Use os parâmetros definidos no início deste documento para nomear a VM e se conectar à sub-rede correta. Os nomes também são atribuídos pelos parâmetros dos discos de inicialização e de dados.

  3. Para instalar e configurar o site simples, primeiro conecte-se à VM base usando o SSH.

    gcloud compute ssh vm-base-$NAME_SUFFIX --zone=$ZONE1
    
  4. Na sessão SSH para a VM, crie um script para configurar a VM em um editor de sua escolha. O exemplo a seguir usa Nano (em inglês) como o editor:

    nano configure-vm.sh
    

    Cole o script de configuração a seguir no arquivo. Atualize a variável NAME_SUFFIX para corresponder ao valor definido no início deste documento, como app:

    #!/bin/bash
    
    NAME_SUFFIX=app
    
    # Create directory for the basic website files
    sudo mkdir -p /var/www/example.com
    sudo chmod a+w /var/www/example.com
    sudo chown -R www-data: /var/www/example.com
    
    # Find the disk name, then format and mount it
    DISK_NAME="google-disk-$NAME_SUFFIX"
    DISK_PATH="$(find /dev/disk/by-id -name "${DISK_NAME}" | xargs -I '{}' readlink -f '{}')"
    
    sudo mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard $DISK_PATH
    sudo mount -o discard,defaults $DISK_PATH /var/www/example.com
    
    # Install Apache, additional utilities, and cloud-init
    sudo apt-get update && sudo apt-get -y install apache2 moreutils cloud-init
    
    # Write out a basic HTML file to the mounted persistent disk
    sudo tee -a /var/www/example.com/index.html >/dev/null <<'EOF'
    <!doctype html>
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a test web server with persistent disk snapshots!</p>
    </body>
    </html>
    EOF
    
    # Write out an Apache configuration file
    sudo tee -a /etc/apache2/sites-available/example.com.conf >/dev/null <<'EOF'
    <VirtualHost *:80>
            ServerName www.example.com
    
            ServerAdmin webmaster@localhost
            DocumentRoot /var/www/example.com
    
            ErrorLog ${APACHE_LOG_DIR}/error.log
            CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    EOF
    
    # Enable the Apache configuration file and reload service
    sudo a2dissite 000-default
    sudo a2ensite example.com.conf
    sudo systemctl reload apache2
    
  5. Grave o arquivo e saia do editor. Por exemplo, no Nano, use Ctrl-O para gravar o arquivo e saia com Ctrl-X.

  6. Torne o script de configuração executável e execute-o:

    chmod +x configure-vm.sh
    ./configure-vm.sh
    
  7. Se houver uma falha na instância e o grupo de instâncias gerenciadas precisar criar uma substituição a partir dessa VM base, os dados do aplicativo precisarão estar disponíveis. As etapas a seguir serão executadas automaticamente em cada nova VM:

    • Receber algumas informações do servidor de metadados
    • Acessar o snapshot mais recente do disco permanente
    • Criar um disco a partir deste snapshot mais recente
    • Anexar o disco novo à VM
    • Ativar o disco na VM

    Crie um script de inicialização chamado app-startup.sh que execute essas etapas necessárias para a VM. Esse script de inicialização é aplicado a um modelo de instância em uma etapa seguinte.

    sudo mkdir /opt/cloud-init-scripts
    
    sudo tee -a /opt/cloud-init-scripts/app-startup.sh >/dev/null <<'EOF'
    #!/bin/bash
    
    # Install jq and get an access token for API requests
    apt-get install -y jq
    OAUTH_TOKEN=$(curl "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
        -H "Metadata-Flavor: Google" --silent | jq -r '.access_token')
    
    # Make a request against the metadata server to determine the project name,
    # instance name, and what zone it's running in
    ZONE_INFO=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone \
        -H "Metadata-Flavor: Google" --silent)
    PROJECT_NAME=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone \
        -H "Metadata-Flavor: Google" --silent | awk -v FS="/" '{print $2}')
    ZONE_NAME=$(curl http://metadata.google.internal/computeMetadata/v1/instance/zone \
        -H "Metadata-Flavor: Google" --silent | sed 's:.*/::')
    INSTANCE_NAME=$(curl http://metadata.google.internal/computeMetadata/v1/instance/name \
        -H "Metadata-Flavor: Google" --silent)
    
    # Get the latest snapshot of the app disk
    LATEST_SNAPSHOT=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
        https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/global/snapshots \
        --silent | jq -s '.[].items[] | select(.name | contains("disk-$NAME")) | .name' \
        | sort -r | head -n 1 | tr -d '"')
    
    # Create a persistent disk using the latest persistent disk snapshot
    curl -X POST -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json; charset=utf-8" \
        https://compute.googleapis.com/compute/v1/$ZONE_INFO/disks \
        --data '{"name":"'$LATEST_SNAPSHOT'-restored","sizeGb":"10","type":"zones/'$ZONE_NAME'/diskTypes/pd-ssd","sourceSnapshot":"https://www.googleapis.com/compute/v1/projects/'$PROJECT_NAME'/global/snapshots/'$LATEST_SNAPSHOT'"}'
    
    # Wait for the persistent disk to be created from the disk snapshot
    DISK_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
        https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/disks/$LATEST_SNAPSHOT-restored \
        --silent | jq -r .status)
    
    while [ $DISK_STATUS != "READY" ]
    do
        sleep 2
        DISK_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
            https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/disks/$LATEST_SNAPSHOT-restored \
            --silent | jq -r .status)
    done
    
    # Attach the new persistent disk created from the snapshot to the VM
    curl -X POST -H "Authorization: Bearer $OAUTH_TOKEN" -H "Content-Type: application/json; charset=utf-8" \
        https://compute.googleapis.com/compute/v1/$ZONE_INFO/instances/$INSTANCE_NAME/attachDisk \
        --data '{ "source": "/compute/v1/'$ZONE_INFO'/disks/'$LATEST_SNAPSHOT'-restored"}'
    
    # Wait for the persistent disk to be attached before mounting
    ATTACH_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" \
        https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/instances/$INSTANCE_NAME \
        --silent | jq '.disks[] | select(.source | contains("disk-"))')
    
    while [ -z "$ATTACH_STATUS" ]
    do
        sleep 2
        ATTACH_STATUS=$(curl -X GET -H "Authorization: Bearer $OAUTH_TOKEN" GET \
            https://compute.googleapis.com/compute/v1/projects/$PROJECT_NAME/zones/$ZONE_NAME/instances/$INSTANCE_NAME \
            --silent | jq '.disks[] | select(.source | contains("disk-"))')
    done
    
    # With the disk attached, mount the disk and restart Apache
    echo UUID=`blkid -s UUID -o value /dev/sdb` /var/www/example.com ext4 discard,defaults,nofail 0 2 \
        | tee -a /etc/fstab
    mount -a
    systemctl reload apache2
    
    # Remove jq so it's not left on the VM
    apt-get remove -y jq
    EOF
    
  8. Para aplicar a variável NAME_SUFFIX definida no início do documento no script de inicialização, como app, use o comando envsubst:

    export NAME=app
    envsubst '$NAME' < "/opt/cloud-init-scripts/app-startup.sh" \
        | sudo sponge "/opt/cloud-init-scripts/app-startup.sh"
    
  9. Saia da sessão SSH da VM.

    exit
    
  10. Consiga o endereço IP da VM e use curl para ver a página da Web básica:

    curl $(gcloud compute instances describe vm-base-$NAME_SUFFIX \
        --zone $ZONE1 \
        --format="value(networkInterfaces.accessConfigs.[0].natIP)")
    

    O site básico é retornado, conforme mostrado no seguinte exemplo de saída:

    <!doctype html>
    
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a test web server with persistent disk snapshots!</p>
    </body>
    </html>
    

    Esta etapa confirma que o Apache está configurado corretamente e a página está carregada do disco permanente anexado. Nas próximas etapas, você criará uma imagem usando essa VM base e configurará um modelo de instância com um script de inicialização.

Criar uma programação de snapshot de disco permanente

Para garantir que as VMs criadas no grupo gerenciado de instâncias sempre tenham os dados mais recentes do disco permanente, crie uma programação de snapshot. Essa programação tira snapshots automáticos de um disco permanente em horários definidos e controla por quanto tempo eles serão mantidos. A imagem a seguir mostra como esse processo de snapshot funciona:

É criada uma política de recursos que define uma programação de snapshot e é anexada ao disco permanente para criar snapshots regulares.

Pense nas necessidades do seu aplicativo e nas metas comerciais com que frequência você deve tirar instantâneos. Por exemplo, um site estático precisa de instantâneos menos frequentes do que um aplicativo ativo que grava dados no disco.

Para mais informações sobre como determinar a melhor abordagem para os aplicativos e qual método de recuperação usar, consulte o guia de planejamento de recuperação de desastres.

  1. Neste cenário, use uma programação de snapshot para criar snapshots de disco permanente regulares. Essa programação de snapshot é definida em uma política de recursos. Com as políticas de recursos, é possível definir ações para executar e anexá-las aos recursos no ambiente.

    Nesta política de recursos, você define uma programação para criar um snapshot com as seguintes configurações:

    • Tirar um snapshot a cada quatro horas, a partir das 22h UTC.
    • Reter snapshots por um dia.

    Configure essa programação conforme necessário para seu ambiente, como o horário de início e a frequência com que quer tirar os snapshots:

    gcloud compute resource-policies create snapshot-schedule snapshot-schedule-$NAME_SUFFIX \
        --description "Snapshot persistent disk every 4 hours" \
        --max-retention-days 1 \
        --start-time 22:00 \
        --hourly-schedule 4 \
        --region $REGION
    

    Para mais informações, veja como usar snapshots programados para discos permanentes.

  2. Para usar a programação de snapshot, anexe a política de recursos ao disco permanente. Especifique o nome do disco permanente e a política de recursos criada na etapa anterior:

    gcloud compute disks add-resource-policies disk-$NAME_SUFFIX \
        --resource-policies snapshot-schedule-$NAME_SUFFIX \
        --zone $ZONE1
    
  3. Não é possível concluir o restante deste documento e ver o grupo gerenciado de instâncias em ação até que o primeiro snapshot do disco seja criado. Crie um snapshot do disco manualmente e permita que o snapshot da política do recurso crie outros snapshots, conforme definido:

    gcloud compute disks snapshot disk-$NAME_SUFFIX \
        --zone=$ZONE1 \
        --snapshot-names=disk-$NAME_SUFFIX-$(date "+%Y%m%d%H%M%S")
    

Criar uma conta de serviço

Cada VM no grupo gerenciado de instâncias criado nas próximas etapas precisa executar um script de inicialização. Esse script de inicialização cria um disco permanente a partir de um snapshot e o anexa à VM. Como prática recomendada de segurança, crie uma nova conta de serviço apenas com as permissões necessárias para realizar essas operações de disco. Em seguida, atribua essa conta de serviço à VM.

  1. Crie uma conta de serviço para usar com as VMs no grupo gerenciado de instâncias:

    gcloud iam service-accounts create instance-sa-$NAME_SUFFIX \
        --description="Service account for HA/DR example" \
        --display-name="HA/DR for VM instances"
    
  2. Crie um papel personalizado e atribua apenas as permissões necessárias para realizar as tarefas de gerenciamento de disco. As seguintes permissões são necessárias:

    • compute.snapshots.list
    • compute.snapshots.useReadOnly
    • compute.disks.get
    • compute.disks.create
    • compute.instances.get
    • compute.instances.attachDisk
    • compute.disks.use
    gcloud iam roles create instance_snapshot_management_$NAME_SUFFIX \
        --project=$PROJECT_ID \
        --title="Snapshot management for VM instances" \
        --description="Custom role to allow an instance to create a persistent disk from a snapshot and attach to VM." \
        --permissions=compute.snapshots.list,compute.snapshots.useReadOnly,compute.disks.get,compute.disks.create,compute.instances.get,compute.instances.attachDisk,compute.disks.use \
        --stage=GA
    
  3. Adicione as vinculações de papéis necessárias para a nova conta de serviço:

    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com" \
        --role="projects/$PROJECT_ID/roles/instance_snapshot_management_$NAME_SUFFIX"
    
    gcloud projects add-iam-policy-binding $PROJECT_ID \
        --member="serviceAccount:instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com" \
        --role="roles/iam.serviceAccountUser"
    

Crie uma imagem de VM e um modelo de instância

Para criar VMs idênticas que podem ser implantadas automaticamente sem configuração adicional, use uma imagem de VM personalizada. Essa imagem captura a configuração do SO e do Apache. Cada VM criada no grupo de instâncias gerenciadas nas próximas etapas usa essa imagem.

  1. Antes de criar uma imagem, é necessário parar a VM:

    gcloud compute instances stop vm-base-$NAME_SUFFIX --zone=$ZONE1
    
  2. Crie uma imagem da VM base configurada na seção anterior:

    gcloud compute images create image-$NAME_SUFFIX \
        --source-disk=vm-base-$NAME_SUFFIX \
        --source-disk-zone=$ZONE1 \
        --storage-location=$REGION
    
  3. Use cloud-init para executar o script de inicialização anterior na primeira vez que uma VM nos grupos de instâncias gerenciadas for inicializada. Um script de inicialização regular aplicado à VM é executado sempre que ela é inicializada, por exemplo, quando a VM é reinicializada após as atualizações.

    Crie um arquivo de configuração cloud-init para usar com o modelo de instância:

    tee -a cloud-init.yaml >/dev/null <<'EOF'
    #cloud-config
    
    runcmd:
     - [ bash, /opt/cloud-init-scripts/app-startup.sh ]
    EOF
    
  4. Crie um modelo de instância que aplique a configuração cloud-init para executar o script de inicialização que cria um disco a partir do snapshot, depois anexa e monta o disco na VM:

    gcloud compute instance-templates create template-$NAME_SUFFIX \
        --machine-type=n1-standard-1 \
        --subnet=projects/$PROJECT_ID/regions/$REGION/subnetworks/subnet-$NAME_SUFFIX-$REGION \
        --tags=http-server \
        --image=image-$NAME_SUFFIX \
        --scopes cloud-platform \
        --service-account="instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com" \
        --metadata-from-file user-data=cloud-init.yaml
    

Criar um grupo de instâncias gerenciadas

Um grupo de instâncias gerenciadas executa as VMs. O grupo de instâncias gerenciadas é executado em uma zona definida e monitora a integridade das VMs. Se houver uma falha e a VM parar de ser executada, o grupo de instâncias gerenciadas tentará recriar outra VM na mesma zona e criará um disco permanente a partir do snapshot mais recente. Se a falha estiver no nível da zona, será necessário executar manualmente o failover frio e criar outro grupo de instâncias gerenciadas em uma zona diferente. A mesma imagem personalizada e o mesmo modelo de instância configuram a VM automaticamente de maneira idêntica.

  1. Crie uma verificação de integridade para monitorar as VMs no grupo gerenciado de instâncias. Essa verificação de integridade garante que a VM responda na porta 80. Para seus próprios aplicativos, monitore as portas apropriadas para verificar a integridade da VM.

    gcloud compute health-checks create http http-basic-check-$NAME_SUFFIX --port 80
    
  2. Crie um grupo de instâncias gerenciadas com apenas uma VM. Essa VM única inicializa e cria um disco permanente a partir do snapshot mais recente, depois o ativa e começa a exibir tráfego da Web.

    gcloud compute instance-groups managed create instance-group-$NAME_SUFFIX-$ZONE1 \
        --base-instance-name=instance-vm-$NAME_SUFFIX \
        --template=template-$NAME_SUFFIX \
        --size=1 \
        --zone=$ZONE1 \
        --health-check=http-basic-check-$NAME_SUFFIX
    

Criar e configurar um balanceador de carga

Para que os usuários acessem um site, é necessário permitir o tráfego até as VMs executadas no grupo gerenciado de instâncias. Também é necessário redirecionar automaticamente o tráfego para novas VMs se houver uma falha de zona em um grupo gerenciado de instâncias.

Na seção a seguir, você cria um balanceador de carga externo com um serviço de back-end para tráfego HTTP na porta 80, usa a verificação de integridade criada nas etapas anteriores e mapeia um endereço IP até serviço de back-end.

Para mais informações, consulte Como configurar um balanceador de carga HTTP externo simples.

  1. Crie e configure o balanceador de carga para o aplicativo:

    # Configure port rules for HTTP port 80
    gcloud compute instance-groups set-named-ports \
        instance-group-$NAME_SUFFIX-$ZONE1 \
        --named-ports http:80 \
        --zone $ZONE1
    
    # Create a backend service and add the managed instance group to it
    gcloud compute backend-services create \
        web-backend-service-$NAME_SUFFIX \
        --protocol=HTTP \
        --port-name=http \
        --health-checks=http-basic-check-$NAME_SUFFIX \
        --global
    
    gcloud compute backend-services add-backend \
        web-backend-service-$NAME_SUFFIX \
        --instance-group=instance-group-$NAME_SUFFIX-$ZONE1 \
        --instance-group-zone=$ZONE1 \
        --global
    
    # Create a URL map for the backend service
    gcloud compute url-maps create web-map-http-$NAME_SUFFIX \
        --default-service web-backend-service-$NAME_SUFFIX
    
    # Configure forwarding for the HTTP traffic
    gcloud compute target-http-proxies create \
        http-lb-proxy-$NAME_SUFFIX \
        --url-map web-map-http-$NAME_SUFFIX
    
    gcloud compute forwarding-rules create \
        http-content-rule-$NAME_SUFFIX \
        --global \
        --target-http-proxy=http-lb-proxy-$NAME_SUFFIX \
        --ports=80
    
  2. Consiga o endereço IP da regra de encaminhamento do tráfego da Web:

    IP_ADDRESS=$(gcloud compute forwarding-rules describe http-content-rule-$NAME_SUFFIX \
        --global \
        --format="value(IPAddress)")
    
  3. Use curl ou abra o navegador da Web para ver o site usando o endereço IP do balanceador de carga da etapa anterior:

    curl $IP_ADDRESS
    

    O balanceador de carga leva alguns minutos para concluir a implantação e direcionar o tráfego corretamente para o back-end. Um erro HTTP 404 ou 502 será retornado se o balanceador de carga ainda estiver sendo implantado. Se necessário, aguarde alguns minutos e tente acessar o site novamente.

    O site básico é retornado, conforme mostrado no seguinte exemplo de saída:

    <!doctype html>
    
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a Compute Engine website with warm failover to Cloud Storage!</p>
    </body>
    </html>
    

Simular uma falha e recuperação de zona

Analise as implantações de recursos antes de simular uma falha no nível da zona. Todos os recursos foram criados para aceitar o seguinte ambiente:

Um balanceamento de carga de aplicativo externo direciona os usuários para uma única VM que é executada em um grupo de instâncias gerenciadas, e uma política de recursos cria snapshots regulares de um disco permanente conectado à VM.

  • Uma VM é executada em um grupo de instâncias gerenciadas com um disco permanente anexado que armazena um site básico.
  • Os snapshots são tirados regularmente do disco permanente com o uso de uma programação de snapshot de política de recursos.
  • Um script de inicialização é aplicado a um modelo de instância para que qualquer VM criada no grupo gerenciado de instâncias crie um disco permanente a partir do último snapshot do disco e o anexe.
  • Uma verificação de integridade monitora o status das VMs dentro do grupo gerenciado de instâncias.
  • O balanceador de carga de aplicativo externo direciona os usuários para a VM que é executada no grupo de instâncias gerenciadas.
  • Se a VM falhar, o grupo de instâncias gerenciadas tentará recriar uma na mesma zona. Se a falha estiver no nível da zona, você precisará criar manualmente um grupo de instâncias gerenciadas substituto em outra zona de trabalho.

Em um ambiente de produção, é possível receber um alerta usando o Cloud Monitoring ou outra solução de monitoramento quando houver um problema. Esse alerta solicita que um humano entenda o escopo da falha antes de criar manualmente um grupo de instâncias gerenciadas de substituição em outra zona de trabalho. Uma abordagem alternativa é usar sua solução de monitoramento para responder automaticamente a interrupções com o grupo gerenciado de instâncias.

Quando você ou sua solução de monitoramento determinarem a ação mais apropriada é fazer o failover, crie um grupo de instâncias gerenciadas de substituição. Neste documento, você cria manualmente esse recurso de substituição.

  1. Para simular uma falha no nível da zona, exclua o back-end do balanceador de carga e o grupo de instâncias gerenciadas:

    gcloud compute backend-services remove-backend \
        web-backend-service-$NAME_SUFFIX \
        --instance-group=instance-group-$NAME_SUFFIX-$ZONE1 \
        --instance-group-zone=$ZONE1 \
        --global
    
    gcloud compute instance-groups managed delete instance-group-$NAME_SUFFIX-$ZONE1 \
          --zone=$ZONE1
    

    Quando solicitado, confirme a solicitação para excluir o grupo de instâncias gerenciadas.

    Em um ambiente de produção, seu sistema de monitoramento gera um alerta para solicitar ações de failover a frio.

  2. Use curl ou seu navegador da Web novamente para acessar o endereço IP do balanceador de carga:

    curl $IP_ADDRESS --max-time 5
    

    A solicitação curl falha porque não há destinos íntegros para o balanceador de carga.

  3. Para simular o failover frio, crie um grupo de instâncias gerenciadas em uma zona diferente:

    gcloud compute instance-groups managed create instance-group-$NAME_SUFFIX-$ZONE2 \
        --template=template-$NAME_SUFFIX \
        --size=1 \
        --zone=$ZONE2 \
        --health-check=http-basic-check-$NAME_SUFFIX
    

    A imagem da VM, o modelo da instância e o disco permanente mantêm toda a configuração da instância do aplicativo.

  4. Atualize o balanceador de carga para adicionar o novo grupo de instâncias gerenciadas e a nova VM:

    gcloud compute instance-groups set-named-ports \
        instance-group-$NAME_SUFFIX-$ZONE2 \
        --named-ports http:80 \
        --zone $ZONE2
    
    gcloud compute backend-services add-backend \
        web-backend-service-$NAME_SUFFIX \
        --instance-group=instance-group-$NAME_SUFFIX-$ZONE2 \
        --instance-group-zone=$ZONE2 \
        --global
    
  5. Use curl ou o navegador da Web mais uma vez para acessar o endereço IP do balanceador de carga que direciona o tráfego para a VM executada no grupo de instâncias gerenciadas:

    curl $IP_ADDRESS
    

    Demora alguns minutos para a VM concluir a implantação e a restauração de dados do snapshot do disco permanente mais recente. Se a VM ainda estiver sendo implantada, um erro HTTP 404 ou 502 será retornado, e o Apache padrão será exibido se ainda estiver restaurando dados. Se necessário, aguarde alguns minutos e tente acessar o site novamente.

    Na resposta de exemplo a seguir, a página da Web é executada corretamente na VM:

    <!doctype html>
    <html lang=en>
    <head>
    <meta charset=utf-8>
        <title>HA / DR example</title>
    </head>
    <body>
        <p>Welcome to a test web server with persistent disk snapshots!</p>
    </body>
    </html>
    
  6. Verifique o status de integridade do grupo gerenciado de instâncias:

    gcloud compute instance-groups managed list-instances instance-group-$NAME_SUFFIX-$ZONE2 \
        --zone $ZONE2
    

    O resultado de exemplo a seguir mostra o status da VM como RUNNING e HEALTHY:

    NAME             ZONE           STATUS   HEALTH_STATE  ACTION
    instance-vm-app  us-central1-f  RUNNING  HEALTHY       NONE
    
  7. Para verificar se o disco permanente anexado foi criado a partir de um snapshot, veja a origem. Especifique a instância NAME exibida no comando list-instances anterior.

    gcloud compute instances describe NAME \
        --zone=$ZONE2 \
        --format="value(disks.[1].source)"
    

    A saída de exemplo a seguir mostra que o disco permanente é denominado disk-app-us-central1-a-20210630165529-umopkt17-restored. O sufixo -restored é adicionado pelo script de inicialização ao nome do snapshot de disco mais recente:

    https://www.googleapis.com/compute/v1/projects/project/zones/us-central1-f/disks/disk-app-us-central1-a-20210630165529-umopkt17-restored
    

Limpeza

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

Para excluir os recursos individuais criados neste documento, conclua as etapas a seguir.

  1. Exclua a configuração do balanceador de carga:

    gcloud compute forwarding-rules delete \
        http-content-rule-$NAME_SUFFIX --global --quiet
    
    gcloud compute target-http-proxies delete \
        http-lb-proxy-$NAME_SUFFIX --quiet
    
    gcloud compute url-maps delete web-map-http-$NAME_SUFFIX --quiet
    
    gcloud compute backend-services delete \
        web-backend-service-$NAME_SUFFIX --global --quiet
    
  2. Exclua o grupo gerenciado de instâncias e a verificação de integridade:

    gcloud compute instance-groups managed delete instance-group-$NAME_SUFFIX-$ZONE2 \
        --zone=$ZONE2 --quiet
    
    gcloud compute health-checks delete http-basic-check-$NAME_SUFFIX --quiet
    
  3. Exclua o modelo de instância, a configuração do cloud-init, as imagens, a VM base, o disco permanente e a programação de snapshot.

    gcloud compute instance-templates delete template-$NAME_SUFFIX --quiet
    
    rm cloud-init.yaml
    
    gcloud compute images delete image-$NAME_SUFFIX --quiet
    
    gcloud compute instances delete vm-base-$NAME_SUFFIX --zone=$ZONE1 --quiet
    
    gcloud compute disks delete disk-$NAME_SUFFIX --zone=$ZONE1 --quiet
    
    gcloud compute resource-policies delete \
        snapshot-schedule-$NAME_SUFFIX --region $REGION --quiet
    
  4. Liste e exclua os snapshots e discos criados pelas instâncias:

    gcloud compute disks list --filter="name:disk-$NAME_SUFFIX" \
        --uri | xargs gcloud compute disks delete
    
    gcloud compute snapshots list --filter="name:disk-$NAME_SUFFIX" \
        --uri | xargs gcloud compute snapshots delete
    
  5. Exclua o papel personalizado e a conta de serviço:

    gcloud iam roles delete instance_snapshot_management_$NAME_SUFFIX \
      --project=$PROJECT_ID --quiet
    
    gcloud iam service-accounts delete \
        instance-sa-$NAME_SUFFIX@$PROJECT_ID.iam.gserviceaccount.com --quiet
    
  6. Exclua as regras de firewall:

    gcloud compute firewall-rules delete allow-health-check-$NAME_SUFFIX --quiet
    
    gcloud compute firewall-rules delete allow-ssh-$NAME_SUFFIX --quiet
    
    gcloud compute firewall-rules delete allow-http-$NAME_SUFFIX --quiet
    
  7. Exclua a sub-rede e a VPC:

    gcloud compute networks subnets delete \
        subnet-$NAME_SUFFIX-$REGION --region=$REGION --quiet
    
    gcloud compute networks delete network-$NAME_SUFFIX --quiet
    

A seguir