DRBD + OCFS2 + Haproxy + Keepalived + Debian Wheezy
E ai galera, aqui vou estar apresentando uma solução de Alta disponibilidade com balanceamento de carga para servidores Apache, porém pode ser utilizado para outros tipos de serviço, nessa solução vou estar utilizando o DRBD + OCFS2 para garantir a disponibilidade dos dados entre os servidores Apache, vou estar utilizando o Haproxy que vai fazer o balanceamento da Carga, ele tem uma fácil configuração e tem uma interface web para acompanhamento de estatísticas, o Keepalived é um framework escrito em C, que fica monitorando o pool do LVS, o LVS é o responsável pelo balanceamento de carga, com isso caso um dos servidores do pool acabe caindo ele toma à ação de remover do pool para não ter conflito na resposta para o cliente.
O que vou utilizar de máquinas:
Vamos utilizar no mínimo 4 máquinas nesta solução, pois teremos 2 balancer para garantir a disponibilidade do balanceamento de carga, teremos 2 servidores apache para os dados, aqui vou utilizar o algoritmo round robin que distribui as requisições iguais entre os 2 servidores.
- Nodo1 do Balancer nome: balancer1
- Ip Real: 192.168.25.40/24
- Ip Compartilhado: 192.168.25.30/24
- Nodo2 do Balancer nome: balancer2
- Ip Real: 192.168.25.41/24
- Ip compartilhado: 192.168.25.30/24
- Nodo1 do Apache: apache1
- Ip Real: 192.168.25.42/24
- Partição utilizada: /dev/sdb1 dispositivo com 8 GB
- Ip para DRBD: 172.19.0.1/30
- Nodo2 do Apache : apache2
- Ip Real: 192.168.25.43/24
- Partição utilizada: /dev/sdb1 dispositivo com 8 GB
- Ip para DRBD: 172.19.0.2/30
Aqui nos servidores que vão ter o apache, vou utilizar 2 faixas de ip, uma delas está na DMZ que seria a nossa VLAN da DMZ e a outra está na rede de dados, que poderia ser a VLAN de SCSI.
Por que utilizar dessa forma ?
Aqui vamos separar, o tráfego, pois quanto maior for o compartilhamento de dados entre os DRBD, maior vai ser o nosso fluxo na rede, com isso vamos deixar em uma VLAN que é dedicada para dados para não complicar o resto da nossa rede.
Prepare o seu sistema com o seguinte script http://wiki.douglasqsantos.com.br/doku.php/confinicialwheezy_en para que não falte nenhum pacote ou configuração.
Configuração inicial dos servidores Apache
Vamos começar a configuração dos servidores do Apache, que é um pouco mais trabalhosa.
Vamos atualizar e fazer um upgrade do sistema nas duas maquinas
aptitude update && aptitude dist-upgrade -y
Vamos acertar o /etc/hosts deixe como abaixo nos dois nodos do Apache.
vim /etc/hosts 127.0.0.1 localhost 192.168.25.42 apache1.douglasqsantos.com.br apache1 192.168.25.43 apache2.douglasqsantos.com.br apache2
Agora vamos instalar o drbd e o ocfs2 faça isso nos dois nodos do Apache.
aptitude install drbd8-utils ocfs2-tools ocfs2-tools-dev -y
Agora vamos carregar os módulos faça isso nos dois nodos do Apache.
modprobe cn modprobe drbd
Configuração do DRBD
Deixe o arquivo como abaixo nos dois nodos do Apache.
vim /etc/drbd.conf include "drbd.d/global_common.conf"; #include "drbd.d/*.res";
Execute nas duas maquinas a parte abaixo.
Vamos fazer backup do arquivo de configuração original
cp /etc/drbd.d/global_common.conf{,.bkp}
Deixe o arquivo como abaixo
vim /etc/drbd.d/global_common.conf #/etc/drbd.conf # Opções Globais # Geralmente no início do arquivo. Poucas opções são definidas nesta seção. # global { usage-count yes; # Gerar status da atualização do sistema de DRBD. } # # Opções comuns a mais de um recurso, quando houver. No caso de existir opções # definidas internamente ao recurso, elas irão sobrepor as opções comuns. common { protocol C; # Método de replicação. Neste caso, replicação síncrona. } ### ocfs2 usando 02 primários resource r1 { net { # Permitir/habilitar dois servidores primários. allow-two-primaries; #Permite habilitar dois servidores primários #Descarta o último disco que se tornar primário em caso da quebra de #consistência, quando os dois discos estiverem como secundários after-sb-0pri discard-younger-primary; #Entrar em consenso para descartar um disco após quebra de consistência #quando houver um disco primário. Geralmente é resolvido na opção anterior, #Caso contrário, irá desconectar os dois discos after-sb-1pri consensus; #Desconectar em caso de quebra de consistência quando houver dois discos primários after-sb-2pri disconnect; } startup { # Iniciar os dois servidores como primários, por padrão. become-primary-on both; # Espera 20 segundos pelo segundo nodo caso ele não suba podemos subir somente 1. wfc-timeout 20; } syncer { rate 600M; #Para placas de rede de 10/100 utilizar 10M } on apache1 { device /dev/drbd1; # Nome do dispositivo de DRBD disk /dev/sdb1; # Dispositivo de baixo nível utilizado a partição address 172.19.0.1:7789; # IP:porta de conexão meta-disk internal; # Armazenamento das informações de dados é feito # dentro do dispositivo de baixo nível. } on apache2 { device /dev/drbd1; disk /dev/sdb1; address 172.19.0.2:7789; meta-disk internal; } }
Agora vamos preparar o disco, faça isso nos dois nodos do Apache.
fdisk /dev/sdb O dispositivo não contém nem uma tabela de partições DOS válida nem um rótulo de disco Sun, OSF ou SGI Building a new DOS disklabel with disk identifier 0x6aadf3ff. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won't be recoverable. Aviso: a opção inválida 0x0000 da tabela de partições 4 será corrigida por gravação (w) WARNING: DOS-compatible mode is deprecated. It's strongly recommended to switch off the mode (command 'c') and change display units to sectors (command 'u'). Comando (m para ajuda): p Disk /dev/sdb: 8589 MB, 8589934592 bytes 255 heads, 63 sectors/track, 1044 cylinders Units = cilindros of 16065 * 512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x6aadf3ff Dispositivo Boot Start End Blocks Id System Comando (m para ajuda): n Comando - ação e estendida p partição primária (1-4) p Número da partição (1-4): 1 Primeiro cilindro (1-1044, default 1): ENTER Using default value 1 Last cilindro, +cilindros or +size{K,M,G} (1-1044, default 1044): ENTER Using default value 1044 Comando (m para ajuda): w A tabela de partições foi alterada! Chamando ioctl() para reler tabela de partições. Sincronizando discos.
Agora vamos zerar as partições tem que ser executado nos dois nodos do Apáche.
dd if=/dev/zero of=/dev/sdb1 bs=1M count=128
Execute este comando nos dois nodos do Apache antes de passar para o próximo comando.
drbdadm -- --discard-my-data connect r1 --== Thank you for participating in the global usage survey ==-- The server's response is: you are the 163th user to install this version
Onde r1 é o nome do nosso dispositivo, que no arquivo de configuração do drbd está como resource r1.
Execute este comando nos dois nodos do Apache antes de passar para o próximo comando.
drbdadm create-md r1 Writing meta data... initializing activity log NOT initialized bitmap New drbd meta data block successfully created. success
Execute este comando nos dois nodos do Apache antes de passar para o próximo comando.
drbdadm attach r1
Execute este comando nos dois nodos do Apache antes de passar para o próximo comando.
drbdadm connect r1
Pronto, agora podemos iniciar o drbd, inicie-o nos dois nodos do Apache com o seguinte comando:
/etc/init.d/drbd start Starting DRBD resources:[ s(r1) ]1: State change failed: (-2) Refusing to be Primary without at least one UpToDate disk Command '/sbin/drbdsetup 1 primary' terminated with exit code 17 1: State change failed: (-2) Refusing to be Primary without at least one UpToDate disk Command '/sbin/drbdsetup 1 primary' terminated with exit code 17 1: State change failed: (-2) Refusing to be Primary without at least one UpToDate disk Command '/sbin/drbdsetup 1 primary' terminated with exit code 17 1: State change failed: (-2) Refusing to be Primary without at least one UpToDate disk Command '/sbin/drbdsetup 1 primary' terminated with exit code 17 1: State change failed: (-2) Refusing to be Primary without at least one UpToDate disk Command '/sbin/drbdsetup 1 primary' terminated with exit code 17
Podemos observar como está a situação do nosso dispositivo drbd com o seguinte comando.
cat /proc/drbd version: 8.3.11 (api:88/proto:86-96) srcversion: F937DCB2E5D83C6CCE4A6C9 1: cs:Connected ro: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 ep:1 wo:f oos:8387292
Se em “Connected st” estiver como !Primary/Primary, está tudo ok, porém se estiver como !Secondary/Secondary temos que forçar os dispositivos a passarem para primary e temos mais uma situação quanto ao dispositivo Unknown, normalmente é quando um dos servidores não está operante por problemas de rede ou de configuração do arquivo do drbd. Então muita atenção a esses detalhes.
Vamos levar em consideração que só estamos com o problema que os dois servidores estão como secondary, resolvemos com o seguinte comando. Este comando tem que ser rodado nos dois servidores.
drbdadm -- --overwrite-data-of-peer primary r1
Agora vamos monitorar novamente.
cat /proc/drbd version: 8.3.11 (api:88/proto:86-96) srcversion: F937DCB2E5D83C6CCE4A6C9 1: cs:SyncTarget ro:Primary/Primary ds:Inconsistent/UpToDate C r----- ns:0 nr:1393280 dw:1393280 dr:0 al:0 bm:85 lo:1 pe:7420 ua:0 ap:1 ep:1 wo:f oos:6994012 [==>.................] sync'ed: 16.7% (6828/8188)Mfinish: 0:03:16 speed: 35,620 (36,664) want: 614,400 K/sec
Agora é só esperar eles sincronizarem os dados, isso depende da placa de rede, da velocidade do disco e do tamanho do disco, fora os processos do drbd, se você notar muita lentidão em algum desses fatores, veja se não é bom fazer algum upgrade.
Para acompanhar a sincronização pode utilizar o seguinte comando:
watch cat /proc/drbd Every 2,0s: cat /proc/drbd Mon Jun 24 16:26:39 2013 version: 8.3.11 (api:88/proto:86-96) srcversion: F937DCB2E5D83C6CCE4A6C9 1: cs:SyncTarget ro:Primary/Primary ds:Inconsistent/UpToDate C r----- ns:0 nr:2209156 dw:2209152 dr:0 al:0 bm:134 lo:1 pe:7446 ua:0 ap:1 ep:1 wo:f oos:6178140 [====>...............] sync'ed: 26.4% (6032/8188)Mfinish: 0:02:49 speed: 36,404 (36,212) want: 614,400 K/sec
Agora depois de sincronizados
cat /proc/drbd version: 8.3.11 (api:88/proto:86-96) srcversion: F937DCB2E5D83C6CCE4A6C9 1: cs:Connected ro:Primary/Primary ds:UpToDate/UpToDate C r----- ns:0 nr:8387316 dw:8387292 dr:16 al:0 bm:512 lo:0 pe:0 ua:0 ap:0 ep:1 wo:f oos:0
Configurando o OCFS2
Vamos configurar o cluster para o ocfs2. Tem que ser configurado nos dois nodos do Apache.
vim /etc/ocfs2/cluster.conf node: ip_port = 7777 ip_address = 172.19.0.1 number = 0 name = apache1 cluster = ocfs2 node: ip_port = 7777 ip_address = 172.19.0.2 number = 1 name = apache2 cluster = ocfs2 cluster: node_count = 2 name = ocfs2
Agora vamos configurar o o2cb tem que ser configurado nos dois nodos do Apache.
sed -i 's/O2CB_ENABLED=false/O2CB_ENABLED=true/g' /etc/default/o2cb
Agora é vamos reiniciar o serviço do o2cb nos dois nodos
/etc/init.d/o2cb restart ls: cannot access /config: No such file or directory Loading filesystem "configfs": OK Mounting configfs filesystem at /sys/kernel/config: OK Loading stack plugin "o2cb": OK Loading filesystem "ocfs2_dlmfs": OK Creating directory '/dlm': OK Mounting ocfs2_dlmfs filesystem at /dlm: OK Setting cluster stack "o2cb": OK Starting O2CB cluster ocfs2: OK
Agora vamos reiniciar o ocfs2 nos dois nodos
/etc/init.d/ocfs2 restart Stopping Oracle Cluster File System (OCFS2) OK
Agora é so criar o sistema de arquivos ocfs2 no drbd, precimos fazer isso somente em um dos dois nodos do Apache
Opções: -C (indicado acima de 128K para grandes arquivos) -b (indicado 4K) -N qtd de nodos -L label para o a partição
mkfs.ocfs2 -b 4K -C 128K -N 2 -L ocfs2 /dev/drbd1 mkfs.ocfs2 1.4.4 Cluster stack: classic o2cb Label: Features: sparse backup-super unwritten inline-data strict-journal-super Block size: 4096 (12 bits) Cluster size: 4096 (12 bits) Volume size: 8586858496 (2096401 clusters) (2096401 blocks) Cluster groups: 65 (tail covers 32017 clusters, rest cover 32256 clusters) Extent allocator size: 4194304 (1 groups) Journal size: 67108864 Node slots: 4 Creating bitmaps: done Initializing superblock: done Writing system files: done Writing superblock: done Writing backup superblock: 2 block(s) Formatting Journals: done Growing extent allocator: done Formatting slot map: done Writing lost+found: done mkfs.ocfs2 successful
Agora é so montar a partição
Vamos criar um diretório para o OCFS2 nos dois nodos do Apache e vamos montar.
mkdir /ocfs2 mount.ocfs2 /dev/drbd1 /ocfs2/
Vamos agora verificar as nossas partições
df -Th Sist. Arq. Tipo Tam Usad Dispon. Uso% Montado em rootfs rootfs 323M 212M 95M 70% / udev devtmpfs 10M 0 10M 0% /dev tmpfs tmpfs 38M 376K 37M 1% /run /dev/disk/by-uuid/86265303-3a06-49db-aa1b-49088580a1cb ext4 323M 212M 95M 70% / tmpfs tmpfs 5,0M 4,0K 5,0M 1% /run/lock tmpfs tmpfs 167M 0 167M 0% /run/shm /dev/sda9 ext4 2,8G 69M 2,6G 3% /home /dev/sda8 ext4 234M 6,1M 216M 3% /tmp /dev/sda5 ext4 2,8G 1019M 1,7G 39% /usr /dev/sda6 ext4 1,4G 329M 980M 26% /var /dev/drbd1 ocfs2 8,0G 151M 7,9G 2% /ocfs2
Como podemos ver temos a nossa partição montada com ocfs2
Agora podemos deixar isso na inicialização do sistema
vim /etc/fstab [...] /dev/drbd1 /ocfs2 ocfs2 _netdev,defaults,noatime 0 0
Agora vamos ajustar a ordem de inicialização dos serviços no dois servidores
Agora temos que acertar o o2cb nos dois nodos do apache, o cabeçalho tem que ficar como abaixo, por que nas ultimas versões o drbd não ta funcionando corretamente no runlevel S
vim /etc/init.d/o2cb #!/bin/bash # init fragment for O2CB. # # chkconfig: 2345 24 20 # description: Load O2CB cluster services at system boot. # ### BEGIN INIT INFO # Provides: o2cb # Required-Start: $network drbd # Should-Start: # Required-Stop: $network drbd # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Load O2CB cluster services at system boot. # Description: Load O2CB cluster services at system boot. ### END INIT INFO
Agora temos que acertar o ocfs2 nos dois nodos do apache, o cabeçalho tem que ficar como abaixo, por que nas ultimas versões o drbd não ta funcionando corretamente no runlevel S
vim /etc/init.d/ocfs2 #! /bin/bash # Copyright (c) 2005 Oracle # All rights reserved. # # chkconfig: 2345 25 19 # description: Mount OCFS2 volumes at boot. # ### BEGIN INIT INFO # Provides: ocfs2 # Required-Start: $local_fs $network o2cb # Required-Stop: $local_fs $network o2cb # X-UnitedLinux-Should-Start: # X-UnitedLinux-Should-Stop: # X-Stop-After: sendsigs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Mount OCFS2 volumes at boot. # Description: Mount OCFS2 volumes at boot. ### END INIT INFO
Agora temos que recarregar as configuração de inicialização dos serviços
Vamos tirar os serviços da inicialização primeiro
insserv -r -v ocfs2 insserv -r -v o2cb insserv -r -v drbd
Agora vamos colocar eles na inicialização novamente
insserv -f -v drbd insserv -f -v o2cb insserv -f -v ocfs2
Agora vamos reiniciar os dois nodos do Apache para testarmos se vai ser montado o drbd na inicialização
init 6
Depois da inicialização nodo1 do Apache
Vamos consultar o uptime da maquina
uptime 16:39:26 up 0 min, 1 user, load average: 0,06, 0,01, 0,01
Agora vamos consultar as partições
df -Th Sist. Arq. Tipo Tam Usad Dispon. Uso% Montado em rootfs rootfs 323M 212M 95M 70% / udev devtmpfs 10M 0 10M 0% /dev tmpfs tmpfs 38M 312K 37M 1% /run /dev/disk/by-uuid/86265303-3a06-49db-aa1b-49088580a1cb ext4 323M 212M 95M 70% / tmpfs tmpfs 5,0M 4,0K 5,0M 1% /run/lock tmpfs tmpfs 167M 0 167M 0% /run/shm /dev/sda9 ext4 2,8G 69M 2,6G 3% /home /dev/sda8 ext4 234M 6,1M 216M 3% /tmp /dev/sda5 ext4 2,8G 1019M 1,7G 39% /usr /dev/sda6 ext4 1,4G 330M 980M 26% /var /dev/drbd1 ocfs2 8,0G 151M 7,9G 2% /ocfs2
Depois da inicialização nodo2 do Apache
vamos consultar o uptime da maquina
uptime 16:39:24 up 0 min, 1 user, load average: 0,06, 0,02, 0,01
Agora vamos listar as partições
df -Th Sist. Arq. Tipo Tam Usad Dispon. Uso% Montado em rootfs rootfs 323M 212M 95M 70% / udev devtmpfs 10M 0 10M 0% /dev tmpfs tmpfs 38M 312K 37M 1% /run /dev/disk/by-uuid/86265303-3a06-49db-aa1b-49088580a1cb ext4 323M 212M 95M 70% / tmpfs tmpfs 5,0M 4,0K 5,0M 1% /run/lock tmpfs tmpfs 167M 0 167M 0% /run/shm /dev/sda9 ext4 2,8G 69M 2,6G 3% /home /dev/sda8 ext4 234M 6,1M 216M 3% /tmp /dev/sda5 ext4 2,8G 1019M 1,7G 39% /usr /dev/sda6 ext4 1,4G 330M 980M 26% /var /dev/drbd1 ocfs2 8,0G 151M 7,9G 2% /ocfs2
Caso de algum problema na inicialização como um dos dois nodos do Apache não ficar como primary temos podemos resolver da seguinte maneira
Primeiro vamos mandar desmontar as partições montadas com o ocfs2 nos dois nodos do Apache
umount /ocfs2
Agora vamos mandar reiniciar o drbd nos dois nodos do Apache
/etc/init.d/drbd restart
Agora vamos forçar a utilização dos dois nodos do Apache
drbdadm -- --overwrite-data-of-peer primary r1
Agora é so remontar as partições novamente nos dois nodos do Apache
mount.ocfs2 /dev/drbd1 /ocfs2/
Erros de sincronismo
Exemplo de erro de sincronismo dos discos, aonde perdemos a consistencia dos dados, com isso vamos precisar acertar este erro.
cat /proc/drbd version: 8.3.7 (api:88/proto:86-91) srcversion: EE47D8BF18AC166BE219757 1: cs:StandAlone ro:Secondary/Unknown ds:Outdated/DUnknown r---- ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:258100
No nodo2 vamos mandar ele desconsiderar os dados que ele já tem e resincronizar com o nodo1 do Apache
drbdadm -- --discard-my-data connect r1
Agora vamos verificar a sincronismo.
cat /proc/drbd version: 8.3.7 (api:88/proto:86-91) srcversion: EE47D8BF18AC166BE219757 1: cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r---- ns:0 nr:293128 dw:287336 dr:0 al:0 bm:19 lo:1448 pe:35179 ua:1448 ap:0 ep:1 wo:b oos:207647312 [>....................] sync'ed: 0.2% (202780/203060)M finish: 1:00:10 speed: 57,464 (57,464) K/sec
Assim que terminar este processo precisamos somente forçar os dois como primary da seguinte forma
drbdadm -- --overwrite-data-of-peer primary r1
O discos ainda sincronizando e forçados como primary.
cat /proc/drbd version: 8.3.7 (api:88/proto:86-91) srcversion: EE47D8BF18AC166BE219757 1: cs:SyncSource ro:Primary/Primary ds:UpToDate/Inconsistent C r---- ns:22204456 nr:0 dw:0 dr:22211888 al:0 bm:1356 lo:40 pe:1833 ua:1797 ap:0 ep:1 wo:b oos:185737536 [=>..................] sync'ed: 10.7% (181384/203060)M finish: 0:55:40 speed: 55,560 (47,940) K/sec
Agora vamos instalar o Apache e acertar a configuração básica dele, vamos primeiro configurar o nodo1 do Apache
Configuração do Apache no apache1
aptitude install apache2 apache2-utils -y
Vamos desabilitar o site default no nodo1 do Apache
a2dissite 000-default
Agora vamos criar um virtualHost para teste no nodo1 do Apache
vim /etc/apache2/sites-available/nodo1 <VirtualHost *:80> #Nome do do site ServerName apache1.douglasqsantos.com.br #Apelido para o site ServerAlias apache1.douglasqsantos.com.br #Localização dos arquivos do Site apache1 DocumentRoot "/var/www/website/frontend/" #Controle de acesso ao diretório Raiz do Apache <Directory "/var/www/website/frontend/"> Options -Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory> #Alias para o cgi-bin do site apache1 ScriptAlias /cgi-bin/ "/var/www/website/frontend/cgi-bin/" #Controle de acesso e execução do diretorio cgi-bin do site <Directory "/var/www/website/frontend/cgi-bin/"> AllowOverride All Options ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> #Vamos acertar o Formato do Log para que não seja gerado log dos acessos dos balancer e sim dos clientes. LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined #Agora criar uma regra para negar a geração de logs para o arquivo de checagem que o balancer vai utilizar. SetEnvIf Request_URI "^/.check\.txt$" dontlog #Localização dos logs de Erro do site. ErrorLog "/var/www/website/logs/apache1.douglasqsantos.com.br-error.log" #Negando os logs de checagem do balancer CustomLog "/var/www/website/logs/apache1.douglasqsantos.com.br-access.log" combined env=!dontlog #Para a segurança do servidor vamos tirar a assinatura do Apache ServerSignature Off #Tipos de log que o apache vai gerar LogLevel info </VirtualHost>
Agora vamos criar os diretório necessários para o Apache.
mkdir -p /var/www/website/frontend/cgi-bin/ mkdir -p /var/www/website/logs/
Agora vamos acertar as permissões de acesso ao site
chown -R www-data:www-data /var/www/website
Agora vamos criar o arquivo de checagem do balancer na raiz do site.
touch /var/www/website/frontend/.check.txt
Vamos criar um arquivo de index para identificarmos qual site estamos acessando
echo "<h1>apache1</h1>" > /var/www/website/frontend/index.html
Agora vamos habilitar o nosso site no Apache
a2ensite nodo1
Agora vamos reiniciar o apache do nodo1 do Apache.
/etc/init.d/apache2 restart
Configuração do Apache no apache2
aptitude install apache2 apache2-utils -y
Vamos desabilitar o site default no nodo1 do Apache
a2dissite 000-default
Agora vamos criar um virtualHost para teste no nodo1 do Apache
vim /etc/apache2/sites-available/nodo2 <VirtualHost *:80> #Nome do do site ServerName apache2.douglasqsantos.com.br #Apelido para o site ServerAlias apache2.douglasqsantos.com.br #Localização dos arquivos do Site apache1 DocumentRoot "/var/www/website/frontend/" #Controle de acesso ao diretório Raiz do Apache <Directory "/var/www/website/frontend/"> Options -Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory> #Alias para o cgi-bin do site apache1 ScriptAlias /cgi-bin/ "/var/www/website/frontend/cgi-bin/" #Controle de acesso e execução do diretorio cgi-bin do site <Directory "/var/www/website/frontend/cgi-bin/"> AllowOverride All Options ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> #Vamos acertar o Formato do Log para que não seja gerado log dos acessos dos balancer e sim dos clientes. LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined #Agora criar uma regra para negar a geração de logs para o arquivo de checagem que o balancer vai utilizar. SetEnvIf Request_URI "^/.check\.txt$" dontlog #Localização dos logs de Erro do site. ErrorLog "/var/www/website/logs/apache2.douglasqsantos.com.br-error.log" #Negando os logs de checagem do balancer CustomLog "/var/www/website/logs/apache2.douglasqsantos.com.br-access.log" combined env=!dontlog #Para a segurança do servidor vamos tirar a assinatura do Apache ServerSignature Off #Tipos de log que o apache vai gerar LogLevel info </VirtualHost>
Agora vamos criar os diretório necessários para o Apache.
mkdir -p /var/www/website/frontend/cgi-bin/ mkdir -p /var/www/website/logs/
Agora vamos acertar as permissões de acesso ao site
chown -R www-data:www-data /var/www/website
Agora vamos criar o arquivo de checagem do balancer na raiz do site.
touch /var/www/website/frontend/.check.txt
Vamos criar um arquivo de index para identificarmos qual site estamos acessando
echo "<h1>apache2</h1>" > /var/www/website/frontend/index.html
Agora vamos habilitar o nosso site no Apache
a2ensite nodo2
Agora vamos reiniciar o apache do nodo2 do Apache.
/etc/init.d/apache2 restart
Configuração do Balancer1
Vamos mandar atualizar os repositórios e fazer um upgrade do sistema
aptitude update && aptitude dist-upgrade -y
Agora vamos adicionar os repositórios de backports para obter o haproxy
vim /etc/apt/sources.list [...] #REPOSITORIO BACKPORT deb http://ftp.br.debian.org/debian wheezy-backports main contrib non-free deb-src http://ftp.br.debian.org/debian wheezy-backports main contrib non-free
Agora vamos atualizar os repositórios
aptitude update
Vamos instalar o haproxy nele.
apt-get install haproxy -y
Agora vamos fazer backup do arquivo de configuração do haproxy no nodo1 do balancer, neste arquivo temos alguns exeplos de configuração do haproxy.
cp /etc/haproxy/haproxy.cfg{,.bkp}
Vamos zerar o arquivo de configuração do haproxy
cat /dev/null > /etc/haproxy/haproxy.cfg
Agora vamos criar o novo arquivo de configuração para a nossa solução.
vim /etc/haproxy/haproxy.cfg global #definição de logs gerados pelo haproxy #endereço do servidor de log, categoria do syslog, prioridade log 127.0.0.1 local0 log 127.0.0.1 local1 notice #número máximo de conexões simultaneas para todos os clusters neste servidor, #se ultrapassar este valor o haproxy para de aceitar conexões, para todos os clusters maxconn 4096 #Habilita o debug, e desabilita o trabalho do haproxy em background, #para mostrar as mensagems de iniciliazação. #debug #Não mostra mensagem durante a inicialização do haproxy #quiet #usuário que o haproxy vai ser executado user haproxy #grupo que o haproxy vai ser executado group haproxy #O haproxy vai ser executado em segundo plano no sistema. daemon #Definido o tipo de proxy que sera utilizado defaults #utiliza a configuração de log da seção global. log global #Temos 3 modos de operação tcp trabalha como tcp padrão modo full-duplex, #http qualquer pedido que não é compatível com RFC serão rejeitadas #health este modo só vai responder "OK" para conexões de entrada e fechar a conexão. Nada será logado mode http #Ativa o log de solicitação HTTP de estado de sessão, e temporizadores. option httplog #Não gerar logs de conexões aonde nenhum dado foi transferido. option dontlognull #Número de tentativas para executar em um servidor após uma falha de conexão. retries 3 #Ativa a redistribuição da sessão em caso de falha de conexão. option redispatch #Tempo limite de verificação adicional, mas apenas depois que uma conexão já foi estabilecida timeout check 5000 #Tempo limite de inatividade máxima no lado do cliente. timeout client 50000 #Tempo limite de inatividade máxima no lado do servidor timeout server 50000 #Tempo máximo de espera para uma tentativa de conexão a um servidor para sucesso. timeout connect 2000 #Definição do ip e porta que vai responder o cluster listen clusterapache 192.168.25.30:80 #número máximo de conexões simultaneas, se ultrapassar este valor o clusterapache, #para de responder novas conexões. maxconn 1000 #Temos 3 modos de operação tcp trabalha como tcp padrão modo full-duplex, #http qualquer pedido que não é compatível com RFC serão rejeitadas #health este modo só vai responder "OK" para conexões de entrada e fechar a conexão. Nada será logado mode http #libera acesso a pagina de estatísticas do haproxy stats enable #usuário e senha da página de estatísticas do haproxy stats auth user1:senha #Quantidade de conexões simultâneas ao relatório de estdrão é 1maxconn 5 #algoritmo de balanceamento balance roundrobin #Modo analisador de URL padrão, com isso o haproxy vai procurar o cookie em 192.168.25.30/.check.txt cookie JSESSIONID prefix #Trabalha como um interruptor para o http, fechando a conexão, após cada transferência. option httpclose #Força o haproxy inspecionar todas as requisições de uma conexão option forwardfor #Definindo como que vai ser a checagem do serviço http método HEAD , uri /.check.txt, Versão HTTP/1.0 option httpchk HEAD /.check.txt HTTP/1.0 #Definição dos servidores apache, o nome apache1 ou apache2 é o que vai aparecer nos logs #10.101.0.* é o ip dos servidores pode ser ipv4 ou ipv6 #:80 é opcional, senão for definido vai ser redirecionado na mesma porta que o cliente solicitou ao haproxy #cookie A ou B é o valor do cookie enviado ao cliente. #Quem pode ter valores de cookies iguais é o servidor A por exemplo e o Backup. server apache1 192.168.25.42:80 cookie A check server apache2 192.168.25.43:80 cookie B check
Agora vamos configurar o haproxy para ser executado na inicialização do sistema.
sed -i "s/ENABLED=0/ENABLED=1/" /etc/default/haproxy
Agora vamos ajustar o kernel para que ele possa adicionar o ip que foi definido no haproxy para o clusterapache.
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
Agora vamos carregar a nova variável do kernel.
sysctl -p
Agora vamos instalar o keepalived no nodo1 do balancer
apt-get install keepalived -y
Agora vamos criar o arquivo de configuração para o keepalived, podemos obter exemplos da configuração do keepalived em /usr/share/doc/keepalived/samples
vim /etc/keepalived/keepalived.conf #Configuração global do keepalived global_defs { #Quem vai receber o email de notificação do keepalived notification_email { douglas@douglasqsantos.com.br } #Em nome de quem vai ser enviado o email notification_email_from douglas@douglasqsantos.com.br #Qual o servidor de email que vai enviar a mensagem smtp_server smtp.douglasqsantos.com.br #tempo de espera máximo smtp_connect_timeout 30 #identificação que vai aparecer no email sobre esta notificação router_id clusterapache } #Script que vai ser executado em caso do outro nodo estar utilizando o ip virtual vrrp_script chk_haproxy { #O comando que vai ser executado script "killall -0 haproxy" #Intervalo de checagem interval 2 #Peso do script weight 2 } # vrrp_instance clusterapache { #Interface que vai receber o ip virtual interface eth0 #Tipo da instancia, pode ser master ou backup state MASTER #identificação desta instancia virtual_router_id 51 #prioridade 101 no servidor master, 100 no backup priority 101 #Ip virtual que vai ser compartilhado virtual_ipaddress { 192.168.25.30/24 } #Ação que vai ser tomada caso tenhamos conflito no uso do ip virtual track_script { chk_haproxy } }
Agora vamos iniciar o haproxy e o keepalived
/etc/init.d/haproxy restart && /etc/init.d/keepalived restart
Agora vamos ver se o haproxy subiu o ip 192.168.25.30
ip address list eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:c7:b7:94 brd ff:ff:ff:ff:ff:ff inet 192.168.25.40/24 brd 10.101.0.255 scope global eth0 inet 192.168.25.30/24 scope global secondary eth0 inet6 fe80::a00:27ff:fec7:b794/64 scope link valid_lft forever preferred_lft forever
Como pode ser notado o nosso nodo1 do balancer já está ok.
Agora podemos testar o nosso balancer em http://192.168.25.30, cada vez que mandarmos atualizar ele vai para um servidor diferente.
OBS: No Google Chrome ele não fica atualizando pois a conexão não foi fechado com isso ele vai continuar no mesmo server, somente vai ser mudado o servidor quando a conexão for fechada.
Vamos abrir algumas requisições simultâneas para o nosso servidor.
Vamos instalar o apache-utils
aptitude install apache2-utils -y
Agora vamos mandar algumas requisições para os servidores
ab -n 3000 -c 100 http://192.168.25.30/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.25.30 (be patient) Completed 300 requests Completed 600 requests Completed 900 requests Completed 1200 requests Completed 1500 requests Completed 1800 requests Completed 2100 requests Completed 2400 requests Completed 2700 requests Completed 3000 requests Finished 3000 requests Server Software: Apache/2.2.16 Server Hostname: 192.168.25.30 Server Port: 80 Document Path: / Document Length: 17 bytes Concurrency Level: 100 Time taken for tests: 2.156 seconds Complete requests: 3000 Failed requests: 0 Write errors: 0 Total transferred: 876000 bytes HTML transferred: 51000 bytes Requests per second: 1391.16 [#/sec] (mean) Time per request: 71.882 [ms] (mean) Time per request: 0.719 [ms] (mean, across all concurrent requests) Transfer rate: 396.70 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.2 0 2 Processing: 1 2 0.4 2 5 Waiting: 0 1 0.4 1 5 Total: 1 2 0.4 2 5 Percentage of the requests served within a certain time (ms) 50% 2 66% 2 75% 2 80% 2 90% 3 95% 3 98% 3 99% 3 100% 5 (longest request)
Agora podemos conferir as estatísticas no haproxy em http://192.168.25.30/haproxy?stats aqui vamos precisar informar o usuário: user01 e a senha: senha como foi definido no haproxy.
A página vai ser similar a está.
Configuração do Balancer2
Vamos mandar atualizar os repositórios e fazer um upgrade do sistema
aptitude update && aptitude dist-upgrade -y
Agora vamos adicionar os repositórios de backports para obter o haproxy
vim /etc/apt/sources.list [...] #REPOSITORIO BACKPORT deb http://ftp.br.debian.org/debian wheezy-backports main contrib non-free deb-src http://ftp.br.debian.org/debian wheezy-backports main contrib non-free
Agora vamos atualizar os repositórios
aptitude update
Vamos instalar o haproxy nele.
apt-get install haproxy -y
Agora vamos fazer backup do arquivo de configuração do haproxy no nodo1 do balancer, neste arquivo temos alguns exeplos de configuração do haproxy.
cp /etc/haproxy/haproxy.cfg{,.bkp}
Vamos zerar o arquivo de configuração do haproxy
cat /dev/null > /etc/haproxy/haproxy.cfg
Agora vamos criar o novo arquivo de configuração para a nossa solução.
vim /etc/haproxy/haproxy.cfg global #definição de logs gerados pelo haproxy #endereço do servidor de log, categoria do syslog, prioridade log 127.0.0.1 local0 log 127.0.0.1 local1 notice #número máximo de conexões simultaneas para todos os clusters neste servidor, #se ultrapassar este valor o haproxy para de aceitar conexões, para todos os clusters maxconn 4096 #Habilita o debug, e desabilita o trabalho do haproxy em background, #para mostrar as mensagems de iniciliazação. #debug #Não mostra mensagem durante a inicialização do haproxy #quiet #usuário que o haproxy vai ser executado user haproxy #grupo que o haproxy vai ser executado group haproxy #O haproxy vai ser executado em segundo plano no sistema. daemon #Definido o tipo de proxy que sera utilizado defaults #utiliza a configuração de log da seção global. log global #Temos 3 modos de operação tcp trabalha como tcp padrão modo full-duplex, #http qualquer pedido que não é compatível com RFC serão rejeitadas #health este modo só vai responder "OK" para conexões de entrada e fechar a conexão. Nada será logado mode http #Ativa o log de solicitação HTTP de estado de sessão, e temporizadores. option httplog #Não gerar logs de conexões aonde nenhum dado foi transferido. option dontlognull #Número de tentativas para executar em um servidor após uma falha de conexão. retries 3 #Ativa a redistribuição da sessão em caso de falha de conexão. option redispatch #Tempo limite de verificação adicional, mas apenas depois que uma conexão já foi estabilecida timeout check 5000 #Tempo limite de inatividade máxima no lado do cliente. timeout client 50000 #Tempo limite de inatividade máxima no lado do servidor timeout server 50000 #Tempo máximo de espera para uma tentativa de conexão a um servidor para sucesso. timeout connect 2000 #Definição do ip e porta que vai responder o cluster listen clusterapache 192.168.25.30:80 #número máximo de conexões simultaneas, se ultrapassar este valor o clusterapache, #para de responder novas conexões. maxconn 1000 #Temos 3 modos de operação tcp trabalha como tcp padrão modo full-duplex, #http qualquer pedido que não é compatível com RFC serão rejeitadas #health este modo só vai responder "OK" para conexões de entrada e fechar a conexão. Nada será logado mode http #libera acesso a pagina de estatísticas do haproxy stats enable #usuário e senha da página de estatísticas do haproxy stats auth user1:senha #Quantidade de conexões simultâneas ao relatório de estdrão é 1maxconn 5 #algoritmo de balanceamento balance roundrobin #Modo analisador de URL padrão, com isso o haproxy vai procurar o cookie em 192.168.25.30/.check.txt cookie JSESSIONID prefix #Trabalha como um interruptor para o http, fechando a conexão, após cada transferência. option httpclose #Força o haproxy inspecionar todas as requisições de uma conexão option forwardfor #Definindo como que vai ser a checagem do serviço http método HEAD , uri /.check.txt, Versão HTTP/1.0 option httpchk HEAD /.check.txt HTTP/1.0 #Definição dos servidores apache, o nome apache1 ou apache2 é o que vai aparecer nos logs #10.101.0.* é o ip dos servidores pode ser ipv4 ou ipv6 #:80 é opcional, senão for definido vai ser redirecionado na mesma porta que o cliente solicitou ao haproxy #cookie A ou B é o valor do cookie enviado ao cliente. #Quem pode ter valores de cookies iguais é o servidor A por exemplo e o Backup. server apache1 192.168.25.42:80 cookie A check server apache2 192.168.25.43:80 cookie B check
Agora vamos configurar o haproxy para ser executado na inicialização do sistema.
sed -i "s/ENABLED=0/ENABLED=1/" /etc/default/haproxy
Agora vamos ajustar o kernel para que ele possa adicionar o ip que foi definido no haproxy para o clusterapache.
echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf
Agora vamos carregar a nova variável do kernel.
sysctl -p
Agora vamos instalar o keepalived no nodo1 do balancer
apt-get install keepalived -y
Agora vamos criar o arquivo de configuração para o keepalived, podemos obter exemplos da configuração do keepalived em /usr/share/doc/keepalived/samples
vim /etc/keepalived/keepalived.conf #Configuração global do keepalived global_defs { #Quem vai receber o email de notificação do keepalived notification_email { douglas@douglasqsantos.com.br } #Em nome de quem vai ser enviado o email notification_email_from douglas@douglasqsantos.com.br #Qual o servidor de email que vai enviar a mensagem smtp_server smtp.douglasqsantos.com.br #tempo de espera máximo smtp_connect_timeout 30 #identificação que vai aparecer no email sobre esta notificação router_id clusterapache } #Script que vai ser executado em caso do outro nodo estar utilizando o ip virtual vrrp_script chk_haproxy { #O comando que vai ser executado script "killall -0 haproxy" #Intervalo de checagem interval 2 #Peso do script weight 2 } # vrrp_instance clusterapache { #Interface que vai receber o ip virtual interface eth0 #Tipo da instancia, pode ser master ou backup state MASTER #identificação desta instancia virtual_router_id 51 #prioridade 101 no servidor master, 100 no backup priority 101 #Ip virtual que vai ser compartilhado virtual_ipaddress { 192.168.25.30/24 } #Ação que vai ser tomada caso tenhamos conflito no uso do ip virtual track_script { chk_haproxy } }
Agora vamos iniciar o haproxy e o keepalived
/etc/init.d/haproxy restart && /etc/init.d/keepalived restart
Agora vamos ver se o haproxy subiu o ip 192.168.25.30, como pode ser notado ele não está aqui, pois está sendo utilizado no nodo1.
ip address list eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:c7:b7:94 brd ff:ff:ff:ff:ff:ff inet 192.168.25.41/24 brd 10.101.0.255 scope global eth0 inet6 fe80::a00:27ff:fec7:b794/64 scope link valid_lft forever preferred_lft forever
Como pode ser notado o nosso nodo2 do balancer já está ok.
Agora vamos desligar o nodo1 do balancer, para verificar se o ip 192.168.25.30 vai para o nodo2 balancer
No nodo1 do balancer
init 0
Agora vamos conferir no nodo2 do balancer se ele assumiu o ip
ip address list eth0 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:58:cf:cf brd ff:ff:ff:ff:ff:ff inet 192.168.25.41/24 brd 10.101.0.255 scope global eth0 inet 192.168.25.30/24 scope global secondary eth0 inet6 fe80::a00:27ff:fe58:cfcf/64 scope link valid_lft forever preferred_lft forever
Agora vamos testar o nosso cluster em http://192.168.25.30, ele ainda está funcionando como se nada tivesse acontecido.
Vamos instalar o apache-utils
aptitude install apache2-utils -y
Agora vamos mandar algumas requisições para os servidores
ab -n 3000 -c 100 http://192.168.25.30/ This is ApacheBench, Version 2.3 <$Revision: 655654 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking 192.168.25.30 (be patient) Completed 300 requests Completed 600 requests Completed 900 requests Completed 1200 requests Completed 1500 requests Completed 1800 requests Completed 2100 requests Completed 2400 requests Completed 2700 requests Completed 3000 requests Finished 3000 requests Server Software: Apache/2.2.16 Server Hostname: 192.168.25.30 Server Port: 80 Document Path: / Document Length: 17 bytes Concurrency Level: 100 Time taken for tests: 2.156 seconds Complete requests: 3000 Failed requests: 0 Write errors: 0 Total transferred: 876000 bytes HTML transferred: 51000 bytes Requests per second: 1391.16 [#/sec] (mean) Time per request: 71.882 [ms] (mean) Time per request: 0.719 [ms] (mean, across all concurrent requests) Transfer rate: 396.70 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 0.2 0 2 Processing: 1 2 0.4 2 5 Waiting: 0 1 0.4 1 5 Total: 1 2 0.4 2 5 Percentage of the requests served within a certain time (ms) 50% 2 66% 2 75% 2 80% 2 90% 3 95% 3 98% 3 99% 3 100% 5 (longest request)
Agora podemos conferir as estatísticas no haproxy em http://192.168.25.30/haproxy?stats aqui vamos precisar informar o usuário: user01 e a senha: senha como foi definido no haproxy.
A página vai ser similar a está.
Como pode ser notado o nosso balancer está ok.
Agora vamos acertar o apache para ele buscar os dados do site no drbd.
Vamos configurar no nodo1 do apache.
Vamos mover a configuração do site para o ocfs2 como vai ser a mesma para os dois apache.
mv /var/www/ /ocfs2
Agora vamos criar um link simbolico em /var para não precisarmos alterar muita coisa.
ln -sf /ocfs2/www/ /var/www
Agora vamos acertar a permissão do Link
chown -R www-data:www-data /var/www
Agora no nodo2 do apache somente precisamos acertar o link, vamos fazer isso então.
Vamos remover o /var/www
rm -rf /var/www
Agora vamos criar o link
ln -sf /ocfs2/www /var/www
Agora vamos acertar as permissões
chown -R www-data:www-data /var/www
Agora vamos somente acertar a configuração do virtualhost do nodo1 do apache, levando em consideração que o cluster que estamos montado é para o www.
sed -i "s/apache1/www/g" /etc/apache2/sites-available/nodo1
Agora vamos somente acertar a configuração do virtualhost do nodo2 do apache, levando em consideração que o cluster que estamos montado é para o www.
sed -i "s/apache2/www/g" /etc/apache2/sites-available/nodo2
Agora só precisamos configurar o servidor DNS para responder o www.douglasqsantos.com.br em 192.168.25.30 e temos o nosso cluster com balanceamento funcionando.