Manual
do
Maker
.
com
Essa solução é muito bem aplicada em ambientes que necessitem alta disponibilidade para serviço web e banco de dados.
Se sua necessidade é baseada em MySQL a partir da versão 5.5, leia esse outro post sobre a replicação com MySQL 5.5 e faça a parte do HA com heartbeat a partir deste próprio.
O ambiente é montado por 2 servidores X (indiferente do hardware utilizado). O Software é basicamente um LAMP + heartbeat rodando em Debian e o tempo de configuração deve ser de uns 10 minutos.
Existem diversos artigos na internet de ambas soluções aplicadas aqui, porém decidi escrever um artigo sobre o assunto para que eu mesmo possa utilizado na posteridade, quando não me lembrar mais do procedimento.
Além da instalação do sistema LAMP (Linux, Apache, PHP, MySQL) e heartbeat será necessário separar 3 IPs fixos, sendo 1 para cada servidor e 1 para utilização de IP virtual. O IP virtual é o IP que será divulgado; as solicitações vindas dos peers remotos terão como destino o IP virtual. Desse modo, a máquina que estiver disponível como master responderá às solicitações. Caso essa máquina se torne indisponível, a outra assumirá automaticamente o IP virtual e passará a responder as solicitações.
No exemplo, utilizarei os IPs 172.0.0.200, 172.0.0.201 e virtual 172.0.0.202. Todas as requisições devem ir para 172.0.0.202.
A base de dados se comunica por background, diretamente pelos seus respectivos IPs. Qualquer operação que seja feita em uma, imediatamente é replicada para a outra e vice-versa. É possível adicionar slaves também para possuir um backup extra, mas não fará parte deste artigo.
Os servidores envolvidos serão nomeados aqui (e preferencialmente utilize a mesma denominação em seu ambiente) como node01 e node02.
Os arquivos de configuração do serviço heartbeat ficam em /etc/ha.d. Alguns arquivos não existem, mas basta criá-los com o respectivo conteúdo.
Seu conteúdo:
auth 2
2 sha1 test-ha
Nesse arquivo especifica-se o nome do servidor master seguido do IP virtual e do script de reload das variáveis de ambiente de trabalho necessárias de se recarregar. Esse script pode ter qualquer nome e deve ficar em /etc/init.d/ como um serviço. Seu conteúdo será explanado mais adiante.node01 172.0.0.202 reload_environment.sh
Esse arquivo contém as pré-definições do funcionamento do heartbeat.
#arquivo de debug
debugfile /var/log/ha-debug
#arquivo de log
logfile /var/log/ha-log
#nivel de log
logfacility local0
#tempo de tolerância
keepalive 2
#tempo para considerar como morto
deadtime 10
#tempo de warning
warntime 10
#diretiva utilizada em tempo de inicialização do heartbeat
initdead 30
#...
udpport 694
#unicast respectivo ao host oposto; 201 no node01, 200 no node02
ucast eth0 172.0.0.201
# O auto_failback retoma como master automaticamente quando se encontra em condições de fazê-lo. Deixá-lo como
#off fará com que retorne somente se o host que assumir como master se perca.
auto_failback off
# node nodename ... -- must match uname -n
node node01 node02
#um host para ping. No caso, o gateway da rede de exemplo.
ping 172.0.0.254
respawn root /usr/lib/heartbeat/ipfail
apiauth ipfail gid=root uid=root
apiauth default gid=root
apiauth cl\_status gid=root
O nome curto deve aparecer como node01 ou node02. Constate isso com hostname -s.
Não experimentei resolver os nomes de outra maneira, então deixo a recomendação de incluir os IPs reais dos hosts no arquivo de hosts:
172.0.0.200 node01
172.0.0.201 node02
Configure apenas os IPs reais em ambos os hosts. Por exemplo:
iface eth0 inet static
address 172.0.0.200
netmask 255.255.255.0
network 172.0.0.0
broadcast 172.0.0.255
gateway 172.0.0.254
Nesse arquivo deve-se especificar o IP virtual, tal como abaixo:
NameVirtualHost 172.0.0.202:80
Listen 80
# SSL name based virtual hosts are not yet supported, therefore no
# NameVirtualHost statement here
Listen 443
Se preferir, renomeie o arquivo a contento, lembrando que se alterado, não esqueça de mudar o nome também no arquivo haresources.
O conteúdo desse arquivo é para exemplo. No caso, estou fazendo HA para o Asterisk:
#! /bin/sh
# /etc/init.d/reload_environment.sh
#
# Some things that run always
touch /var/lock/reload\_environment.sh
# Carry out specific functions when asked to by the system
case "$1" in
start)
#para o asterisk
/usr/sbin/asterisk -rx "restart now"
#matar o script XXX
$(which kill) -9 $(ps ax|egrep 'XXX.py'|egrep -v 'grep'|awk '{print $1}') 2>/dev/null
exit 0
;;
stop)
echo "Nothing to do"
;;
\*)
echo "Usage: /etc/init.d/blah {start|stop}"
exit 1
;;
esac
exit 0
Adeque-o para sua necessidade.
Feitas essas configurações, o serviço pode ser iniciado:/etc/init.d/heartbeat start
Se tiver algum erro, verifique suas configurações, os logs e finalmente faça uma busca no google. Se tudo estiver perdido, escreva o problema nos comentários e "se" realmente for algo que julgar válido, escrevo a resposta.
Em alguns momentos o IP virtual deverá subir na interface eth0 (que foi a utilizada nesse exemplo) do node01. Isso representa o sucesso da operação.
Se desejar fazer um teste com o HA, insira em /var/www um arquivo html com o nome do host. Com ambos os hosts em um mesmo switch, a partir de um client acesse o IP virtual e veja o nome de host que aparece; faça refresh a vontade. Enquanto isso, peça a alguém que remova o cabo do node que estiver sendo exibido durante seus refresh. O IP virtual subirá no outro node.
No arquivo ha.cf você poderá então mudar o tempo de vida conforme desejado, para mais ou para menos, mas tudo dependerá da aplicação que pretende rodar em seu ambiente. Fatores como qualidade de rede física e lógica também podem influenciar.
O MySQL é impressionante por sua facilidade de configuração. Além de estar toda concentrada no arquivo /etc/mysql/my.cnf, não é necessário instalar nenhum pacote adicional para a tarefa. Não estou certo de que posso ser claro na explicação dos parâmetros, mas seguramente é uma configuração funcional. Seu conteúdo:
#padrao
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0
[mysqld]
#
# \* Basic Settings
#
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
language = /usr/share/mysql/english
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
#bind-address = 127.0.0.1
#
# \* Fine Tuning
#
key\_buffer = 16M
max\_allowed\_packet = 16M
thread\_stack = 128K
thread\_cache\_size = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover = BACKUP
#max\_connections = 100
#table\_cache = 64
#thread\_concurrency = 10
#
# \* Query Cache Configuration
#
query\_cache\_limit = 1M
query\_cache\_size = 16M
#
# \* Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
#log = /var/log/mysql/mysql.log
#
# Error logging goes to syslog. This is a Debian improvement :)
#
# Here you can see queries with especially long duration
#log\_slow\_queries = /var/log/mysql/mysql-slow.log
#long\_query\_time = 2
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
#configuracoes para o servico
#no node02 utilize 2 e no node01 utilize 1 no server-id
server-id = 2
replicate-same-server-id= 0
auto-increment-increment= 2
auto-increment-offset = 2
log\_bin = /var/log/mysql/mysql-bin.log
expire\_logs\_days = 10
max\_binlog\_size = 500M
#bases que nao serao replicadas devem ser explicitamente ignoradas
binlog\_ignore\_db = mysql
#bases a replicar
binlog\_do\_db = asterisk
replicate-do-db = asterisk
binlog\_do\_db = base\_2
replicate-do-db = base\_2
binlog\_do\_db = base\_3
replicate-do-db = base\_3
binlog\_do\_db = base\_n
replicate-do-db = base\_n
#o master para o nodeX é o outro node
master-host = 172.0.0.201
#sugestao: replicar com o mesmo usuario e senha para facilitar a configuracao
master-user = replicador
master-password = escravo
master-connect-retry = 60
#
# \* BerkeleyDB
#
# Using BerkeleyDB is now discouraged as its support will cease in 5.1.12.
skip-bdb
[mysqldump]
quick
quote-names
max\_allowed\_packet = 16M
[mysql]
#no-auto-rehash # faster start of mysql but no tab completition
[isamchk]
key\_buffer = 16M
#
# \* IMPORTANT: Additional settings that can override those from this file!
# The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/
Terminada a configuração do my.cnf, deve-se ainda executar a permissão para o usuário de replicação. Algo como isto funciona bem:mysql> grant all privileges on *.* to replicador@'%' identified by 'escravo';
Pode ser necessário (porque tenho certeza de que funcionou sem, mas já tive que fazê-lo) utilizar um comando para levantar o slave:mysql> start slave;
A partir de então, pode-se testar fazendo um insert em qualquer um dos nodes e verificando sua inserção no outro e vice-versa. Alguns problemas podem ser resolvidos a partir desses documentos:
http://dev.mysql.com/doc/refman/4.1/pt/replication-problems.html
http://dev.mysql.com/doc/refman/4.1/pt/replication-faq.html
Alguns comandos também podem auxiliar em diagnósticos e informações, como:
show slave statusG;
show master statusG;
show processlist;
O comando show slave statusG deverá retornar em seu primeiro campo a informação:Slave_IO_State: Waiting for master to send event
E mais abaixo, outras duas informações essenciais:
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Infelizmente é inviável explicar todos os parâmetros, todos os comandos diagnósticos, ações a tomar em casos de falhas etc, mas ao menos você poderá iniciar um projeto de replicação com HA a partir de um ambiente funcional e os avanços dependerão apenas de você. ;-)
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.