Всем интересующимся программированием на java: проводятся курсы, доп. информация по ссылке. Автор курса мой знакомый - Лигай Виталий, гуру программирования, как я считаю.
четверг, 26 февраля 2015 г.
понедельник, 23 февраля 2015 г.
Отказоустойчивый, масштабируемый кластер приложения с балансировкой нагрузки, часть 1
Заголовок броский, я бы даже сказал, слегка желтоват (желтая IT пресса - более унылой вещи трудно представить). Но, тем не менее, это правда, хотя, как известно, все скрывается в деталях. В данном случае детали - это, собственно, возможность самого ПО делить нагрузку или обеспечивать отказоустойчивость. Но хватит лирики, перейдем к постановке задачи.
Мне нужен почтовый релей, забегая вперед, скажу, что с таким же успехом это может быть любое другое приложение, например, web сервер. Могу показаться банальным занудой, но хочу еще раз повторить: каждый сервис требует отдельного анализа, и не факт, что желаемое удастся реализовать. Далее отразим заголовок статьи: релей должен быть отказоустойчивым и иметь возможность масштабирования. Читатель статьи может возразить, что для почтового релея все вышесказанное можно реализовать, добавив несколько MX записей в доменной зоне. К сожалению, я ограничен одним, уже существующим ip адресом релея, таким образом, вариант с MX не годится. Подведем итог: нужно несколько почтовых релеев, обеспечивающих отказоустойчивость сервиса, разделяющих нагрузку и использующих один ip адрес.
В плане выбора ПО все просто и традиционно - я буду использовать дистрибутив oracle linux 7 (почти аналогичны ему centos 7 или rhel 7), в качестве smtp сервиса - postfix. Для балансировки будет использоваться решение LVS, поскольку ее частью является подсистема linux ядра - ipvs, быстрый и надежный вариант балансировки трафика на 4-м уровне сетевой модели OSI.
Оставшиеся вводные данные:
Используемая сеть: 192.168.3.0/24
IP серверов по порядку: 192.168.3.[101-105]
Обычно в стандартной практике делают отдельный кластер балансировки и группу серверов приложения, к примеру, рекомендуемое решение от Red Hat. Особенность данной реализации заключается в том, что каждый сервер является сервером приложения и балансировщиком трафика одновременно. Один из балансировщиков является активным, остальные резервные. В моем случае используются четыре релея, расположенные по два в двух географически разнесенных ЦОДах. Ниже приведен рисунок, иллюстрирующий прохождение трафика в кластере, к которому мы будем возвращаться при описании процесса работы.
Посмотрите, что происходит: входящее соединение попадает на активную ноду (кластерный mac не используется), активная нода в соответствии с правилами балансировки обрабатывает соединение самостоятельно или передает его на одну из соседних нод, т.е. в обработке принимают участие все ноды кластера, затем нода отвечает клиенту. Таким образом весь входящий трафик проходит через одну активную ноду, а соответствующий исходящий трафик отправляется напрямую клиенту.
Перейдем к установке и настройке. Все написанное ниже справедливо для всех нод кластера, если не указано обратное. Установку и настройку postfix рассматривать не будем, убедитесь только что postfix использует все доступные сетевые интерфейсы:
# grep "inet_interfaces" /etc/postfix/main.cf | grep -v "^#"
inet_interfaces = all
Отключим firewalld, его можно будет настроить позднее, после того как будете твердо уверены, что кластер функционирует должным образом:
# systemctl disable firewalld.service
# systemctl stop firewalld.service
Установим keepalived, ipvsadm и модуль python ipaddr, модуль нужен для скрипта:
# yum -y install keepalived ipvsadm python-ipaddr
Разберем конфигурационный файл keepalived:
# Секция определения общих параметров
global_defs {
notification_email {
# Список почтовых адресов, по которым будут приходить оповещения о
# недоступности нод или сервисов
unix_adm@domain.ru
}
# Email от которого будет рассылаться почта
notification_email_from keepalived@domain.ru
# Адрес smtp сервера и время, в течение которого будет производится попытка
# отправки почты
smtp_server 192.168.3.1
smtp_connect_timeout 30
# Идентификатор сервера
router_id server01.domain.ru
}
# Секция описания экземпляров VRRP (перемещаемые IP)
vrrp_instance mail_relay {
# Начальное состояние при запуске, на остальных серверах должно быть BACKUP
state MASTER
# Интерфейс, на котором будет работать экземпляр VRRP
interface eth0
# Идентификатор экземпляра VRRP, должен быть идентичен на всех нодах.
virtual_router_id 11
# Приоритет при выборе MASTER'а, нода с большим приоритетом становится
# активной.
priority 100
# Интервал уведомлений о состоянии, которые рассылает MASTER нода.
# При отсутствии уведомлений произойдут перевыборы.
advert_int 2
# Секция аутентификации, пароль должен быть идентичен на всех нодах,
# используется первые 8 символов.
authentication {
auth_type PASS
auth_pass mrelay
}
# Список адресов, которые будут добавлены на ноду при выборе ее MASTER
virtual_ipaddress {
192.168.3.100
}
# Произвести миграцию состояния MASTER при появлении ноды с более высоким
# приоритетом. В случае установки опции в nopreempt при появлении ноды с
# более высоким приоритетом MASTER нодой останется прежняя нода.
preempt
# Скрипт, который надо выполнить при событии, когда нода становится MASTER
notify_master "/etc/keepalived/bypass_ipvs.py -r 192.168.3.100"
# Скрипт, который надо выполнить при событии, когда нода становится SLAVE
notify_backup "/etc/keepalived/bypass_ipvs.py -a 192.168.3.100"
# Скрипт, который надо выполнить при событии ошибки смены роли ноды
notify_fault "/etc/keepalived/bypass_ipvs.py -a 192.168.3.100"
}
Что выполняет скрипт: при установке состояния BACKUP на ноде он добавляет правило в iptables, которое заменяет (NAT) общий IP в пакетах входящего трафика на локальный IP ноды, и наоборот - для ответного трафика:
-A PREROUTING -t nat -d 192.168.3.100/32 -p tcp -j REDIRECT
Таким образом реализуется совместная обработка трафика всеми нодами, посмотрите еще раз рисунок вверху. В случае, когда нода становится MASTER, скрипт убирает правило натирования, поскольку общий IP принадлежит этой ноде. Скачать скрипт можно здесь.
Несколько замечаний:
- state - если вы уверены в качестве сети, можно на всех нодах кластера выставить BACKUP, в этом случае мастер определится в результате выборов.
- priority - в случае равных приоритетов побеждает нода с большим IP.
- nopreempt - при данной опции state должен быть установлен в BACKUP.
- если установить опции state BACKUP, одинаковый priority и nopreempt на все ноды, мы получим идентичный конфигурационный файл, что очень удобно в системах централизованного сопровождения серверов. Но вместе с тем шансы возникновения ситуации "split brain" в результате каких либо проблем также увеличиваются.
# Секция конфигурации политики балансировки (LVS) и описание серверов приложения
virtual_server 192.168.3.100 25 {
# Период опроса серверов приложения
delay_loop 2
# Планировщик балансировки, wlc - Weighted Least-Connections Scheduling.
lb_algo wlc
# Метод передачи пакетов на сервера приложений, dr - Direct Routing
lb_kind DR
protocol TCP
# Секция описание сервера приложения 192.168.3.101
real_server 192.168.3.101 25 {
# Вес сервера
weight 1
# Секция проверки доступности приложения, в данном случае выполняется
# проверка доступности smtp приложения.
SMTP_CHECK {
connect_timeout 5
retry 3
# Имя в команде smtp helo
helo_name smtpchecker.domain.ru
}
}
# Далее однотипные описания серверов для 192.168.3.102 и т.д.
}
Еще несколько замечаний:
- lb_algo wlc - распределяет большее количество запросов серверам с наименьшим количеством активных подключений в соответствии с их весом.
- lb_kind DR - маршрутизация пакета, в этом случае пакет с активной ноды передается на резервную следующим образом: производится замена MAC адреса в поле destination MAC в ethernet заголовке пакета с MAC адреса активной ноды на MAC адрес сервера приложения. IP адрес остается без изменения. В свою очередь сервер приложения (нода в состоянии BACKUP) получив пакет, натирует общий IP адрес в поле destination IP в свой собственный.
- со всеми вариантами балансировки, передачи пакетов, методах проверки доступности приложения можно ознакомиться на сайте проекта LVS.
Запустим keepalived и проверим что получилось:
# systemctl enable keepalived.service
# systemctl start keepalived.service
$ telnet 192.168.3.100 25
Trying 192.168.3.100...
Connected to 192.168.3.100.
Escape character is '^]'.
220 server01.domain.ru ESMTP Postfix
quit
221 2.0.0 Bye
Connection closed by foreign host.
[valentine@server ~]$ telnet 192.168.3.100 25
Trying 192.168.3.100...
Connected to 192.168.3.100.
Escape character is '^]'.
220 server02.domain.ru ESMTP Postfix
quit
221 2.0.0 Bye
Connection closed by foreign host.
Посмотреть логи keepalived:
# journalctl -u keepalived.service
Посмотреть, на какой ноде находится общий IP, привычная команда ifconfig его не показывает:
# ip addr show
...
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 52:54:00:0d:5a:1a brd ff:ff:ff:ff:ff:ff
inet 192.168.3.101/24 brd 192.168.3.255 scope global dynamic eth0
valid_lft 70403sec preferred_lft 70403sec
inet 192.168.3.100/32 scope global eth0
...
Или более современный вариант:
# nmcli device show eth0
...
IP4.ADDRESS[1]: ip = 192.168.3.101/24, gw = 192.168.3.1
IP4.ADDRESS[2]: ip = 192.168.3.100/32, gw = 192.168.3.1
...
Посмотреть статистику балансировки:
# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.3.100:25 wlc
-> 192.168.3.101:25 Route 1 2 14
-> 192.168.3.102:25 Route 1 3 9
...
Посмотреть текущие соединения:
# ipvsadm -Lnc
IPVS connection entries
pro expire state source virtual destination
TCP 13:20 ESTABLISHED 192.168.3.3:59527 192.168.3.100:25 192.168.3.102:25
...
Если в сети несколько vrrp экземпляров, можно проверить номера идентификаторов
# tcpdump -nnn ip proto 112
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
21:11:36.244824 IP 192.168.3.101 > 224.0.0.18: VRRPv2, Advertisement, vrid 11, prio 100, authtype simple, intvl 1s, length 20
Удачных внедрений!
Upd: продолжение, для тех кому мало будет 4 ноды.
воскресенье, 22 февраля 2015 г.
Настройка соединения мост для использования в Virtual Machine Manager
Коллеги, читатели, сегодня мне понадобилось провести эксперимент с несколькими виртуальными машинами на домашнем PC. Для эксперимента надо было пустить машины напрямую в локальную сеть. Сделать это можно путем создания сетевого моста (бридж), в котором будут находится интерфейсы виртуальных машин и интерфейс гипервизора, в литературе этот вариант настройки также называется "shared physical device"
Несмотря на то, что, начиная с Fedora 20 (у меня Fedora 21) NetworkManager поддерживает создание соединений типа мост, выполнять будем по старинке (я не всегда понимаю логику работы NetworkManager, и собственно, попробовав с наскоку настроить, я получил неудовлетворительный результат).
Создайте конфигурационный файл сетевого моста:
# cat /etc/sysconfig/network-scripts/ifcfg-bridge0
DEVICE=bridge0
ONBOOT=yes
TYPE=Bridge
BOOTPROTO=dhcp
NM_CONTROLLED=no
DELAY=0
где bridge0 это имя моста.
Соответствующая конфигурация сетевого интерфейса гипервизора:
# cat /etc/sysconfig/network-scripts/ifcfg-eno1
TYPE=Ethernet
ONBOOT=yes
HWADDR=91:DE:80:B4:5F:0C
DEVICE=eno1
BOOTPROTO=none
NM_CONTROLLED=no
BRIDGE=bridge0
Удалите конфигурацию NetworkManadger, относящуюся к физическому интерфейсу. Далее можете перегрузиться или перезапустить network.service. Перейдем к настройке в Virtual Machine Manager. Зайдите в параметры оборудования виртуальной машины, выберите "Указать имя общего устройства" и соответственно укажите имя сетевого моста, как на рисунке ниже
Подписаться на:
Сообщения (Atom)