Como implantar um cluster MySQL 5.6 altamente disponível com DRBD no Compute Engine

Last reviewed 2019-05-10 UTC

Este tutorial explica o processo de implantação de um banco de dados MySQL 5.6 no Google Cloud usando o Dispositivo de Bloqueio Replicado Distribuído (DRBD, na sigla em inglês) e o Compute Engine. O DRBD é um sistema de armazenamento replicado distribuído para a plataforma Linux.

Este tutorial é útil para administradores de sistema, desenvolvedores, engenheiros, administradores de banco de dados ou engenheiros de DevOps. Há vários motivos para você preferir gerenciar sua própria instância do MySQL em vez de usar o serviço gerenciado. Entre eles estão:

  • você está usando instâncias entre regiões do MySQL;
  • você precisa definir parâmetros que não estão disponíveis na versão gerenciada do MySQL;
  • você quer otimizar o desempenho de maneiras que não podem ser definidas na versão gerenciada.

A replicação no nível do bloqueio do dispositivo é possível com DRBD. Isso elimina a necessidade de configurar a replicação no próprio MySQL e você tem acesso a benefícios imediatos do DRBD como, por exemplo, suporte para leitura do balanceamento de carga e conexões seguras.

Neste tutorial, são usados os seguintes recursos:

Não é necessário conhecimento avançado para usar esses recursos, embora este documento faça referência a recursos avançados como geração de cluster no MySQL, configuração de DRBD e gerenciamento de recursos do Linux.

Arquitetura

O Pacemaker é um gerenciador de recursos de clusters. O Corosync é um pacote de comunicação e participação de clusters usado pelo Pacemaker. Neste tutorial, o DRBD será usado para replicar o disco MySQL da instância principal para a instância de espera. Um balanceador de carga interno também é implantado para que os clientes se conectem ao cluster MySQL.

Implante um cluster gerenciado pelo Pacemaker de três instâncias de computação. Instale o MySQL em duas dessas instâncias que servem como instâncias principais e como instâncias de espera. A terceira instância serve como um dispositivo de quórum.

Em um cluster, cada um dos nós vota no que deve ser o nó ativo, ou seja, o que executa o MySQL. Em um cluster de dois nós, é necessário apenas um voto para determinar o nó ativo. Nesse caso, o comportamento do cluster pode levar a problemas de divisão cerebral ou inatividade. Problemas do cérebro dividido ocorrem quando os dois nós assumem o controle, porque é necessário apenas um voto quando há dois nós. A inatividade ocorre quando o nó que é encerrado é aquele configurado para ser sempre o nó principal em caso de perda de conectividade. Se os dois nós perderem a conectividade entre si, há o risco de que mais de um nó de cluster assuma ser o nó ativo.

Adicionar um dispositivo de quórum evita que isso aconteça. Um dispositivo de quórum serve como um árbitro com a única função de votar. Assim, em uma situação em que as instâncias database1 e database2 não são capazes de se comunicar, o nó do dispositivo de quórum pode se comunicar com uma das duas instâncias e a maioria ainda pode ser alcançada.

O diagrama a seguir mostra a arquitetura do sistema descrito aqui.

Arquitetura mostrando um banco de dados MySQL 5.6 implantado no Google Cloud usando DRBD e Compute Engine

Objetivos

  • Criar as instâncias do cluster.
  • Instalar o MySQL e o DRBD em duas das instâncias.
  • Configurar a replicação de DRBD.
  • Instalar o Pacemaker nas instâncias.
  • Configurar o agrupamento em cluster do Pacemaker nas instâncias.
  • Criar uma instância e configurá-la como um dispositivo de quórum.
  • Testar o failover.

Custos

Use a calculadora de preços para gerar uma estimativa de custo com base no uso previsto.

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. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

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

  7. Enable the Compute Engine API.

    Enable the API

Neste tutorial, comandos serão inseridos usando o Cloud Shell, salvo indicação contrária.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

Etapas da configuração

Nesta seção, será feita a configuração de uma conta de serviço, criação de variáveis de ambiente e reserva endereços IP.

Configurar uma conta de serviço para as instâncias do cluster

  1. Abra o Cloud Shell:

    ABRIR o Cloud Shell

  2. Crie a conta de serviço:

    gcloud iam service-accounts create mysql-instance \
        --display-name "mysql-instance"
    
  3. Anexe os papéis necessários para este tutorial à conta de serviço:

    gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \
        --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \
        --role=roles/compute.instanceAdmin.v1
    
    gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \
        --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \
        --role=roles/compute.viewer
    
    gcloud projects add-iam-policy-binding ${DEVSHELL_PROJECT_ID} \
        --member=serviceAccount:mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \
        --role=roles/iam.serviceAccountUser
    

Criar variáveis de ambiente do Cloud Shell

  1. Crie um arquivo com as variáveis de ambiente necessárias para este tutorial:

    cat <<EOF > ~/.mysqldrbdrc
    # Cluster instance names
    DATABASE1_INSTANCE_NAME=database1
    DATABASE2_INSTANCE_NAME=database2
    QUORUM_INSTANCE_NAME=qdevice
    CLIENT_INSTANCE_NAME=mysql-client
    # Cluster IP addresses
    DATABASE1_INSTANCE_IP="10.140.0.2"
    DATABASE2_INSTANCE_IP="10.140.0.3"
    QUORUM_INSTANCE_IP="10.140.0.4"
    ILB_IP="10.140.0.6"
    # Cluster zones and region
    DATABASE1_INSTANCE_ZONE="asia-east1-a"
    DATABASE2_INSTANCE_ZONE="asia-east1-b"
    QUORUM_INSTANCE_ZONE="asia-east1-c"
    CLIENT_INSTANCE_ZONE="asia-east1-c"
    CLUSTER_REGION="asia-east1"
    EOF
    
  2. Carregue as variáveis de ambiente na sessão atual e configure o Cloud Shell para carregar automaticamente as variáveis em logins futuros:

    source ~/.mysqldrbdrc
    grep -q -F "source ~/.mysqldrbdrc" ~/.bashrc || echo "source ~/.mysqldrbdrc" >> ~/.bashrc
    

Reservar endereços IP

  • No Cloud Shell, reserve um endereço IP interno para cada um dos três nós do cluster:

    gcloud compute addresses create ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} ${QUORUM_INSTANCE_NAME} \
        --region=${CLUSTER_REGION} \
        --addresses "${DATABASE1_INSTANCE_IP},${DATABASE2_INSTANCE_IP},${QUORUM_INSTANCE_IP}" \
        --subnet=default
    

Como criar as instâncias do Compute Engine

