Atenção: esse artigo tem um vídeo complementar. Clique e assista!

Do que se trata o artigo:

Este artigo trata de como planejar e executar as configurações necessárias para montar uma estrutura de alta disponibilidade para serviços, quer sejam de Internet ou não, utilizando GNU/Linux.


Para que serve:

Serve para garantir que os serviços (banco de dados, servidores web etc.) estejam disponíveis para uso pelos Clientes mesmo quando da ocorrência de problemas graves, tais como instabilidade ou falhas de hardware.


Em que situação o tema é útil:

Quando você for responsável por manter um serviço que não pode parar (24 h e 7 d) e/ou o mesmo tiver um alto número de acessos e você desejar minimizar os impactos que uma manutenção ou problema de hardware venha causar.

No ambiente atual, a demanda para que os serviços estejam disponíveis 24x7 é maior e cada vez mais presente em todos os segmentos, da indústria ao varejo. Se antes era um requisito existente ou recurso disponível apenas para grandes ambientes, por conta de seu custo, hoje já é possível torná-lo acessível para uma audiência muito maior através de ferramentas open source.

Neste contexto, este artigo apresentará como implementar um ambiente de alta disponibilidade utilizando apenas soluções open source. Contudo, antes de apresentarmos as ferramentas que estão à nossa disposição, é preciso introduzir alguns termos comuns na área e esclarecer os limites da solução proposta.

Alta disponibilidade e escalabilidade

A alta disponibilidade e escalabilidade são requisitos desejáveis em qualquer sistema, e apesar de serem vistas com frequência juntas, as soluções que visam prover alta disponibilidade não implicam em escalabilidade e vice-versa. Para fins deste artigo, podemos definir que:

Alta disponibilidade é a capacidade de um sistema/servidor estar disponível por grandes períodos de tempo;

Escalabilidade é a capacidade de oferecer serviços com qualidade aceitável mesmo com uma demanda crescente.

Este artigo abordará apenas o primeiro item, uma vez que o segundo requer um conhecimento muito mais específico da aplicação que se deseja atender.

Paralisações

Uma vez que um serviço é colocado à disposição dos usuários, uma pressão, antes inexistente, se manifesta: o serviço deve estar disponível sempre que necessário!

Infelizmente, em qualquer ambiente temos que conviver com eventos que atuam para impedir o objetivo acima de ser satisfeito. Estes eventos são as paralisações dos servidores/serviços.

Para minimizarmos seus impactos temos que entender os tipos de paralisações. Estas podem ser divididas em duas categorias:

Não planejadas: são o resultado de falhas aleatórias (imprevisíveis) dos sistemas, associadas a componentes de hardware ou software. Como exemplo, temos discos rígidos com defeitos físicos, memórias com erros, fontes de alimentação queimadas, entre outros;

Planejadas (ou manutenções): associadas a paralisações agendadas para promover a atualização de hardware ou software. Costumam oferecer menor impacto ao negócio por normalmente serem realizadas em momentos de menor tráfego.

No caso das paralisações não planejadas, você pode ter uma postura preventiva, trocando, por exemplo, componentes antes do tempo médio do aparecimento de problemas. Entretanto, tal atitude não é uma garantia de que o componente não apresentará problemas antes dessa data.

Mas qual o impacto de uma paralisação? Apesar de não ser fácil quantificar o prejuízo de uma paralisação, é possível realizar um simples exercício para se entender o potencial que um problema pode alcançar.

Suponha que você tenha um servidor que demora 5 minutos para completar o processo de reinicialização. Se ele é responsável por atender a 100 requisições por segundo, isso significa que teremos 5 minutos x 60 segundos x 100 requisições por segundo = 30.000 requisições não atendidas!

Níveis de disponibilidade

Apesar do desejo de termos uma disponibilidade de 100%, este valor não é realizável na prática. Por conta disso, precisamos definir qual o nível de disponibilidade, conhecido como SLA (Service Level Agreement – que define os níveis aceitáveis para um serviço), antes de desenharmos a nossa solução.

Um SLA é um acordo negociado entre duas partes, onde uma é o Cliente e outra é o fornecedor de um serviço. Ele registra os parâmetros mínimos de qualidade sobre serviços, prioridades, responsabilidades e garantias.

Usualmente iniciamos estimando o tempo máximo desejável de parada (downtime) durante um ano de operação medido em minutos, e encontramos qual a classe de disponibilidade que satisfaz o requisito utilizando a seguinte fórmula:

  D = (1 - R) x 365 x 24 x 60 

