Установка и настройка отказоустойчивого балансировщика нагрузки на Debian(ubuntu) на основе Keepalived для бэкэндов php-fpm.
1.Конфигурация.
Операционная система: debian 8 minimal(net install) с доступом по ssh.
Server1: lb1.domain.local 10.4.1.181 – основной loadbalancer(MASTER)
Server2: lb.domain.local 10.4.1.182– резервный loadbalancer(BACKUP) и т.д. На обоих серверах по 2 сети, одна из которых смотрит в инет и будет иметь у активного балансера ip 190 (eth1).
VIP(virtual IP) – 10.4.1.190 — плавающий/расшаренный между балансировщиками нагрузки виртуальный IP-адрес,на который прописаны сайты в DNS. Можно использовать больше балансировщиков, для большей отказоустойчивости, например 4. Просто будем менять все(приоритет у серверов)
Кластер из для обработки web-приложений – 2 ноды, которые будут полностью дублировать друг-друга.
Web-server-1: nginx+php-fpm+gluserfs+mysql(with replication – с репликацией). ip 10.4.1.151
Web-server-2: nginx+php-fpm+gluserfs+mysql(with replication – с репликацией). ip 10.4.1.152
Что мы получим в итоге. По обращение по ip 10.4.1.190 мы всегда будем иметь рабочий сайт(если не упадут 2 машины ))) ), так же при падении одной из машин,или падению nginx’a будем получать уведомление по e-mail. В общем, получим отказоустойчивое решение, что немаловажно в наше время в ввиду повсеместного перевода всех бизнес-процессов в сеть и соответсвенно простой сервиса – потеря прибыли(убыток).
2.Установка и настройка Keepalived на балансерах
(в зависимостях подтянет ipvsadm-утилиту для администрирования ipvs (ip virtul server)). Саму балансировку настроим в самом конце, после всех манипуляций со всеми нодами. так же установим sendmail для отправки оповещений.
sudo su aptitude install keepalived sendmail -y
Включаем маршрутизацию пакетов на обоих балансерах
# nano /etc/sysctl.conf
net.ipv4.ip_forward = 1 net.ipv4.ip_nonlocal_bind = 1
Проверяем
sysctl -p
Видим:
net.ipv4.ip_forward = 1
net.ipv4.ip_nonlocal_bind = 1
Двигаемся далее – редактируем lb1(1-ый балансировщик);
nano /etc/keepalived/keepalived.conf
! this is who emails will go to on alerts
notification_email {
a.v.galushko86@gmail.com
! add a few more email addresses here if you would like
}
notification_email_from servers@domain.com
! I use the local machine to relay mail
smtp_server 1.1.1.1
smtp_connect_timeout 30
! each load balancer should have a different ID
! this will be used in SMTP alerts, so you should make
! each router easily identifiable
lvs_id LVS_EXAMPLE_01
}
vrrp_script chk_http_port {
script "/usr/bin/killall -0 nginx"
interval 2
weight 2
}
vrrp_instance lb1 {
interface eth0
state MASTER
virtual_router_id 190 # должен быть одинаковым у кластера keepalived
priority 150
! send an alert when this instance changes state from MASTER to BACKUP
smtp_alert
authentication {
auth_type PASS
auth_pass cbrt32456
}
track_script {
chk_http_port
}
virtual_ipaddress {
10.1.9.190/32 dev eth0
}
}
Здесь мы настроили сервис – наш сервер-1 будет главным – state master, вес ему поставили 101(далее другим ставим меньше на один), обратите внимание на virtaul_router_id – у нашей связки он должен быть одним, будет опрелять кластер из наших серверов ( в данном случае ставим 52 на всех), так же обратите внимание на auth_pass – пароль для нашего кластера. virtual_ipaddress – виртуальный адресс нашего кластера keepalived.
Виртуальный ip мы повешаем на первую(eth0) сетевую карту, можно это сделать и на вторую(eth1) – как хотите, это не принципиально.
Запускаем keepalived
sudo /etc/init.d/keepalived start
Проверяем его
ip addr show | grep 190
Видим это
inet 10.1.9.190/32 scope global eth0
Далее на втором серваке – lb2 (server балансировщик 2);
nano /etc/keepalived/keepalived.conf
vrrp_script chk_http_port {
script "/usr/bin/killall -0 nginx"
interval 2
weight 2
}
vrrp_instance VI_1 {
interface eth0
state BACKUP
virtual_router_id 190 # одиноаковый id для кластера
priority 100
authentication {
auth_type PASS
auth_pass cbrt2456
}
track_script {
chk_http_port
}
virtual_ipaddress {
10.4.1.190/32 dev eth0
}
}Здесь все аналогично первому, только роль backup и вес поменьше. Всё ок.
Запускаем keepaliver
sudo /etc/init.d/keepalived start
Проверяем его
ip addr show | grep 190
Видим это(если первый сервак выключить или остановить keepalived на 1 серваке)
inet 10.1.9.190/32 scope global eth0
Небольшое отступление. На самом деле настроек keepalived.conf очень много, ниже я приведу конфиг, в котором они описаны( на англ) для ознакомления
! This is a comment
! Configuration File for keepalived
global_defs {
! this is who emails will go to on alerts
notification_email {
admins@example.com
fakepager@example.com
! add a few more email addresses here if you would like
}
notification_email_from admins@example.com
! I use the local machine to relay mail
smtp_server 127.0.0.1
smtp_connect_timeout 30
! each load balancer should have a different ID
! this will be used in SMTP alerts, so you should make
! each router easily identifiable
lvs_id LVS_EXAMPLE_01
}
! vrrp_sync_groups make sure that several router instances
! stay together on a failure - a good example of this is
! that the external interface on one router fails and the backup server
! takes over, you want the internal interface on the failed server
! to failover as well, otherwise nothing will work.
! you can have as many vrrp_sync_group blocks as you want.
vrrp_sync_group VG1 {
group {
VI_1
VI_GATEWAY
}
}
! each interface needs at least one vrrp_instance
! each vrrp_instance is a group of VIPs that are logically grouped
! together
! you can have as many vrrp_instaces as you want
vrrp_instance VI_1 {
state MASTER
interface eth0
lvs_sync_daemon_inteface eth0
! each virtual router id must be unique per instance name!
virtual_router_id 51
! MASTER and BACKUP state are determined by the priority
! even if you specify MASTER as the state, the state will
! be voted on by priority (so if your state is MASTER but your
! priority is lower than the router with BACKUP, you will lose
! the MASTER state)
! I make it a habit to set priorities at least 50 points apart
! note that a lower number is lesser priority - lower gets less vote
priority 150
! how often should we vote, in seconds?
advert_int 1
! send an alert when this instance changes state from MASTER to BACKUP
smtp_alert
! this authentication is for syncing between failover servers
! keepalived supports PASS, which is simple password
! authentication
! or AH, which is the IPSec authentication header.
! I don't use AH
! yet as many people have reported problems with it
authentication {
auth_type PASS
auth_pass example
}
! these are the IP addresses that keepalived will setup on this
! machine. Later in the config we will specify which real
! servers are behind these IPs
! without this block, keepalived will not setup and takedown the
! any IP addresses
virtual_ipaddress {
192.168.1.11
! and more if you want them
}
}
! now I setup the instance that the real servers will use as a default
! gateway
! most of the config is the same as above, but on a different interface
vrrp_instance VI_GATEWAY {
state MASTER
interface eth1
lvs_sync_daemon_inteface eth1
virtual_router_id 52
priority 150
advert_int 1
smtp_alert
authentication {
auth_type PASS
auth_pass example
}
virtual_ipaddress {
10.20.40.1
}
}
! now we setup more information about are virtual server
! we are just setting up one for now, listening on port 22 for ssh
! requests.
! notice we do not setup a virtual_server block for the 10.20.40.1
! address in the VI_GATEWAY instance. That's because we are doing NAT
! on that IP, and nothing else.
virtual_server 192.168.1.11 22 {
delay_loop 6
! use round-robin as a load balancing algorithm
lb_algo rr
! we are doing NAT
lb_kind NAT
nat_mask 255.255.255.0
protocol TCP
! there can be as many real_server blocks as you need
real_server 10.20.40.10 22 {
! if we used weighted round-robin or a similar lb algo,
! we include the weight of this server
weight 1
! here is a health checker for this server.
! we could use a custom script here (see the keepalived docs)
! but we will just make sure we can do a vanilla tcp connect()
! on port 22
! if it fails, we will pull this realserver out of the pool
! and send email about the removal
TCP_CHECK {
connect_timeout 3
connect_port 22
}
}
}
! that's allВот такой вот конфиг мануал.
3.Настройка проксирования и балансировки на nginx на lb1 и lb2.
Теперь настроим наши сервера на, чтобы они слушали другие сервера в нашей сети с php+mysql на борту и распределяли между ними нагрузку, и в случае выхода одного из серверов переключались на другой.
Установим nginx
sudo apt-get install nginx
Правим конфиги на обоих серваках
sudo nano /etc/nginx
upstream backend {
server 10.4.1.151:80;
server 10.4.1.152:80;
}
server {
listen 80;
server_name example.org;
location ~* \.()$ {
root /var/www/example.org; }
location / {
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 16 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
proxy_connect_timeout 30s;
proxy_pass https://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}Как мы видим на наш nginx будут слушать и распределять нагрузку между нашими 2 серверами с ip 10.4.1.151 и 10.4.1.152. На нах будет крутиться php-fpm+nginx+mysql+gluster-fs. В принципе вы можете иметь сколько угодно реплицируемых серверов.О их настройке будет написано ниже.
Данная конфигурация работает так:
1. Как только первая Master нода перестает работать, например: /etc/init.d/network stop
! Происходит переключение на вторую ноду BackUp, при этом теряется 2-3 пакета, it’s okay, не так страшен зверь как то с чем его едят :)
2. После того как 1-ая нода Master оживает, /etc/init.d/network start, обратного автопереключения не происходит :( т.е. иду на вторую ноду BackUp жму /etc/init.d/network stop и ппц, пинги до моего внешго IP перестают идти, до того момента пока я руками на первой ноде Master не сделаю еще дополнительно /etc/init.d/network restart
Мне показалось что это не очень живучая конфигурация, живущая лишь только словах и на вере в лучшее.
Может быть у кого-то будут соображения на этот счет, как оптимизировать данную конфигурацию, чтобы её можно было назвать “отказоустойчивой”? :)