Nas etapas a seguir, o Debian 9 é usado pelas instâncias do cluster e o Ubuntu 16 pelas instâncias do cliente.

  1. No Cloud Shell, crie uma instância do MySQL chamada database1 na zona asia-east1-a:

    gcloud compute instances create ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --machine-type=n1-standard-2  \
        --network-tier=PREMIUM \
        --maintenance-policy=MIGRATE \
        --image-family=debian-9 \
        --image-project=debian-cloud \
        --boot-disk-size=50GB \
        --boot-disk-type=pd-standard \
        --boot-disk-device-name=${DATABASE1_INSTANCE_NAME} \
        --create-disk=mode=rw,size=300,type=pd-standard,name=disk-1 \
        --private-network-ip=${DATABASE1_INSTANCE_NAME} \
        --tags=mysql --service-account=mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \
        --scopes="https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly" \
        --metadata="DATABASE1_INSTANCE_IP=${DATABASE1_INSTANCE_IP},DATABASE2_INSTANCE_IP=${DATABASE2_INSTANCE_IP},DATABASE1_INSTANCE_NAME=${DATABASE1_INSTANCE_NAME},DATABASE2_INSTANCE_NAME=${DATABASE2_INSTANCE_NAME},QUORUM_INSTANCE_NAME=${QUORUM_INSTANCE_NAME},DATABASE1_INSTANCE_ZONE=${DATABASE1_INSTANCE_ZONE},DATABASE2_INSTANCE_ZONE=${DATABASE2_INSTANCE_ZONE}"
    
  2. Crie uma instância do MySQL chamada database2 na zona asia-east1-b:

    gcloud compute instances create ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE} \
        --machine-type=n1-standard-2  \
        --network-tier=PREMIUM \
        --maintenance-policy=MIGRATE \
        --image-family=debian-9 \
        --image-project=debian-cloud \
        --boot-disk-size=50GB \
        --boot-disk-type=pd-standard \
        --boot-disk-device-name=${DATABASE2_INSTANCE_NAME} \
        --create-disk=mode=rw,size=300,type=pd-standard,name=disk-2 \
        --private-network-ip=${DATABASE2_INSTANCE_NAME} \
        --tags=mysql \
        --service-account=mysql-instance@${DEVSHELL_PROJECT_ID}.iam.gserviceaccount.com \
        --scopes="https://www.googleapis.com/auth/compute,https://www.googleapis.com/auth/servicecontrol,https://www.googleapis.com/auth/service.management.readonly" \
        --metadata="DATABASE1_INSTANCE_IP=${DATABASE1_INSTANCE_IP},DATABASE2_INSTANCE_IP=${DATABASE2_INSTANCE_IP},DATABASE1_INSTANCE_NAME=${DATABASE1_INSTANCE_NAME},DATABASE2_INSTANCE_NAME=${DATABASE2_INSTANCE_NAME},QUORUM_INSTANCE_NAME=${QUORUM_INSTANCE_NAME},DATABASE1_INSTANCE_ZONE=${DATABASE1_INSTANCE_ZONE},DATABASE2_INSTANCE_ZONE=${DATABASE2_INSTANCE_ZONE}"
    
  3. Crie um nó de quórum para ser usado pelo Pacemaker na zona asia-east1-c:

    gcloud compute instances create ${QUORUM_INSTANCE_NAME} \
        --zone=${QUORUM_INSTANCE_ZONE} \
        --machine-type=n1-standard-1 \
        --network-tier=PREMIUM \
        --maintenance-policy=MIGRATE \
        --image-family=debian-9  \
        --image-project=debian-cloud \
        --boot-disk-size=10GB \
        --boot-disk-type=pd-standard \
        --boot-disk-device-name=${QUORUM_INSTANCE_NAME} \
        --private-network-ip=${QUORUM_INSTANCE_NAME}
    
  4. Crie uma instância do cliente MySQL:

    gcloud compute instances create ${CLIENT_INSTANCE_NAME} \
        --image-family=ubuntu-1604-lts \
        --image-project=ubuntu-os-cloud \
        --tags=mysql-client \
        --zone=${CLIENT_INSTANCE_ZONE} \
        --boot-disk-size=10GB \
        --metadata="ILB_IP=${ILB_IP}"
    

Como instalar e configurar o DRBD

Nesta seção, você instala e configura os pacotes DRBD nas instâncias database1 e database2 e, em seguida, inicia a replicação DRBD de database1 para database2.

Configurar o DRBD no database1

  1. No Console do Google Cloud, acesse a página Instâncias de VM.

    PÁGINA DE INSTÂNCIAS DE VM

  2. Na linha da instância database1, clique em SSH para se conectar à instância.

  3. Crie um arquivo para recuperar e armazenar metadados de instância em variáveis de ambiente:

    sudo bash -c cat <<EOF  > ~/.varsrc
    DATABASE1_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_IP" -H "Metadata-Flavor: Google")
    DATABASE2_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_IP" -H "Metadata-Flavor: Google")
    DATABASE1_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_NAME" -H "Metadata-Flavor: Google")
    DATABASE2_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_NAME" -H "Metadata-Flavor: Google")
    DATABASE2_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_ZONE" -H "Metadata-Flavor: Google")
    DATABASE1_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_ZONE" -H "Metadata-Flavor: Google")
    QUORUM_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/QUORUM_INSTANCE_NAME" -H "Metadata-Flavor: Google")
    
    EOF
    
  4. Carregue as variáveis de metadados do arquivo:

    source ~/.varsrc
    
  5. Formate o disco de dados:

    sudo bash -c  "mkfs.ext4 -m 0 -F -E \
    lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
    

    Para uma descrição detalhada das opções mkfs.ext4, consulte a página de manual mkfs.ext4.

  6. Instale o DRBD:

    sudo apt -y install drbd8-utils
    
  7. Crie o arquivo de configuração do DRBD:

    sudo bash -c 'cat <<EOF  > /etc/drbd.d/global_common.conf
    global {
        usage-count no;
    }
    common {
        protocol C;
    }
    EOF'
    
  8. Crie um arquivo de recursos do DRBD:

    sudo bash -c "cat <<EOF  > /etc/drbd.d/r0.res
    resource r0 {
        meta-disk internal;
        device /dev/drbd0;
        net {
            allow-two-primaries no;
            after-sb-0pri discard-zero-changes;
            after-sb-1pri discard-secondary;
            after-sb-2pri disconnect;
            rr-conflict disconnect;
        }
        on database1 {
            disk /dev/sdb;
            address 10.140.0.2:7789;
        }
        on database2 {
            disk /dev/sdb;
            address 10.140.0.3:7789;
        }
    }
    EOF"
    
  9. Carregue o módulo de kernel do DRBD:

    sudo modprobe drbd
    
  10. Limpe o conteúdo do disco /dev/sdb:

    sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
    
  11. Crie o recurso do DRBD r0:

    sudo drbdadm create-md r0
    
  12. Exiba o DRBD:

    sudo drbdadm up r0
    
  13. Desative o DRBD quando o sistema for iniciado, para que o software de gerenciamento de recursos de cluster exiba todos os serviços necessários na ordem:

    sudo update-rc.d drbd disable
    

Configurar o DRBD no database2