Onde D é o tempo máximo de parada em minutos e R é a razão entre o tempo disponível e o indisponível. No mercado é comum encontrarmos os níveis conforme a Tabela 1.

Disponibilidade (%)

Tempo de parada no ano

99

3,65 dias

99,9

8,76 horas

99,99

52,6 minutos

99,999

5,26 minutos

99,9999

30 segundos

Tabela 1. Níveis de disponibilidade

Como atingir a alta disponibilidade?

Uma das maneiras de se atingir a alta disponibilidade está em se desenvolver ou utilizar sistemas tolerantes a falhas. Nestes sistemas, a falha de um componente não afeta a operação, pois é compensada por outro de maneira transparente e automática.

Se considerarmos apenas o contexto de hardware, os sistemas tolerantes a falhas, normalmente proprietários, possuem partes redundantes, ou seja, componentes adicionais que são acionados quando o principal apresenta falha. Nesta categoria encontramos CPUs, memória, disco, fontes de alimentação e refrigeração.

Por sua característica proprietária, os sistemas tolerantes a falhas possuem custos elevados, o que impede a sua adoção fora de ambientes nos quais recursos de pessoal técnico ou financeiros sejam abundantes. Ou pelo menos impedia até o lançamento de projetos como o Linux HA (Linux High Availability – é um conjunto de ferramentas disponíveis para ambiente GNU/Linux).

O Linux HA foi criado em 1998 e reúne vários subprojetos de software que visam trazer a alta disponibilidade ao ambiente GNU/Linux. Ele tem como principal software o pacote Heartbeat.

Com o Linux HA temos acesso a soluções, via software, para alcançar os níveis de disponibilidade sem trazer os altos custos de soluções proprietárias.

Construindo a solução de disponibilidade

Para a construção de nossa solução nos basearemos na redundância de componentes comuns (commodity hardware – hardware comum encontrado no mercado) e de software para detectar a falha e promover a recuperação automática.

Neste artigo assumiremos um ambiente exemplo como visto na Figura 1. Em nosso ambiente temos um servidor WWW, que serve os arquivos e aplicativos de nossa empresa para o mundo.

Figura 1. Servidor WWW.

Obviamente, como temos apenas um servidor, qualquer mau funcionamento nele que acarrete uma paralisação, programada ou não, irá impedir que os usuários acessem os aplicativos lá hospedados.

A primeira abordagem que podemos assumir é duplicar o hardware e de alguma maneira sincronizar o conteúdo de ambos os servidores. Na Figura 2 podemos ver tal abordagem utilizando uma ferramenta comum no ambiente Unix, o rsync.

O rsync é uma ferramenta que permite sincronizar o conteúdo de disco (partições, arquivos, etc.) remotamente e de maneira eficiente. Ele só leva as mudanças que aconteceram entre uma sincronização e outra. Assim, se você faz uma sincronização a cada cinco minutos, ele só leva as mudanças ocorridas nesse período, em vez de copiar todo o conteúdo novamente.

Dessa forma, se seu site está configurado para apontar para o IP A e o servidor apresenta problema, você pode reconfigurar a máquina reserva para usar o mesmo IP e assim seus usuários voltarão a acessar o conteúdo – pelo menos o que existia até a última sincronização (ver Figura 3).

Figura 2. Redundância com o rsync.

Figura 3. Servidor backup em ação.

A solução anterior funciona em alguns ambientes, mas possui muitos limitantes para a realidade pretendida:

A sincronização é periódica. Com isso, todos os dados atualizados entre uma sincronização e outra são perdidos em caso de falha; ou seja, se o servidor de backup sincroniza a cada 1 hora e o principal ficar inacessível nesse intervalo, você colocará o servidor de backup com dados incompletos em seu lugar;

A configuração é manual. A troca do IP do servidor backup e inicialização dos serviços é manual. Isso representa um tempo para recuperação elevado.

Tais restrições nos impendem de alcançar níveis de SLA aceitáveis para a maioria das necessidades. Dessa forma, precisamos utilizar outra abordagem que partirá do mesmo princípio (redundância de hardware), mas se valerá de dois componentes do Linux HA: DRBD (Distributed Replicated Block Device) e o Heartbeat para resolver as limitações vistas com a proposta do rsync.