Agora, você instala e configura os pacotes do DRBD na instância database2.

  1. Conecte-se à instância do database2 pelo SSH.
  2. Crie um arquivo .varsrc para recuperar e armazenar metadados de instância em variáveis de ambiente:

    sudo bash -c cat <<EOF  > ~/.varsrc
    DATABASE1_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_IP" -H "Metadata-Flavor: Google")
    DATABASE2_INSTANCE_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_IP" -H "Metadata-Flavor: Google")
    DATABASE1_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_NAME" -H "Metadata-Flavor: Google")
    DATABASE2_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_NAME" -H "Metadata-Flavor: Google")
    DATABASE2_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE2_INSTANCE_ZONE" -H "Metadata-Flavor: Google")
    DATABASE1_INSTANCE_ZONE=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/DATABASE1_INSTANCE_ZONE" -H "Metadata-Flavor: Google")
    QUORUM_INSTANCE_NAME=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/QUORUM_INSTANCE_NAME" -H "Metadata-Flavor: Google")
    EOF
    
  3. Carregue as variáveis de metadados do arquivo:

    source ~/.varsrc
    
  4. Formate o disco de dados:

    sudo bash -c  "mkfs.ext4 -m 0 -F -E  lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb"
    
  5. Instale os pacotes do DRBD:

    sudo apt -y install drbd8-utils
    
  6. Crie o arquivo de configuração do DRBD:

    sudo bash -c 'cat <<EOF  > /etc/drbd.d/global_common.conf
    global {
        usage-count no;
    }
    common {
        protocol C;
    }
    EOF'
    
  7. Crie um arquivo de recursos do DRBD:

    sudo bash -c "cat <<EOF  > /etc/drbd.d/r0.res
    resource r0 {
        meta-disk internal;
        device /dev/drbd0;
        net {
            allow-two-primaries no;
            after-sb-0pri discard-zero-changes;
            after-sb-1pri discard-secondary;
            after-sb-2pri disconnect;
            rr-conflict disconnect;
        }
        on ${DATABASE1_INSTANCE_NAME} {
            disk /dev/sdb;
            address ${DATABASE1_INSTANCE_IP}:7789;
        }
        on ${DATABASE2_INSTANCE_NAME} {
            disk /dev/sdb;
            address ${DATABASE2_INSTANCE_IP}:7789;
        }
    }
    EOF"
    
  8. Carregue o módulo de kernel do DRBD:

    sudo modprobe drbd
    
  9. Limpe o disco /dev/sdb:

    sudo dd if=/dev/zero of=/dev/sdb bs=1k count=1024
    
  10. Crie o recurso do DRBD r0:

    sudo drbdadm create-md r0
    
  11. Exiba o DRBD:

    sudo drbdadm up r0
    
  12. Desative o DRBD quando o sistema for iniciado, para que o software de gerenciamento de recursos de cluster exiba todos os serviços necessários na ordem:

    sudo update-rc.d drbd disable
    

Iniciar a replicação DRBD do database1 para o database2

  1. Conecte-se à instância do database1 pelo SSH.
  2. Substitua todos os recursos r0 no nó principal:

    sudo drbdadm -- --overwrite-data-of-peer primary r0
    sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/drbd0
    
  3. Verifique o status do DRBD:

    sudo cat /proc/drbd | grep ============
    

    A saída será semelhante ao seguinte:

    [===================>] sync'ed:100.0% (208/307188)M
    
  4. Ativar /dev/drbd para /srv:

    sudo mount -o discard,defaults /dev/drbd0 /srv
    

Como instalar o MySQL e o Pacemaker

Nesta seção, você instalará o MySQL e o Pacemaker em cada uma das instâncias.

Instalar o MySQL no database1

  1. Conecte-se à instância do database1 pelo SSH.
  2. Atualize o repositório APT com as definições do pacote MySQL 5.6:

    sudo bash -c 'cat <<EOF  > /etc/apt/sources.list.d/mysql.list
    deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6\ndeb-src http://repo.mysql.com/apt/debian/ stretch mysql-5.6
    EOF'
    
  3. Adicione as chaves GPG ao arquivo repository.srv APT:

    wget -O /tmp/RPM-GPG-KEY-mysql https://repo.mysql.com/RPM-GPG-KEY-mysql
    sudo apt-key add /tmp/RPM-GPG-KEY-mysql
    
  4. Atualize a lista de pacotes:

    sudo apt update
    
  5. Instale o servidor MySQL:

    sudo apt -y install mysql-server
    

    Quando uma senha for solicitada, insira DRBDha2.

  6. Pare o servidor MySQL:

    sudo /etc/init.d/mysql stop
    
  7. Crie o arquivo de configuração do MySQL:

    sudo bash -c 'cat <<EOF  > /etc/mysql/mysql.conf.d/my.cnf
    [mysqld]
    bind-address = 0.0.0.0  # You may want to listen at localhost at the beginning
    datadir = /var/lib/mysql
    tmpdir = /srv/tmp
    user = mysql
    EOF'
    
  8. Crie um diretório temporário para o servidor MySQL (configurado em mysql.conf):

    sudo mkdir /srv/tmp
    sudo chmod 1777 /srv/tmp
    
  9. Mova todos os dados do MySQL para o diretório do DRBD /srv/mysql:

    sudo mv /var/lib/mysql /srv/mysql
    
  10. Vincule /var/lib/mysql a /srv/mysql no volume de armazenamento replicado do DRBD:

    sudo ln -s /srv/mysql /var/lib/mysql
    
  11. Altere o proprietário /srv/mysql para um processo mysql:

    sudo chown -R mysql:mysql /srv/mysql
    
  12. Remova os dados iniciais do InnoDB para garantir que o disco esteja o mais limpo possível:

    sudo bash -c "cd /srv/mysql && rm ibdata1 && rm ib_logfile*"
    

    O InnoDB é um mecanismo de armazenamento para o sistema de gerenciamento de banco de dados MySQL.

  13. Inicie o MySQL:

    sudo /etc/init.d/mysql start
    
  14. Conceda ao usuário raiz acesso a conexões remotas para que seja feito posteriormente o teste da implantação:

    mysql -uroot -pDRBDha2 -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'DRBDha2' WITH GRANT OPTION;"
    
  15. Desative a inicialização automática do MySQL, que é de responsabilidade do gerenciamento de recursos de cluster:

    sudo update-rc.d -f mysql disable
    

Instalar o Pacemaker no database1

  1. Carregue as variáveis de metadados do arquivo .varsrc criado anteriormente:

    source ~/.varsrc
    
  2. Pare o servidor MySQL:

    sudo /etc/init.d/mysql stop
    
  3. Instale o Pacemaker:

    sudo apt -y install pcs
    
  4. Ative pcsd, corosync e pacemaker na inicialização do sistema na instância principal:

    sudo update-rc.d -f pcsd enable
    sudo update-rc.d -f corosync enable
    sudo update-rc.d -f pacemaker enable
    
  5. Configure corosync para iniciar antes de pacemaker:

    sudo update-rc.d corosync defaults 20 20
    sudo update-rc.d pacemaker defaults 30 10
    
  6. Defina a senha de usuário do cluster como haCLUSTER3 para autenticação:

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  7. Execute o script corosync-keygen para gerar uma chave de autorização de cluster de 128 bits e grave em /etc/corosync/authkey:

    sudo corosync-keygen -l
    
  8. Copie authkey para a instância database2. Quando for solicitada uma senha longa, pressione Enter:

    sudo chmod 444 /etc/corosync/authkey
    gcloud beta compute scp /etc/corosync/authkey ${DATABASE2_INSTANCE_NAME}:~/authkey --zone=${DATABASE2_INSTANCE_ZONE} --internal-ip
    sudo chmod 400 /etc/corosync/authkey
    
  9. Crie um arquivo de configuração do cluster Corosync:

    sudo bash -c "cat <<EOF  > /etc/corosync/corosync.conf
    
    totem {
        version: 2
        cluster_name: mysql_cluster
        transport: udpu
        interface {
            ringnumber: 0
            Bindnetaddr: ${DATABASE1_INSTANCE_IP}
            broadcast: yes
            mcastport: 5405
        }
    }
    quorum {
        provider: corosync_votequorum
    two_node: 1
    }
    
    nodelist {
        node {
            ring0_addr: ${DATABASE1_INSTANCE_NAME}
        name:  ${DATABASE1_INSTANCE_NAME}
    
        nodeid: 1
        }
        node {
            ring0_addr:  ${DATABASE2_INSTANCE_NAME}
            name:  ${DATABASE2_INSTANCE_NAME}
            nodeid: 2
        }
    }
    logging {
        to_logfile: yes
        logfile: /var/log/corosync/corosync.log
        timestamp: on
    }
    
    EOF"
    

    Na seção totem, é feita a configuração do protocolo Totem para uma comunicação confiável. Essa comunicação é usada pelo Corosync para controlar a associação de cluster e para especificar como os membros do cluster devem se comunicar uns com os outros.

    As definições relevantes para a configuração são as seguintes:

    • transport: especifica o modo de unicast (udpu).
    • Bindnetaddr: especifica o endereço de rede ao qual o Corosync está vinculado.
    • nodelist: define os nós no cluster e como eles podem ser alcançados. Nesse caso, os nós database1 e database2.
    • quorum/two_node: por padrão, em um cluster de dois nós, nenhum nó adquirirá um quórum. É possível substituir isso especificando o valor “1” para two_node na seção quorum.

    Essas definições permitem configurar o cluster e prepará-lo para uma etapa posterior, ao adicionar um terceiro nó que será o dispositivo de quórum.

  10. Crie o diretório do serviço para corosync:

    sudo mkdir -p /etc/corosync/service.d
    
  11. Configure corosync para que esteja ciente do Pacemaker:

    sudo bash -c 'cat <<EOF  > /etc/corosync/service.d/pcmk
    service {
        name: pacemaker
        ver: 1
    }
    EOF'
    
  12. Ative o serviço corosync por padrão:

    sudo bash -c 'cat <<EOF  > /etc/default/corosync
    # Path to corosync.conf
    COROSYNC_MAIN_CONFIG_FILE=/etc/corosync/corosync.conf
    # Path to authfile
    COROSYNC_TOTEM_AUTHKEY_FILE=/etc/corosync/authkey
    # Enable service by default
    START=yes
    EOF'
    
  13. Reinicie os serviços corosync e pacemaker:

    sudo service corosync restart
    sudo service pacemaker restart
    
  14. Instale o pacote do dispositivo de quórum do Corosync:

    sudo apt -y install corosync-qdevice
    
  15. Instale um script de shell para processar eventos de falha do DRBD:

    sudo bash -c 'cat << 'EOF'  > /var/lib/pacemaker/drbd_cleanup.sh
    #!/bin/sh
    if [ -z \$CRM_alert_version ]; then
        echo "\$0 must be run by Pacemaker version 1.1.15 or later"
        exit 0
    fi
    
    tstamp="\$CRM_alert_timestamp: "
    
    case \$CRM_alert_kind in
        resource)
            if [ \${CRM_alert_interval} = "0" ]; then
                CRM_alert_interval=""
            else
                CRM_alert_interval=" (\${CRM_alert_interval})"
            fi
    
            if [ \${CRM_alert_target_rc} = "0" ]; then
                CRM_alert_target_rc=""
            else
                CRM_alert_target_rc=" (target: \${CRM_alert_target_rc})"
            fi
    
            case \${CRM_alert_desc} in
                Cancelled) ;;
                *)
                    echo "\${tstamp}Resource operation "\${CRM_alert_task}\${CRM_alert_interval}" for "\${CRM_alert_rsc}" on "\${CRM_alert_node}": \${CRM_alert_desc}\${CRM_alert_target_rc}" >> "\${CRM_alert_recipient}"
                    if [ "\${CRM_alert_task}" = "stop" ] && [ "\${CRM_alert_desc}" = "Timed Out" ]; then
                        echo "Executing recovering..." >> "\${CRM_alert_recipient}"
                        pcs resource cleanup \${CRM_alert_rsc}
                    fi
                    ;;
            esac
            ;;
        *)
            echo "\${tstamp}Unhandled \$CRM_alert_kind alert" >> "\${CRM_alert_recipient}"
            env | grep CRM_alert >> "\${CRM_alert_recipient}"
            ;;
    esac
    EOF'
    sudo chmod 0755 /var/lib/pacemaker/drbd_cleanup.sh
    sudo touch /var/log/pacemaker_drbd_file.log
    sudo chown hacluster:haclient /var/log/pacemaker_drbd_file.log
    

Instale o MySQL no database2

  1. Conecte-se à instância do database2 pelo SSH.
  2. Atualize o repositório APT com o pacote MySQL 5.6:

    sudo bash -c 'cat <<EOF  > /etc/apt/sources.list.d/mysql.list
    deb http://repo.mysql.com/apt/debian/ stretch mysql-5.6\ndeb-src http://repo.mysql.com/apt/debian/ stretch mysql-5.6
    EOF'
    
  3. Adicione as chaves GPG ao repositório APT:

    wget -O /tmp/RPM-GPG-KEY-mysql https://repo.mysql.com/RPM-GPG-KEY-mysql
    sudo apt-key add /tmp/RPM-GPG-KEY-mysql
    
  4. Atualize a lista de pacotes:

    sudo apt update
    
  5. Instale o servidor MySQL:

    sudo apt -y install mysql-server
    

    Quando uma senha for solicitada, insira DRBDha2.

  6. Pare o servidor MySQL:

    sudo /etc/init.d/mysql stop
    
  7. Crie o arquivo de configuração do MySQL:

    sudo bash -c 'cat <<EOF  > /etc/mysql/mysql.conf.d/my.cnf
    [mysqld]
    bind-address = 0.0.0.0  # You may want to listen at localhost at the beginning
    datadir = /var/lib/mysql
    tmpdir = /srv/tmp
    user = mysql
    EOF'
    
  8. Remova os dados em /var/lib/mysql e adicione um link simbólico ao destino do ponto de ativação para o volume DRBD replicado. O volume DRBD (/dev/drbd0) será montado em /srv somente quando ocorrer um failover.

    sudo rm -rf /var/lib/mysql
    sudo ln -s /srv/mysql /var/lib/mysql
    
  9. Desative a inicialização automática do MySQL, que é de responsabilidade do gerenciamento de recursos de cluster:

    sudo update-rc.d -f mysql disable
    