O DRBD se apresenta para o sistema operacional como um sistema de blocos, assim como um disco rígido. A diferença é que quando o sistema operacional manda escrever nesse dispositivo ele o faz via rede em um dispositivo remoto. Daí o seu caráter distribuído. Por se apresentar como um sistema de blocos ele é transparente para o sistema operacional, que acredita estar gravando localmente como em qualquer dispositivo.

O Heartbeat, por sua vez, é o nosso agente de monitoramento. Ele fica monitorando os elementos que irão compor nossa solução e ao detectar que o elemento considerado ativo (primário) não está respondendo, ele se encarrega de promover o elemento passivo (secundário) de maneira que o mesmo assuma todos os serviços do elemento ativo.

Nossa meta é criar um ambiente que permita em até 30 segundos detectar a falha e automaticamente possibilitar que o servidor backup assuma os serviços oferecidos pelo servidor principal.

Anatomia da solução

Neste artigo iremos montar um ambiente de alta disponibilidade para um servidor Web. Nossa solução, vista na Figura 4, é composta de quatro componentes:

1. Um servidor primário – sistema operacional Linux, com duas interfaces de rede e responsável inicialmente por prover o serviço de Web através do Apache;

2. Um servidor secundário – sistema operacional Linux, com duas interfaces de rede;

3. Um barramento de rede principal ou público – é o barramento de rede pelo qual os Clientes irão acessar o servidor;

4. Um barramento de rede secundário ou privado – é o barramento interno, utilizado apenas para a sincronização (replicação) dos dados do servidor primário para o secundário.

Figura 4. Solução com DRBD+Heartbeat

Na solução usando o DRBD+Hearbeat resolvemos as duas restrições citadas anteriormente (ver Figuras 2 e 3):

Sincronização dos dados transparente. Por se comportar como um disco convencional para o sistema operacional (DRBD), toda e qualquer operação de escrita é transmitida para o ponto secundário automaticamente e de maneira síncrona;

Configuração automática. O Hearbeat ao perceber que o ponto primário não está operante, faz com que o nó secundário assuma o seu papel realizando configurações, como de IP, de forma automática.

Na Figura 5 vemos o que acontece quando ocorre a falha do ponto primário. O servidor B irá assumir o papel do nó primário, passando a responder pelo IP C (associado ao serviço www.dominio.com.br) e iniciará o servidor Apache localmente.

Figura 5. Falha no servidor primário.

Configurando o ambiente

Em nosso exemplo estamos montando uma solução HA para um servidor Web. Usaremos nos dois servidores o sistema operacional Linux com a distribuição CentOS 5.x, os pacotes do Apache, DRBD e o Heartbeat.

Para baixar estas aplicações, acesse os endereços listados no final do artigo na seção Links.

Apesar dos procedimentos de instalação diferirem quanto à distribuição escolhida, todos os pacotes são encontrados nas distribuições mais recentes.

Para montar um ambiente, usaremos como exemplo os parâmetros abaixo:

Servidor A

Interface pública: 172.16.117.162 / 255.255.255.0

Interface privada: 192.168.0.2 / 255.255.255.0

Nome: node0

Servidor B

Interface pública: 172.16.117.163 / 255.255.255.0

Interface privada: 192.168.0.3 / 255.255.255.0

Nome: node1

IP público do serviço Web

172.16.117.160

É importante que em ambos os servidores o serviço do Apache esteja configurado para não se iniciar automaticamente. Esse controle será feito pelo Heartbeat.

Agora realize as etapas descritas a seguir nos dois servidores, salvo onde explicitamente for indicado para realizar apenas no servidor primário.

1ª Etapa: configurando o DRBD

O DRBD é responsável pela sincronização dos dados entre os nós. É desta maneira que é possível usá-lo sem que as aplicações que fazem uso daquela partição tenham que ser modificadas para se beneficiar da replicação.

O arquivo de configuração do DRBD padrão é o /etc/drbd.conf. Usualmente é criado um de exemplo no processo de instalação do pacote. Em nosso exemplo teremos o arquivo apresentado na Listagem 1.