Instale o Pacemaker no database2

  1. Carregue as variáveis de metadados do arquivo .varsrc:

    source ~/.varsrc
    
  2. Instale o Pacemaker:

    sudo apt -y install pcs
    
  3. Mova o arquivo Corosync authkey copiado anteriormente para /etc/corosync/:

    sudo mv ~/authkey /etc/corosync/
    sudo chown root: /etc/corosync/authkey
    sudo chmod 400 /etc/corosync/authkey
    
  4. Ative pcsd, corosync e pacemaker na inicialização do sistema na instância de espera:

    sudo update-rc.d -f pcsd enable
    sudo update-rc.d -f corosync enable
    sudo update-rc.d -f pacemaker enable
    
  5. Configure corosync para iniciar antes de pacemaker:

    sudo update-rc.d corosync defaults 20 20
    sudo update-rc.d pacemaker defaults 30 10
    
  6. Defina a senha do usuário do cluster para autenticação. A senha é a mesma (haCLUSTER3) usada para a instância database1.

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  7. Crie o arquivo corosync de configuração:

    sudo bash -c "cat <<EOF  > /etc/corosync/corosync.conf
    
    totem {
        version: 2
        cluster_name: mysql_cluster
        transport: udpu
        interface {
            ringnumber: 0
            Bindnetaddr: ${DATABASE2_INSTANCE_IP}
            broadcast: yes
            mcastport: 5405
        }
    }
    quorum {
        provider: corosync_votequorum
        two_node: 1
    }
    nodelist {
        node {
            ring0_addr: ${DATABASE1_INSTANCE_NAME}
            name: ${DATABASE1_INSTANCE_NAME}
            nodeid: 1
        }
        node {
            ring0_addr: ${DATABASE2_INSTANCE_NAME}
            name: ${DATABASE2_INSTANCE_NAME}
            nodeid: 2
        }
    }
    logging {
        to_logfile: yes
        logfile: /var/log/corosync/corosync.log
    timestamp: on
    }
    EOF"
    
  8. Crie o diretório de serviços do Corosync:

    sudo mkdir /etc/corosync/service.d
    
  9. Configure corosync para que esteja ciente do Pacemaker:

    sudo bash -c 'cat <<EOF  > /etc/corosync/service.d/pcmk
    service {
    name: pacemaker
    ver: 1
    }
    EOF'
    
  10. Ative o serviço corosync por padrão:

    sudo bash -c 'cat <<EOF  > /etc/default/corosync
    # Path to corosync.conf
    COROSYNC_MAIN_CONFIG_FILE=/etc/corosync/corosync.conf
    # Path to authfile
    COROSYNC_TOTEM_AUTHKEY_FILE=/etc/corosync/authkey
    # Enable service by default
    START=yes
    EOF'
    
  11. Reinicie os serviços corosync e pacemaker:

    sudo service corosync restart
    sudo service pacemaker restart
    
  12. Instale o pacote do dispositivo de quórum do Corosync:

    sudo apt -y install corosync-qdevice
    
  13. Instale um script de shell para processar eventos de falha do DRBD:

    sudo bash -c 'cat << 'EOF'  > /var/lib/pacemaker/drbd_cleanup.sh
    #!/bin/sh
    if [ -z \$CRM_alert_version ]; then
        echo "\$0 must be run by Pacemaker version 1.1.15 or later"
        exit 0
    fi
    
    tstamp="\$CRM_alert_timestamp: "
    
    case \$CRM_alert_kind in
        resource)
            if [ \${CRM_alert_interval} = "0" ]; then
                CRM_alert_interval=""
            else
                CRM_alert_interval=" (\${CRM_alert_interval})"
            fi
    
            if [ \${CRM_alert_target_rc} = "0" ]; then
                CRM_alert_target_rc=""
            else
                CRM_alert_target_rc=" (target: \${CRM_alert_target_rc})"
            fi
    
            case \${CRM_alert_desc} in
                Cancelled) ;;
                *)
                    echo "\${tstamp}Resource operation "\${CRM_alert_task}\${CRM_alert_interval}" for "\${CRM_alert_rsc}" on "\${CRM_alert_node}": \${CRM_alert_desc}\${CRM_alert_target_rc}" >> "\${CRM_alert_recipient}"
                    if [ "\${CRM_alert_task}" = "stop" ] && [ "\${CRM_alert_desc}" = "Timed Out" ]; then
                        echo "Executing recovering..." >> "\${CRM_alert_recipient}"
                        pcs resource cleanup \${CRM_alert_rsc}
                    fi
                    ;;
            esac
            ;;
        *)
            echo "\${tstamp}Unhandled \$CRM_alert_kind alert" >> "\${CRM_alert_recipient}"
            env | grep CRM_alert >> "\${CRM_alert_recipient}"
            ;;
    esac
    EOF'
    sudo chmod 0755 /var/lib/pacemaker/drbd_cleanup.sh
    sudo touch /var/log/pacemaker_drbd_file.log
    sudo chown hacluster:haclient /var/log/pacemaker_drbd_file.log
    
  14. Verifique o status do cluster do Corosync:

    sudo corosync-cmapctl | grep "members...ip"
    

    A saída será semelhante ao seguinte:

    runtime.totem.pg.mrp.srp.members.1.ip (str) = r(0) ip(10.140.0.2)
    runtime.totem.pg.mrp.srp.members.2.ip (str) = r(0) ip(10.140.0.3)
    

Como iniciar o cluster

  1. Conecte-se à instância do database2 pelo SSH.
  2. Carregue as variáveis de metadados do arquivo .varsrc:

    source ~/.varsrc
    
  3. Autentique-se nos nós do cluster:

    sudo pcs cluster auth --name mysql_cluster ${DATABASE1_INSTANCE_NAME} ${DATABASE2_INSTANCE_NAME} -u hacluster -p haCLUSTER3
    
  4. Inicie o cluster

    sudo pcs cluster start --all
    
  5. Verifique o status do cluster:

    sudo pcs status
    

    A saída será semelhante ao seguinte:

    Cluster name: mysql_cluster
    WARNING: no stonith devices and stonith-enabled is not false
    Stack: corosync
    Current DC: database2 (version 1.1.16-94ff4df) - partition with quorum
    Last updated: Sat Nov  3 07:24:53 2018
    Last change: Sat Nov  3 07:17:17 2018 by hacluster via crmd on database2
    
    2 nodes configured
    0 resources configured
    
    Online: [ database1 database2 ]
    
    No resources
    
    Daemon Status:
      corosync: active/enabled
      pacemaker: active/enabled
      pcsd: active/enabled
    

Como configurar o Pacemaker para gerenciar recursos de cluster

Você configurará o Pacemaker com os recursos DRBD, de disco, MySQL e de quórum.

  1. Conecte-se à instância do database1 pelo SSH.
  2. Use o utilitário pcs do Pacemaker para enfileirar várias alterações em um arquivo e, posteriormente, enviar essas mudanças para o Cluster Information Base (CIB) atomicamente:

    sudo pcs cluster cib clust_cfg
    
  3. Desative STONITH, você implantará o dispositivo de quórum mais tarde:

    sudo pcs -f clust_cfg property set stonith-enabled=false
    
  4. Desative as configurações relacionadas ao quórum. O nó do dispositivo de quorum será configurado posteriormente.

    sudo pcs -f clust_cfg property set no-quorum-policy=stop
    
  5. Evite que o Pacemaker retome recursos após uma recuperação:

    sudo pcs -f clust_cfg resource defaults resource-stickiness=200
    
  6. Crie o recurso DRBD no cluster:

    sudo pcs -f clust_cfg resource create mysql_drbd ocf:linbit:drbd \
        drbd_resource=r0 \
        op monitor role=Master interval=110 timeout=30 \
        op monitor role=Slave interval=120 timeout=30 \
        op start timeout=120 \
        op stop timeout=60
    
  7. Verifique se foi atribuído apenas um papel principal ao recurso DRBD:

    sudo pcs -f clust_cfg resource master primary_mysql mysql_drbd \
        master-max=1 master-node-max=1 \
        clone-max=2 clone-node-max=1 \
        notify=true
    
  8. Crie o recurso do sistema de arquivos para ativar o disco do DRBD:

    sudo pcs -f clust_cfg resource create mystore_FS Filesystem \
        device="/dev/drbd0" \
        directory="/srv" \
        fstype="ext4"
    
  9. Configure o cluster para colocar o recurso DRBD com o recurso de disco na mesma VM:

    sudo pcs -f clust_cfg constraint colocation add mystore_FS with primary_mysql INFINITY with-rsc-role=Master
    
  10. Configure o cluster para exibir o recurso de disco somente depois que o principal do DRBD for promovido:

    sudo pcs -f clust_cfg constraint order promote primary_mysql then start mystore_FS
    
  11. Crie um serviço MySQL:

    sudo pcs -f clust_cfg resource create mysql_service ocf:heartbeat:mysql \
        binary="/usr/bin/mysqld_safe" \
        config="/etc/mysql/my.cnf" \
        datadir="/var/lib/mysql" \
        pid="/var/run/mysqld/mysql.pid" \
        socket="/var/run/mysqld/mysql.sock" \
        additional_parameters="--bind-address=0.0.0.0" \
        op start timeout=60s \
        op stop timeout=60s \
        op monitor interval=20s timeout=30s
    
  12. Configure o cluster para colocar o recurso MySQL com o recurso de disco na mesma VM:

    sudo pcs -f clust_cfg constraint colocation add mysql_service with mystore_FS INFINITY
    
  13. Assegure-se de que o sistema de arquivos DRBD preceda o serviço MySQL na ordem de inicialização:

    sudo pcs -f clust_cfg constraint order mystore_FS then mysql_service
    
  14. Crie o agente de alerta e adicione o patch ao arquivo de registros como seu destinatário:

    sudo pcs -f clust_cfg alert create id=drbd_cleanup_file description="Monitor DRBD events and perform post cleanup" path=/var/lib/pacemaker/drbd_cleanup.sh
    sudo pcs -f clust_cfg alert recipient add drbd_cleanup_file id=logfile value=/var/log/pacemaker_drbd_file.log
    
  15. Confirme as alterações no cluster:

    sudo pcs cluster cib-push clust_cfg
    
  16. Verifique se todos os recursos estão on-line:

    sudo pcs status
    

    A saída será semelhante ao seguinte:

    Online: [ database1 database2 ]
    
    Full list of resources:
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database1 ]
         Slaves: [ database2 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database1
     mysql_service  (ocf::heartbeat:mysql): Started database1
    

Como configurar um dispositivo de quórum

  1. Conecte-se à instância do qdevice pelo SSH.
  2. Instale pcs e corosync-qnetd:

    sudo apt update && sudo apt -y install pcs corosync-qnetd
    
  3. Inicie o serviço daemon do sistema de configuração do Pacemaker/Corosync (pcsd) e ative-o na inicialização do sistema:

    sudo service pcsd start
    sudo update-rc.d pcsd enable
    
  4. Defina a senha do usuário do (haCLUSTER3) cluster para autenticação:

    sudo bash -c "echo  hacluster:haCLUSTER3 | chpasswd"
    
  5. Verifique o status do dispositivo de quórum:

    sudo pcs qdevice status net --full
    

    A saída será semelhante ao seguinte:

    QNetd address:                  *:5403
    TLS:                            Supported (client certificate required)
    Connected clients:              0
    Connected clusters:             0
    Maximum send/receive size:      32768/32768 bytes
    

Definir as configurações do dispositivo de quórum no database1

  1. Conecte-se ao nó database1 pelo SSH.
  2. Carregue as variáveis de metadados do arquivo .varsrc:

    source ~/.varsrc
    
  3. Autentique o nó do dispositivo de quórum para o cluster:

    sudo pcs cluster auth --name mysql_cluster ${QUORUM_INSTANCE_NAME} -u hacluster -p haCLUSTER3
    
  4. Adicione o dispositivo de quórum ao cluster. Use o algoritmo ffsplit, que garante que o nó ativo será decidido com base em 50% dos votos ou mais:

    sudo pcs quorum device add model net host=${QUORUM_INSTANCE_NAME} algorithm=ffsplit
    
  5. Adicione a configuração de quórum a corosync.conf:

    sudo bash -c "cat <<EOF  > /etc/corosync/corosync.conf
    
    totem {
        version: 2
        cluster_name: mysql_cluster
        transport: udpu
        interface {
            ringnumber: 0
            Bindnetaddr: ${DATABASE1_INSTANCE_IP}
            broadcast: yes
            mcastport: 5405
        }
    }
    
    quorum {
        provider: corosync_votequorum
        device {
            votes: 1
            model: net
            net {
                tls: on
                host: ${QUORUM_INSTANCE_NAME}
                algorithm: ffsplit
            }
        }
    }
    
    nodelist {
        node {
            ring0_addr: ${DATABASE1_INSTANCE_NAME}
            name: ${DATABASE1_INSTANCE_NAME}
            nodeid: 1
        }
        node {
            ring0_addr: ${DATABASE2_INSTANCE_NAME}
            name: ${DATABASE2_INSTANCE_NAME}
            nodeid: 2
        }
    }
    
    logging {
        to_logfile: yes
        logfile: /var/log/corosync/corosync.log
        timestamp: on
    }
    
    EOF"
    
  6. Reinicie o serviço corosync para recarregar a configuração do novo dispositivo de quórum:

    sudo service corosync restart
    
  7. Inicie o daemon de dispositivo de quórum corosync e ative-o na inicialização do sistema:

    sudo service corosync-qdevice start
    sudo update-rc.d corosync-qdevice defaults
    

Definir as configurações do dispositivo de quórum no database2

  1. Conecte-se ao nó database2 pelo SSH.
  2. Carregue as variáveis de metadados do arquivo .varsrc:

    source ~/.varsrc
    
  3. Adicione uma configuração de quórum a corosync.conf:

    sudo bash -c "cat <<EOF  > /etc/corosync/corosync.conf
    
    totem {
        version: 2
        cluster_name: mysql_cluster
        transport: udpu
        interface {
            ringnumber: 0
            Bindnetaddr: ${DATABASE2_INSTANCE_IP}
            broadcast: yes
            mcastport: 5405
        }
    }
    
    quorum {
        provider: corosync_votequorum
        device {
            votes: 1
            model: net
            net {
                tls: on
                host: ${QUORUM_INSTANCE_NAME}
                algorithm: ffsplit
            }
        }
    }
    
    nodelist {
        node {
            ring0_addr: ${DATABASE1_INSTANCE_NAME}
            name: ${DATABASE1_INSTANCE_NAME}
            nodeid: 1
        }
        node {
            ring0_addr: ${DATABASE2_INSTANCE_NAME}
            name: ${DATABASE2_INSTANCE_NAME}
            nodeid: 2
        }
    }
    
    logging {
        to_logfile: yes
        logfile: /var/log/corosync/corosync.log
        timestamp: on
    }
    
    EOF"
    
  4. Reinicie o serviço corosync para recarregar a configuração do novo dispositivo de quórum:

    sudo service corosync restart
    
  5. Inicie o daemon de dispositivo de quórum do Corosync e configure-o para que seja ativado no início do sistema:

    sudo service corosync-qdevice start
    sudo update-rc.d corosync-qdevice defaults
    

Como verificar o status do cluster

O próximo passo é verificar se os recursos do cluster estão on-line.

  1. Conecte-se à instância do database1 pelo SSH.
  2. Verifique o status do cluster:

    sudo pcs status
    

    A saída será semelhante ao seguinte:

    Cluster name: mysql_cluster
    Stack: corosync
    Current DC: database1 (version 1.1.16-94ff4df) - partition with quorum
    Last updated: Sun Nov  4 01:49:18 2018
    Last change: Sat Nov  3 15:48:21 2018 by root via cibadmin on database1
    
    2 nodes configured
    4 resources configured
    
    Online: [ database1 database2 ]
    
    Full list of resources:
    
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database1 ]
         Slaves: [ database2 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database1
     mysql_service  (ocf::heartbeat:mysql): Started database1
    
    Daemon Status:
      corosync: active/enabled
      pacemaker: active/enabled
      pcsd: active/enabled
    
  3. Mostre o status do quórum:

    sudo pcs quorum status
    

    A saída será semelhante ao seguinte:

    Quorum information
    ------------------
    Date:             Sun Nov  4 01:48:25 2018
    Quorum provider:  corosync_votequorum
    Nodes:            2
    Node ID:          1
    Ring ID:          1/24
    Quorate:          Yes
    
    Votequorum information
    ----------------------
    Expected votes:   3
    Highest expected: 3
    Total votes:      3
    Quorum:           2
    Flags:            Quorate Qdevice
    
    Membership information
    ----------------------
        Nodeid      Votes    Qdevice Name
             1          1    A,V,NMW database1 (local)
             2          1    A,V,NMW database2
             0          1            Qdevice
    
  4. Mostre o status do dispositivo de quórum:

    sudo pcs quorum device status
    

    A saída será semelhante ao seguinte:

    Qdevice information
    -------------------
    Model:                  Net
    Node ID:                1
    Configured node list:
        0   Node ID = 1
        1   Node ID = 2
    Membership node list:   1, 2
    
    Qdevice-net information
    ----------------------
    Cluster name:           mysql_cluster
    QNetd host:             qdevice:5403
    Algorithm:              Fifty-Fifty split
    Tie-breaker:            Node with lowest node ID
    State:                  Connected
    

Como configurar um balanceador de carga interno como o IP do cluster

  1. Abra o Cloud Shell:

    ABRIR o Cloud Shell

  2. Crie um grupo de instâncias não gerenciadas e inclua nele a instância do database1:

    gcloud compute instance-groups unmanaged create ${DATABASE1_INSTANCE_NAME}-instance-group \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --description="${DATABASE1_INSTANCE_NAME} unmanaged instance group"
    
    gcloud compute instance-groups unmanaged add-instances ${DATABASE1_INSTANCE_NAME}-instance-group \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --instances=${DATABASE1_INSTANCE_NAME}
    
  3. Crie um grupo de instâncias não gerenciadas e inclua nele a instância do database2:

    gcloud compute instance-groups unmanaged create ${DATABASE2_INSTANCE_NAME}-instance-group \
        --zone=${DATABASE2_INSTANCE_ZONE} \
        --description="${DATABASE2_INSTANCE_NAME} unmanaged instance group"
    
    gcloud compute instance-groups unmanaged add-instances ${DATABASE2_INSTANCE_NAME}-instance-group \
        --zone=${DATABASE2_INSTANCE_ZONE} \
        --instances=${DATABASE2_INSTANCE_NAME}
    
  4. Criar uma verificação de integridade para port 3306:

    gcloud compute health-checks create tcp mysql-backend-healthcheck \
        --port 3306
    
  5. Crie um serviço de back-end interno e regional:

    gcloud compute backend-services create mysql-ilb \
        --load-balancing-scheme internal \
        --region ${CLUSTER_REGION} \
        --health-checks mysql-backend-healthcheck \
        --protocol tcp
    
  6. Adicione os dois grupos de instâncias como back-ends ao serviço de back-end.

    gcloud compute backend-services add-backend mysql-ilb \
        --instance-group ${DATABASE1_INSTANCE_NAME}-instance-group \
        --instance-group-zone ${DATABASE1_INSTANCE_ZONE} \
        --region ${CLUSTER_REGION}
    
    gcloud compute backend-services add-backend mysql-ilb \
        --instance-group ${DATABASE2_INSTANCE_NAME}-instance-group \
        --instance-group-zone ${DATABASE2_INSTANCE_ZONE} \
        --region ${CLUSTER_REGION}
    
  7. Crie uma regra de encaminhamento para o balanceador de carga:

    gcloud compute forwarding-rules create mysql-ilb-forwarding-rule \
        --load-balancing-scheme internal \
        --ports 3306 \
        --network default \
        --subnet default \
        --region ${CLUSTER_REGION} \
        --address ${ILB_IP} \
        --backend-service mysql-ilb
    
  8. Crie uma regra de firewall para permitir uma verificação de integridade do balanceador de carga interno:

    gcloud compute firewall-rules create allow-ilb-healthcheck \
        --direction=INGRESS --network=default \
        --action=ALLOW --rules=tcp:3306 \
        --source-ranges=130.211.0.0/22,35.191.0.0/16 --target-tags=mysql
    
  9. Para verificar o status do seu balanceador de carga, acesse a página Balanceamento de carga no Console do Google Cloud.

    ABRIR A PÁGINA BALANCEAMENTO DE CARGA

  10. Clique em mysql-ilb:

    imagem

    Como o cluster permite que apenas uma instância execute o MySQL por vez, na perspectiva do balanceador de carga interno apenas uma instância é íntegra.

    imagem

Como se conectar ao cluster pelo cliente MySQL

  1. Conecte-se à instância do mysql-client pelo SSH.
  2. Atualize as definições de pacotes:

    sudo apt-get update
    
  3. Instale o cliente MySQL:

    sudo apt-get install -y mysql-client
    
  4. Crie um arquivo de script que crie e preencha uma tabela com dados de amostra:

    cat <<EOF > db_creation.sql
    CREATE DATABASE source_db;
    use source_db;
    CREATE TABLE source_table
    (
        id BIGINT NOT NULL AUTO_INCREMENT,
        timestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
        event_data float DEFAULT NULL,
        PRIMARY KEY (id)
    );
    DELIMITER $$
    CREATE PROCEDURE simulate_data()
    BEGIN
    DECLARE i INT DEFAULT 0;
    WHILE i < 100 DO
        INSERT INTO source_table (event_data) VALUES (ROUND(RAND()*15000,2));
        SET i = i + 1;
    END WHILE;
    END$$
    DELIMITER ;
    CALL simulate_data()
    EOF
    
  5. Crie a tabela:

    ILB_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/ILB_IP" -H "Metadata-Flavor: Google")
    mysql -u root -pDRBDha2 "-h${ILB_IP}" < db_creation.sql
    

Como testar o cluster

Para testar a funcionalidade HA do cluster implantado, é possível executar os seguintes testes:

  • Encerre a instância do database1 para testar se ocorre failover do banco de dados para a instância do database2.
  • Inicie a instância do database1 para ver se database1 consegue voltar a participar do cluster.
  • Encerre a instância do database2 para testar se ocorre failover do banco de dados para a instância do database1.
  • Inicie a instância do database2 para ver se database2 consegue voltar a participar do cluster e se database1 ainda mantém a função de mestre.
  • Crie uma partição de rede entre database1 e database2 para simular um problema de divisão cerebral.

  1. Abra o Cloud Shell:

    ABRIR o Cloud Shell

  2. Interrompa a instância do database1:

    gcloud compute instances stop ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE}
    
  3. Verifique o status do cluster:

    gcloud compute ssh ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE} \
        --command="sudo pcs status"
    

    O resultado será semelhante ao mostrado a seguir. Verifique se as alterações na configuração foram realizadas:

    2 nodes configured
    4 resources configured
    
    Online: [ database2 ]
    OFFLINE: [ database1 ]
    
    Full list of resources:
    
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database2 ]
         Stopped: [ database1 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database2
     mysql_service  (ocf::heartbeat:mysql): Started database2
    
    Daemon Status:
      corosync: active/enabled
      pacemaker: active/enabled
      pcsd: active/enabled
    
  4. Inicie a instância do database1:

    gcloud compute instances start ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE}
    
  5. Verifique o status do cluster:

    gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --command="sudo pcs status"
    

    A saída será semelhante ao seguinte:

    2 nodes configured
    4 resources configured
    
    Online: [ database1 database2 ]
    
    Full list of resources:
    
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database2 ]
         Slaves: [ database1 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database2
     mysql_service  (ocf::heartbeat:mysql): Started database2
    
    Daemon Status:
      corosync: active/enabled
      pacemaker: active/enabled
      pcsd: active/enabled
    
  6. Interrompa a instância do database2:

    gcloud compute instances stop ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE}
    
  7. Verifique o status do cluster:

    gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --command="sudo pcs status"
    

    A saída será semelhante ao seguinte:

    2 nodes configured
    4 resources configured
    
    Online: [ database1 ]
    OFFLINE: [ database2 ]
    
    Full list of resources:
    
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database1 ]
         Stopped: [ database2 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database1
     mysql_service  (ocf::heartbeat:mysql): Started database1
    
    Daemon Status:
      corosync: active/enabled
      pacemaker: active/enabled
      pcsd: active/enabled
    
  8. Inicie a instância do database2:

    gcloud compute instances start ${DATABASE2_INSTANCE_NAME} \
        --zone=${DATABASE2_INSTANCE_ZONE}
    
  9. Verifique o status do cluster:

    gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --command="sudo pcs status"
    

    A saída será semelhante ao seguinte:

    2 nodes configured
    4 resources configured
    
    Online: [ database1 database2 ]
    
    Full list of resources:
    
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database1 ]
         Slaves: [ database2 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database1
     mysql_service  (ocf::heartbeat:mysql): Started database1
    
    Daemon Status:
      corosync: active/enabled
      pacemaker: active/enabled
      pcsd: active/enabled
    
  10. Crie uma partição de rede entre database1 e database2:

    gcloud compute firewall-rules create block-comms \
        --description="no MySQL communications" \
        --action=DENY \
        --rules=all \
        --source-tags=mysql \
        --target-tags=mysql \
        --priority=800
    
  11. Após alguns minutos, verifique o status do cluster. Observe como database1 mantém sua função principal, porque a política de quórum é o nó de ID imediatamente abaixo na situação da partição de rede. Enquanto isso, o serviço MySQL database2 está parado. Esse mecanismo de quórum evita o problema de divisão cerebral quando ocorre a partição de rede.

    gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --command="sudo pcs status"
    

    A saída será semelhante ao seguinte:

    2 nodes configured
    4 resources configured
    
    Online: [ database1 ]
    OFFLINE: [ database2 ]
    
    Full list of resources:
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database1 ]
         Stopped: [ database2 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database1
     mysql_service  (ocf::heartbeat:mysql): Started database1
    
  12. Exclua a regra de firewall de rede para remover a partição de rede. Pressione Y quando for solicitado.

    gcloud compute firewall-rules delete block-comms
    
  13. Verifique se o status do cluster está de volta ao normal:

    gcloud compute ssh ${DATABASE1_INSTANCE_NAME} \
        --zone=${DATABASE1_INSTANCE_ZONE} \
        --command="sudo pcs status"
    

    A saída será semelhante ao seguinte:

    2 nodes configured
    4 resources configured
    
    Online: [ database1 database2 ]
    
    Full list of resources:
    
     Master/Slave Set: primary_mysql [mysql_drbd]
         Masters: [ database1 ]
         Slaves: [ database2 ]
     mystore_FS     (ocf::heartbeat:Filesystem):    Started database1
     mysql_service  (ocf::heartbeat:mysql): Started database1
    
  14. Conecte-se à instância do mysql-client pelo SSH.

  15. No shell, consulte a tabela criada anteriormente:

    ILB_IP=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/ILB_IP" -H "Metadata-Flavor: Google")
    
    mysql -uroot "-h${ILB_IP}" -pDRBDha2 -e "select * from source_db.source_table LIMIT 10"
    

    A saída deve listar 10 registros do formulário a seguir, verificando a consistência de dados no cluster:

    +----+---------------------+------------+
    | id | timestamp           | event_data |
    +----+---------------------+------------+
    |  1 | 2018-11-27 21:00:09 |    1279.06 |
    |  2 | 2018-11-27 21:00:09 |    4292.64 |
    |  3 | 2018-11-27 21:00:09 |    2626.01 |
    |  4 | 2018-11-27 21:00:09 |     252.13 |
    |  5 | 2018-11-27 21:00:09 |    8382.64 |
    |  6 | 2018-11-27 21:00:09 |    11156.8 |
    |  7 | 2018-11-27 21:00:09 |      636.1 |
    |  8 | 2018-11-27 21:00:09 |    14710.1 |
    |  9 | 2018-11-27 21:00:09 |    11642.1 |
    | 10 | 2018-11-27 21:00:09 |    14080.3 |
    +----+---------------------+------------+
    

Sequência de failover

Se o nó principal no cluster ficar inativo, a sequência de failover será semelhante a:

  1. O dispositivo de quórum e o nó de espera perdem a conectividade com o nó principal.
  2. O dispositivo de quórum vota no nó de espera e o nó de espera vota em si mesmo.
  3. O quórum é conseguido pelo nó de espera.
  4. O nó de espera é promovido para principal.
  5. O novo nó principal faz o seguinte:
    1. Promove o DRBD para principal
    2. Ativa o disco de dados MySQL do DRBD.
    3. Inicia o MySQL.
    4. Torna-se íntegro para o balanceador de carga
  6. O balanceador de carga começa a enviar tráfego para o novo nó principal.

Limpar

Excluir o projeto

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

A seguir