Listagem 1. Arquivo de configuração do DRBD.

  resource apache
  {
    protocol C;
    startup { wfc-timeout 0; degr-wfc-timeout     120; }
    disk { on-io-error detach; }
    net {  cram-hmac-alg "sha1"; shared-secret “senha"; }
    syncer { rate 10M; }
   
    on node0 {
      device /dev/drbd0;
      disk /dev/sdb;
      address 192.168.0.2:7788;
      meta-disk internal;
    }
   
    on node1 {
      device /dev/drbd0;
      disk /dev/sdb;
      address 192.168.0.3:7788;
      meta-disk internal;
    }
  } 
A explicação sobre o funcionamento de todos os parâmetros está além do escopo deste artigo. No entanto, analisaremos alguns dos parâmetros gerais, isto é, que afetam todos os recursos do DRBD. Protocol representa o protocolo de controle do status das operações. Ele possui três opções: A, B ou C. O status indica se a operação de escrita pode ser considerada completa em ambos nós. Cada protocolo, dentre as opções, oferece mais ou menos segurança quanto a considerar a operação concluída. No protocolo A, a replicação acontece em modo assíncrono, ou seja, as operações de escrita são consideradas concluídas quando são realizadas no disco local. A ordem de escrita no nó remoto é colocada em uma fila para transmissão na rede. Se ocorrer um erro neste momento é possível haver perda de dados já que os comandos de escrita não chegarão ao nó remoto. No protocolo B, a replicação acontece em modo semi-síncrono, ou seja, as operações de escrita são consideradas concluídas quando são realizadas no disco local e a ordem de escrita no nó remoto chegam ao destino. Ainda é possível haver perda de dados no caso de uma falha simultânea dos nós antes que o nó remoto tenha escrito no seu disco. No protocolo C, a replicação acontece em modo síncrono, ou seja, as operações de escrita são consideradas concluídas quando ambos os discos (do nó local e remoto) confirmam a gravação dos dados. Assim, escolhemos o protocolo C, pois é o que dá mais garantia quanto à integridade dos dados. Startup indica parâmetros utilizados na inicialização do DRBD. Em nosso caso, wfc-timeout indica o tempo que um nó deve esperar até que o outro nó sinalize estar operacional antes de inicializar o DRBD. Este parâmetro é usado pelo nó sendo inicializado se ele estivesse ativo anteriormente e após um reboot não conseguisse conectar ao outro nó. O valor 0 indica que o nó deverá aguardar indefinidamente ou até uma intervenção manual antes de inicializar o dispositivo. O degr-wfc-timeout é usado em uma situação diferente. Se um nó A estiver inicializando e antes do boot atual o nó B com o qual ele se comunica já estivesse inoperante, o nó A deveria aguardar pelo tempo indicado antes de iniciar o dispositivo DRBD. Em nosso cenário, caso o nó B estivesse fora antes do nó A realizar um reboot, este deveria esperar 120 segundos antes de inicializar os dispositivos. Disk indica como tratar os avisos que o dispositivo físico reporta ao DRBD. Em nosso caso, se detectar erros de operação de entrada/saída deverá desconectar o dispositivo físico. Syncer indica a velocidade disponível para o DRBD utilizar na replicação. A velocidade é um fator influenciado pela capacidade de entrada/saída do dispositivo físico (disco rígido/controladora/barramento de dados) e a interface de rede. Como regra geral, sugere-se limitar em 30% da capacidade nominal de transferência. Por exemplo: suponha que seu sistema de discos suporte uma vazão de 110 MB/s (MBytes/s) e você use uma interface Gigabit na rede de replicação. A taxa a ser usada seria 110 x 0.3 = 33 M. Net define o algoritmo usado para a autenticação entre os dois nós e qual a senha que usaremos. É uma medida de segurança para evitar que outros equipamentos possam se conectar e interagir de forma não autorizada. Enquanto os parâmetros anteriores ditam o comportamento geral do nó, temos que definir como os recursos de disco serão usados pelo sistema. Vamos analisar alguns dos parâmetros para a definição dos recursos que serão oferecidos pelo DRBD. O primeiro parâmetro a ser visto é o resource. Cada resource deve ser pensado como um nome associado a uma partição de um disco rígido. Da mesma maneira que você pode criar alias (apelido) para discos físicos em sua configuração, um resource é um indicador que você usará de agora em diante para todos os comandos de manipulação do DRBD. Você pode ter vários recursos dentro do DRBD. No sistema operacional (e no Heartbeat) você irá referenciar a eles através de um nome para facilitar a execução de comandos. Em nossa solução, definimos um recurso chamado apache:
  resource apache 

Na sequência definimos os nós. Abaixo apresentamos um fragmento do mesmo arquivo de configuração, com foco apenas nos parâmetros que definem um recurso:

  on node0 {
      device /dev/drbd0;
      disk /dev/sdb;
      address 192.168.0.2:7788;
      meta-disk internal;
    }
   
  on node1 {
      device /dev/drbd0;
      disk /dev/sdb;
      address 192.168.0.3:7788;
      meta-disk internal;
    } 

Em nosso caso temos no primeiro nó (node0) um dispositivo /dev/drbd0 que é mapeado para o disco físico /dev/sdb, e vemos que ele fica escutando no IP 192.168.0.2 na porta 7788.

Ao observarmos o segundo nó, vemos que com exceção do IP, que é o IP privado do servidor B, as demais configurações são as mesmas.

Para entendermos o que foi feito é preciso explicar que, em nosso exemplo, existe um segundo disco (/dev/sdb) em cada servidor e que criamos em cada nó um dispositivo (/dev/drbd0) que gravará e lerá os dados desse disco.

O nosso sistema operacional irá gravar na partição drbd0 achando que se trata de um disco físico local (como /dev/sda) e os dados serão replicados para o nó que estiver em modo secundário de forma automática. Assim, se houver uma pane no servidor primário, o segundo terá uma cópia exata dos dados até o momento anterior da pane.

Após criar o arquivo de configuração, copie o mesmo manualmente para o segundo servidor (já que ele é idêntico) e execute como usuário root o comando a seguir na console dos dois servidores:

   drbdadm create-md apache 

O drbdadm é um utilitário que é instalado com o DRBD e lhe permitirá consultar e alterar o comportamento do nó, se necessário.

Neste ponto, o DRBD irá iniciar o processo de inicialização do dispositivo /dev/drbd0, conforme a Listagem 2.

Listagem 2. Processo de inicialização do dispositivo drbd0.

  v08 Magic number not found
  v07 Magic number not found
  About to create a new drbd meta data block on /dev/sdb.
   . ==> This might destroy existing data! <==
  Do you want to proceed? [need to type 'yes' to confirm] yes
  Creating meta data... initialising activity log NOT initialized bitmap (256 KB) New drbd meta data block sucessfully created. 

O tempo necessário para esse procedimento dependerá do tamanho do disco (ou partição) usado.

Agora você deve iniciar o serviço do DRBD com o comando:

  service drbd start 

Se ocorreu tudo bem, ambos os nós estarão marcados como secundários. Então execute o comando abaixo em ambos os servidores:

  cat /proc/drbd 

Ele irá mostrar o status do sistema de controle do DRBD para que você veja como se encontram os dispositivos criados, qual o papel de cada dispositivo (primário/secundário) no servidor onde o comando foi executado e se está sincronizado ou não.

O resultado apresentado na Listagem 3 indica que o dispositivo do DRBD foi criado e que ambos os nós estão no modo secundário.

Listagem 3. O processo de inicialização do drbd0 foi concluído.

  version: 8.0.4 (api:86/proto:86) SVN Revision: 2947 build by buildsvn@c5-i386-build, 2007-07-31 19:17:18
   . 0: cs:Connected st:Secondary/Secondary ds:Inconsistent/Inconsistent C r---
    . ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0
     . resync: used:0/31 hits:0 misses:0 starving:0 dirty:0 changed:0 act_log: used:0/257 hits:0 misses:0 starving:0 dirty:0 changed:0 

Agora você deve escolher um dos dois nós para considerar como primário. Como ambos neste momento não possuem nenhum conteúdo, na prática você pode selecionar qualquer um deles. Para padronizarmos, iremos executar o comando abaixo no node0:

  drbdadm -- --overwrite-data-of-peer primary apache 

O comando irá instruir o servidor onde ele foi executado; em nosso caso node0, que ele deve copiar o conteúdo dos blocos do disco do servidor primário para o secundário.

Como no DRBD nós associamos um nome a cada partição criada, estamos fazendo isso para o resource apache. Caso você tivesse mais de um resource, você deveria fazê-lo para todos os resources existentes.

Agora, se repetirmos o cat /proc/drbd a partir do node0, devemos ver o resultado exibido na Listagem 4.

Listagem 4. Processo de sincronização entre o nó primário e secundário.

  0: cs:SyncTarget st:Primary/Secondary ds:Inconsistent/Inconsistent C r---
    . ns:0 nr:68608 dw:68608 dr:0 al:0 bm:4 lo:0 pe:0 ua:0 ap:0
     . [>...................] sync'ed:  0.9% (8124/8191)M finish: 0:12:05 speed: 11,432 (11,432) K/sec resync: 
      used:0/31 hits:4283 misses:5 starving:0 dirty:0 changed:5 act_log: used:0/257 hits:0 misses:0 starving:0 
      dirty:0 changed:0 

Neste momento ele indica que está realizando o processo de sincronização entre o servidor primário e o secundário. No exemplo da Listagem 4 o DRBD se encontra em 0.9% da sincronização e estima que necessitará de mais 12 minutos e 5 segundos para concluir. O tempo real dependerá do tamanho e performance dos discos de cada servidor e da rede.

Quando o DRBD concluiu o processo de sincronização você ficou com dois dispositivos, um em cada nó, com o mesmo conteúdo de cada bloco do disco físico. Os blocos estão, entretanto, sem nenhuma formatação específica. Para poder usar o disco para armazenar o conteúdo você precisa formatar a partição.

Deste modo, quando o valor estiver em 100%, execute o seguinte comando no node0:

  mkfs.ext3 /dev/drbd0 

Feito isso, você já pode montar a partição e começar a usá-la.

  mkdir /mnt/apache
  mount /dev/drbd0 /mnt/apache 

Com isso já conseguimos resolver metade de nosso objetivo. Tudo que venha a ser escrito em /mnt/apache será replicado automaticamente no node1.

Para darmos continuidade ao processo, iremos desmontar a partição /dev/drbd0 recentemente criada. A função do Heartbeat será gerenciar e cuidar de montar e desmontar as partições automaticamente. Para isso, execute:

  umount /mnt/apache 

O próximo passo é configurar o Heartbeat para que monitore o sistema e promova o servidor secundário a primário, quando necessário.

2ª Etapa: Configurando o Heartbeat

O Heartbeat é uma ferramenta de monitoramento bastante versátil. Para a finalidade de nossa solução, estaremos interessados em três arquivos de configuração: /etc/ha.d/authkeys, /etc/ha.d/ha.cf e /etc/ha.d/haresources.

No /etc/ha.d/authkeys você irá configurar um código e uma senha que deverão ser usados por ambos os nós na comunicação do Heartbeat:

  auth 1
  1 sha1 senha-do-heartbeat 

O auth 1 indica o código a ser usado para identificar os servidores que participarão da comunicação, e na linha seguinte qual a senha a ser usada para garantir que apenas os nós participantes possam se identificar.

No /etc/ha.d/ha.cf você deve configurar os parâmetros que serão usados pelo Heartbeat para monitorar os nós e que critérios usar para tomar a decisão se um nó está operante ou não (Listagem 5).

Listagem 5. Configuração do Heartbeat.

  keepalive 1
  deadtime 10
  warntime 5
  initdead 120
  udpport 694
  ping 172.16.117.1
  bcast eth1
  auto_failback off
  node    172.16.117.162
  node    172.16.117.163 

Aqui os pontos principais são:

deadtime: número de segundos sem comunicação a partir do qual o nó é considerado “morto”;

ping: indica qual o endereço IP que o Heartbeat irá monitorar. Em nosso exemplo estamos monitorando o gateway;

bcast: indica qual a interface de rede no qual os pacotes de controle do Heartbeat serão enviados;

auto_failback: caso um nó seja detectado como morto e depois volte à atividade ele deve (ou não) ser auto promovido a primário. Em nosso caso optamos por avaliar manualmente o evento e decidir qual nó deve ser o primário em um caso desses;

node: indica os IPs da rede pública onde o Heartbeat está instalado.

A parte mais importante para nossa configuração está no último arquivo (haresources). É nele que indicaremos o que o Heartbeat deverá fazer quando detectar um problema e precisar elevar um nó de secundário para primário e vice-versa:

  node0 IPaddr::172.16.117.160/24 drbddisk::apache   Filesystem::/dev/drbd0::/mnt/apache::ext3::defaults httpd 

Em nosso exemplo estamos indicando que o nó que estiver como primário deverá configurar o IP 172.16.117.160/255.255.255.0, montar a partição /dev/drbd0 como /mnt/apache e iniciar o serviço httpd.

No manual do Heartbeat estão descritas todas as opções válidas, mas é importante entender que o processamento desse arquivo acontece na seguinte ordem:

Da esquerda para a direita e de cima para baixo. Quando um nó está sendo promovido a primário ele inicia executando os comandos nessa sequência;

Ou:

Da direita para a esquerda e de baixo para cima. Quando um nó está sendo rebaixado de primário para secundário ele inicia executando os comandos nessa sequência.

É importante que entendamos esta ordem e o porquê dela antes de criarmos nosso haresources.

Quando um nó está se ativando e for decidido que ele é primário, ele irá começar criando um alias com o IP indicado. Este IP é o nosso IP público associado ao servidor Web www.dominio.com.br. Em seguida ele irá montar a partição DRBD no diretório que nós indicamos e só depois irá inicializar o serviço do Apache. Após a inicialização do Apache, quem tentar acessar o serviço irá visualizar a página normalmente.

O nó secundário ficará monitorando e, através do DRBD, sincronizando as modificações na partição criada.

Agora suponha que aconteça algo com o nó primário que o impeça de se comunicar com o gateway, por exemplo: a porta do switch apresente problema ou o cabo de rede seja desconectado.

O Heartbeat detectará este problema e após 10 segundos avisará ao nó secundário que ele deve ser promovido. Esse tempo de 10 segundos serve para evitar que pequenas interrupções temporárias gerem falsos positivos e provoquem a alteração desnecessária. Para isso o Heartbeat irá, no atual nó primário (node0), desligar o serviço do Apache, desmontar a partição e remover o alias do IP.

No node1 ele fará exatamente o que fez quando o node0 foi ativado, e desta maneira, em menos de 30 segundos, os usuários que estivessem acessando o site www.dominio.com.br seriam atendidos pelo novo servidor sem tomar conhecimento da mudança ou qualquer intervenção manual.

3ª Etapa: Testando

Ao chegarmos nessa etapa já temos todos os componentes responsáveis pela alta disponibilidade configurados. O que precisamos fazer agora é realizar ajustes no Apache para que ele trabalhe corretamente com nossa solução.

Deste modo, antes de efetuarmos os testes, existem dois passos necessários:

• Configurar o Apache para disponibilizar o conteúdo da partição criada e não do lugar padrão. Como o Apache por padrão utiliza o diretório /var/www/html, é necessário alterá-lo para o /mnt/apache;

• Iniciar o Heartbeat em ambos servidores.

Primeiro configure o Apache para usar o /mnt/apache como DocumentRoot. Isso pode ser feito editando o arquivo de configuração /etc/httpd/conf/httpd.conf. Assim, procure as entradas DocumentRoot e Directory que apontarem para /var/www/html e mude-as para /mnt/apache.

Em seguida inicie o Heartbeat em ambos os nós. Até o momento ele estava configurado, mas não estava em uso.

  /etc/init.d/heartbeat start 

Com isso, o Heartbeat irá ler os arquivos de configuração que apresentamos anteriormente e executar os comandos que criamos no arquivo haresources.

Neste momento, se observarmos no node0 as interfaces de rede através do comando ifconfig, é possível notar que foi criado um alias (eth0:0) para a interface com o IP público, como destaca a Listagem 6.

Listagem 6. Listagem das interfaces de rede e seus endereços após o Heartbeat iniciar o node0.

  eth0      Link encap:Ethernet  HWaddr 00:0C:29:DA:14:35  
  inet addr:172.16.117.162  Bcast:172.16.117.255  Mask:255.255.255.0
   
  eth0:0    Link encap:Ethernet  HWaddr 00:0C:29:DA:14:35  
  inet addr:172.16.117.160  Bcast:172.16.117.255  Mask:255.255.255.0
            
  eth1      Link encap:Ethernet  HWaddr 00:0C:29:DA:14:3F  
  inet addr:192.168.0.2  Bcast:192.168.0.255  Mask:255.255.255.0 

É possível ainda verificar que ele montou a partição que irá conter o resultado, através do comando df:

  Filesystem           1K-blocks      Used Available Use% Mounted on
  /dev/drbd0              507696     10549    470936   3% /mnt/apache 

Em seguida verifique que ele iniciou o serviço do Apache. Use o comando ps –aux | grep httpd:

  4528 Ss /usr/bin/httpd
  4537 S  /usr/bin/httpd 

Se observarmos o log do Heartbeat, podemos ver as operações sendo executadas e ele fazendo com que os recursos (IP, disco e serviço) migrem de um nó para o outro. O log fica localizado em /var/log/messages (veja a Listagem 7).

Listagem 7. O Heartbeat associa o IP 172.16.117.160 ao nó ativo.

  node0 heartbeat: info: Local Resource acquisition completed.
  node0 harc: info: Running /etc/ha.d/rc.d/ip-request-resp ip-request-resp
  node0 ip-request-resp: received ip-request-resp IPaddr::172.16.117.160/24 OK yes
  node0 ResourceManager: info: Acquiring resource group: node0 IPaddr::172.16.117.160/24 drbddisk::apache 
  Filesystem::/dev/drbd0::/mnt/apache::ext3::defaults httpd
  node0 IPaddr: INFO:  Resource is stopped
  node0 ResourceManager: info: Running /etc/ha.d/resource.d/IPaddr 172.16.117.160/24 start 

Na parte em negrito da Listagem 7 vemos que o Heartbeat começou a executar os comandos que configuramos no arquivo haresources. Note que o Heartbeat primeiro cria o alias com IP 172.16.117.160.

Listagem 8. O Heartbeat monta a partição para uso e inicia o Apache.

  node0 IPaddr: INFO: Using calculated nic for 172.16.117.160: eth0
  node0 IPaddr: INFO: Using calculated netmask for 172.16.117.160: 255.255.255.0
  node0 IPaddr: INFO: eval ifconfig eth0:0 172.16.117.160 netmask 255.255.255.0 broadcast 172.16.117.255
  node0 IPaddr: INFO:  Success
  node0 Filesystem: INFO:  Resource is stopped
  node0 ResourceManager: info: Running /etc/ha.d/resource.d/Filesystem /dev/drbd0 /mnt/apache ext3 defaults start
  node0 Filesystem: INFO: Running start for /dev/drbd0 on /mnt/apache
  node0 kernel: kjournald starting.  Commit interval 5 seconds
  kernel: EXT3 FS on drbd0, internal journal
  node0 kernel: EXT3-fs: mounted filesystem with ordered data mode.
  node0 Filesystem: INFO:  Success 

Na Listagem 8 vemos que o Heartbeat montou a partição /dev/drbd0 como /mnt/apache. Ainda na Listagem 8, também notamos que o Heartbeat iniciou o serviço do Apache para receber as requisições de páginas Web.

  node0 ResourceManager: info: Running /etc/init.d/httpd  start 

Nesse momento, se você acessar o endereço http://172.16.117.160, verá o conteúdo que estiver na partição /mnt/apache.

Para vermos a troca de identidades, ou seja, quem é o nó primário (ativo) e quem é o nó secundário (passivo) basta desconectar o cabo de rede do servidor node0.

Ao fazer isso, o node1 assumirá o papel como nó primário em poucos segundos. Depois acesse o servidor node1 e veja o conteúdo do arquivo /var/log/messages.

Listagem 9. Log do servidor secundário no momento que o Heartbeat detecta que o outro nó está inoperante.

  node1 heartbeat: info: Link node0:eth1 dead.
  node1 ipfail: info: Status update: Node node0 now has status dead
  node1 harc: info: Running /etc/ha.d/rc.d/status status
  node1 heartbeat: info: No local resources [/usr/share/heartbeat/ResourceManager listkeys node1] to acquire. 

O log exibido na Listagem 9 ilustra o momento em que node1 detecta que node0 está inoperante e com isso identifica que precisa se apoderar dos recursos.

Se você repetir os comandos vistos quando iniciamos o Heartbeat, mas agora no node1, verá que ele assumiu o alias, montou a partição e iniciou o servidor apache.

Conclusão

Ao longo deste artigo vimos como é possível configurar dois servidores para prover um serviço de alta disponibilidade, com tempo de parada inferior a 30 segundos, utilizando-se apenas de hardware convencional e de software livre.

Os conceitos vistos aqui podem ser utilizados essencialmente em qualquer servidor/serviço. Servidores de arquivo (como Samba ou NFS) e ainda servidores de banco de dados são candidatos ideais e podem ser configurados para trabalhar nessa estrutura com um mínimo de esforço.

A etapa mais importante é a de definir as ações que o Heartbeat deverá executar ao iniciar um nó primário e ao transferir os recursos para o secundário. Isso lhe permitirá identificar as modificações, se houver, nas configurações dos serviços a serem oferecidos e atingir padrões de disponibilidade antes só alcançáveis com grandes investimentos.

Tudo isso com recursos disponíveis a qualquer um com uma conexão à Internet e um pouco de dedicação.

Links

Linux-HA
www.linux-ha.org

Planet HA
www.planet-ha.org

MySQL com DRBD
www.mysql.com/drbd

DRBD
www.drbd.org