вторник, 16 июня 2015 г.



Балансировка нагрузки Microsoft Exchange 2013 с помощью Linux Virtual Server. Часть 1.

В данной статье я хочу поделиться с вами решением, которое получилось успешно внедрить в нескольких организациях Microsoft Exchange 2013 для обеспечения отказоустойчивости и балансировки нагрузки CAS серверов.




В компаниях, с которыми я сталкивался, для данной задачи использовались:

1. Windows NLB
2. RoundRobin DNS
3. Hardware NLB

Первые два метода очень условно обеспечивают отказоустойчивость. Windows NLB в режиме "Unicast", если сетевое оборудование не настроено дополнительно, вообще нагрузку распределять не будет. Большинство запросов придут на один и тот же сервер, который первым ответит на  «broadcast» запрос. И вообще данный метод балансировки Microsoft использовать не рекомендует.

Hardware NLB хорош всем, кроме стоимости решения. Я сталкивался с ситуациями, когда даже крупные организации (больше 10000 пользователей) предпочитали ему Windows NLB, работающем в режиме “IGMP Multicast”.

Есть еще варианты с настройкой WAP и IIS ARR, но их использование для данной задачи выглядит совсем не интересно. Первый умеет работать только с HTTP/HTTPS трафиком, а второй Microsoft официально не поддерживает и не обновляет. Решение предоставляется «как есть», к тому же его тяжело отлаживать и есть вопросы с логированием.

В итоге я остановился на вариантах реализации данной задачи с использованием прокси под управлением OS Linux. Самым очевидным решением показался HAproxy, но от него пришлось отказаться из-за того, что в логах серверов Exchange не будут видны реальные IP клиентов.

Далее начались поиски решения, которое умеет работать в режиме “Direct Routing”. Если коротко, его особенность в том, что при проксировании в пакетах подменяется только МАС адрес назначения. Ответ от сервера идет минуя сам прокси.

Схема выглядит приблизительно так:




RIP - реальный IP адрес
VIP - виртуальный IP адрес

Как видно по схеме, VIP для всех серверов устанавливается одинаковый. RIP уникальны, но все находятся в пределах одной подсети. Это важно, иначе DR работать не будет! VIP и RIP должны находиться в одном физическом сегменте сети и в одной подсети.

BalanceNG был первым решением, которое я попробовал настроить, но его бесплатная версия, как оказалось, имеет ограничения. Денег под данную задачу выбивать не хотелось, поэтому поиски были возобновлены. Я начал копать в сторону LVS (Linux Virtual Server) и буквально к вечеру у меня уже был работающий балансировщик, который после тестирования переехал в продакшн. После месяца работы, аналогичное решение было внедрено и для нескольких других организаций Microsoft Exchange. Прошло уже три месяца и LVS показал себя как исключительно надежное и нетребовательное к ресурсам решение. Один виртуальный сервер с конфигурацией 1vCPU/1GB RAM спокойно обслуживает более 10 000 клиентов Exchange и это далеко не предел.

В данном примере будет развернут 1 сервер. Если нужно будет добавить второй для обеспечения отказоустойчивости, вы без проблем сможете это сделать внеся незначительные изменения в настройки.

Итак,  нам нужен один виртуальный сервер с 1vCPU и 1GB RAM. Должен быть внешний интерфейс, который находится в той же сети, где опубликованы CAS серверы. Настройки на примере ОС Linux Centos 6.6. Приступим.

1. По старой доброй традиции, начнем с обновления Linux и рестарта машины:

#yum -y update
#reboot

2. В файле /etc/sysctl.conf изменяем значение параметра net.ipv4.ip_forward на "1" и применяем изменения:

#sed -i 's/net.ipv4.ip_forward = 0/net.ipv4.ip_forward = 1/g' /etc/sysctl.conf
#sysctl -p /etc/sysctl.conf

3. Создаем виртуальный интерфейс для VIP. Для этого:

Проверяем, на каком интерфейсе RIP. В данном случае это eth1.

# ip a | grep 86.57.246.110
    inet 86.57.246.110/24 brd 178.159.247.255 scope global eth1

Создаем новый интерфейс, в котором указываем VIP.

# vim /etc/sysconfig/network-scripts/ifcfg-eth1:1
DEVICE=eth1:1
TYPE=Ethernet
ONBOOT=yes
BOOTPROTO=static
IPADDR=86.57.246.100
NETMASK=255.255.255.0

Перезагружаем службу сети:

#service network restart

4. Установим службу балансировщика ipvsadm и инструменты для администрирования кластера piranha. Так же на всякий случай проверим установку netcat (нужен для корректной работы скрипта мониторинга портов):

#yum install ipvsadm piranha nc -y

5. При необходимости можно выполнять настройки через GUI, но, на мой взгляд, проще конфигурировать без него, особенно на начальном этапе.

Правим конфиг:

#vim /etc/sysconfig/ha/lvs.cf

serial_no = 1
primary = 86.57.246.110  ### RIP балансировщика
service = lvs
backup_active = 0
backup = 0.0.0.0
heartbeat = 1
heartbeat_port = 539
keepalive = 6
deadtime = 18
network = direct    ### Этот параметр показывает, что будем использовать DR
debug_level = NONE

### Пример настройки балансировки для 443 порта ####
virtual VIP443 {
     active = 1           ### 0 - полностью деактивировать правило
     address = 86.57.246.100 eth1:1   ### VIP и интерфейс балансировщика
     vip_nmask = 255.255.255.0
     port = 443
     expect = "TRUE"   ### Значение, которое должен возвращать скрипт мониторинга
     use_regex = 0
     send_program = "/etc/sysconfig/ha/monitor/portmon.sh %h 443"   ### Скрипт мониторинга
     load_monitor = none
     scheduler = rr          ### Тип балансировки. RR - RoundRobin.
     protocol = tcp
     timeout = 6
     reentry = 15
     quiesce_server = 0
     server CAS01 {
         address = 86.57.246.120  ### RIP CAS сервера
         active = 1   ### 0 - на хост пакеты не идут
         port = 443
         weight = 1   ### Используется, если балансировка, например, Weighted Round-Robin
     }
     server CAS02 {
         address = 86.57.246.130  ### RIP CAS сервера
         active = 1
         port = 443
         weight = 1
     }

Блок, который выделен курсивом, повторяем для портов, подключения к которым собираемся балансировать (например 25, 80, 110, 143, 465, 587, 993, 995)

6. Теперь создадим скрипт для мониторинга состояния портов, который мы указывали в конфиге ранее:

# vim /etc/sysconfig/ha/monitor/portmon.sh

#!/bin/sh

test=$(nc -vz $1 $2 -w5 2>/dev/null | grep -i "succeeded" |wc -l) > /dev/null 2>&1

if [ $test -eq 1 ]; then
        echo "TRUE"
else
        echo "FALSE"
fi

Скрипт пробует присоединиться к порту, указанному в конфиге. Если соединение висит более пяти секунд, он возвращает "FALSE" и сервер временно выкидывается из балансировки.

Добавляем права на выполнение:

#chmod +x /etc/sysconfig/ha/monitor/portmon.sh

7. Далее надо настроить наши CAS серверы.

Создаем loopback интерфейс (инструкция), добавляем на него VIP (маска сети /32), шлюз не указываем. Так же надо установить метрику 254 и снять чекбокс "Register this connection's address in DNS". Затем выполняем команды:

>netsh interface ipv4 set interface <IDX number for Server NIC> weakhostreceive=enabled
>netsh interface ipv4 set interface <IDX number for loopback> weakhostsend=enabled
>netsh interface ipv4 set interface <IDX number for loopback> weakhostreceive=enabled

Чтобы узнать IDX, достаточно выполнить команду:

>netsh interface ipv4 show interfaces

Включение параметра "weakhostreceive" позволяет сетевому интерфейсу принимать пакеты даже в том случае, если ему не присвоен IP адрес назначения (ведь мы помним, что пакеты идут на VIP, который реально есть только на балансировщике). Параметр "weakhostsend" надо включить для того, чтобы мы могли отправлять ответы от имени VIP.

7. Перезапускаем службу балансировщика на сервере с LVS:

#/etc/init.d/pulse restart

Далее проверяем, установились ли соединения с сервером. Вывод должен быть примерно такой:

# ipvsadm -L -n

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
 -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  86.57.246.100:25 rr
  -> 86.57.246.120:25            Route   1      1          0      
  -> 86.57.246.130:25            Route   1      0          0      
TCP  86.57.246.100:80 rr
  -> 86.57.246.120:80            Route   1      0          0      
  -> 86.57.246.130:80            Route   1      0          0      
TCP  86.57.246.100:110 rr
  -> 86.57.246.120:110           Route   1      0          0      
  -> 86.57.246.130:110           Route   1      1          1      
TCP  86.57.246.100:143 rr
  -> 86.57.246.120:143           Route   1      10         1      
  -> 86.57.246.130:143           Route   1      3          1      
TCP  86.57.246.100:443 rr
  -> 86.57.246.120:443           Route   1      5897        109      
  -> 86.57.246.130:443           Route   2      5681        197      
TCP  86.57.246.100:587 rr
  -> 86.57.246.120:587           Route   1      0          0      
  -> 86.57.246.130:587           Route   1      0          0      
TCP  86.57.246.100:993 rr
  -> 86.57.246.120:993           Route   1      2          1      
  -> 86.57.246.130:993           Route   1      4          0      
TCP  86.57.246.100:995 rr
  -> 86.57.246.120:995           Route   1      1          7      
  -> 86.57.246.130:995           Route   1      0          8      


На этом все. Тестируйте и запускайте в продакшен.

P.S. В самом начале статьи я говорил, что ресурсов 1vCPU и 1vRAM хватает с большим запасом. Чтобы они не простаивали, возложим на наш сервер еще одну важную задачу. Но об этом поговорим позже, в одной из следующий статей.

Балансировка нагрузки Microsoft Exchange с помощью Linux Virtual Server. Часть 2.


27 комментариев:

  1. Артем, добрый день!

    А реально ли как то настроить этот балансировщик, когда RIP в разных подсетях?

    Андрей

    ОтветитьУдалить
    Ответы
    1. Добрый день, Андрей!

      Получится, если они в одном сегменте сети, так как у балансировщика в случае с DR должна быть возможность обращаться к RIP по MAC адресам. Ну и, конечно же, все RIP должны быть доступны для балансировщика (маршруты).

      Удалить
  2. Артем, добрый день!

    А реально ли как то настроить этот балансировщик, когда RIP в разных подсетях?

    Андрей

    ОтветитьУдалить
  3. Еще бы для полноты всего описаного написать что в DNS указывать? Просто не многие решались на настройку подобных решений из за дороговизны. А настраивали DNS RR. Было бы хорошо, если бы бы полное описание.

    ОтветитьУдалить
    Ответы
    1. Ок, дополню.

      В DNS надо указать только VIP (в нашем примере это 86.57.246.100).

      Удалить
  4. Артем, спасибо за терпение и а подсказки. Долго мучился и решался попробовать данное решение. А так как Артем любезно решился помочь мне настроить такое решение, то ... В итоге все работает замечательно. С Exchange 2016 в том числе и с его Mapi Over HHTPS. Так что описание полностью рабочее главное БЫТЬ внимательнее и обратить внимание на то, что например у CAS серверов маска подсети на VIP 255.255.255.255! Если просмотрите и поставите как на балансировщике, то работать не будет. И еще, если правите конфиг руками, копируя от сюда, то удаляйте примечания. Последняя piranha ругается на коментарии особенно в строке где ускрипт для проверки CAS

    ОтветитьУдалить
  5. Здравствуйте,

    В результате мы имеем точку отказа в виде балансировщика. Вы писали про поднятие еще одного такого же балансировщика рядышком с незначительным изменением конфигов. Что там будет меняться?

    В какую сторону лучше копать? Ваше мнение? Есть ли смысл балансировать нагрузку между балансировщиками с помощью DNS RR?

    ОтветитьУдалить
    Ответы
    1. Нет, ни в коем случае не используйте DNS RR! Я сейчас доделаю проект и подробно опишу, как сделать отказоустойчивость балансировщика правильно.

      Удалить
    2. Добрый день. Я тоже жду описания отказоустойчивости )) Подобное решение я уже внедрил и в дочерней организации и на CentOS 7

      Удалить
  6. Добрвй день. Подскажите, при настройке Windows NLB, переконфигурировать базы под CasArry, здесь так же?

    ОтветитьУдалить
    Ответы
    1. Добрый день.

      Cas Array в Exchange 2013/2016 отсутствует. Поэтому ничего больше настраивать не надо.

      Удалить
  7. Добрый день Артём.
    Скажите пожалуйста можно ли настроить балансировку по вашей схеме для варианта работы с Exchange2013, когда CAS и DAG установлены на одном сервере? На сколько я помню по данным Microsoft нельзя делать балансировку подобным способом для. серверов с ролью DAG.

    ОтветитьУдалить
    Ответы
    1. CAS и DAG на одном сервере это Вы что имели ввиду? А как же тогда Exchage 2016? В общем у меня работает в варианте два сервера с объединенными службами с DAG и с двумя серверами балансировки по такому способу..

      Удалить
    2. Владислав, это не совсем так. Балансировку не получится сделать средствами Windows NLB, если роли MBX и CAS установлены на одном сервере. Но в данном варианте мы используем программный аналог аппаратного балансировщика нагрузки. Поэтому - никаких проблем. Все будет работать отлично.

      Удалить
  8. Артем, добрый день!
    При совмещенных ролях CAS + DAG, какой ip кластера DAG необходимо указать в настройках DNS?
    Если такой же как у балансировщика, то выходит ошибка, что такой адрес уже есть.

    ОтветитьУдалить
    Ответы
    1. IP надо указывать не DAG(это вообще другая история и другая защита и балансировка, а именно баз данных,к пользовательским же подключениям не имеет никакого отношения), а VIP.

      Удалить
    2. Все верно. DAG не предназначен для клиентских подключений (да, работает, но это unsupported). Для клиентских подключений необходимы отдельные IP адреса. В данном случае их будет четыре:
      1 CAS_1_RIP
      1 CAS_2_RIP
      1 LoadBalancer_RIP
      1 VIP (к которому подключаются клиенты)

      Удалить
  9. Все круто! Спасибо! Настроил, работает MAPI - хорошо. А вот POP3 и IMAP никак не хотят подключаться через балансировщик, а напрямую к серверу хотят. Почему так?

    ОтветитьУдалить
  10. ipvsadm -L -n
    Показывает в списке порты 110 и 143? Соединение на корректный адрес ведет?
    Что возвращает:
    /etc/sysconfig/ha/monitor/portmon.sh ExchangeServerIP 143

    ОтветитьУдалить
  11. Добрый. У меня тоже не все порты почему то тестировал на живучесть. Как раз 110 и 143... Долго обсуждал с Артемом, в итоге сошлись на том, что можно использовать например 80 или 25.. Ведь тут мы весь сервер проверяем. Я тогда так и не смог решить почему так.

    ОтветитьУдалить
  12. Попробуйте изменить health probe:

    test=$(nc -z $1 $2 -w5 | grep -i "succeeded" |wc -l) > /dev/null 2>&1

    ОтветитьУдалить
  13. добрый день!

    а как быть с сертификатами для IIS на этих двух CAS ? ведь имена серверов CAS разные ?

    ОтветитьУдалить
  14. Вы немного запутались. Для подключения Exchange существуею единое внешнее имя, которое прописывается в IIS на всех CAS. И даже не важно, каким образом вы балансируете нагрузку (wNLB, rrDNS, HLB, LVS, etc.)

    ОтветитьУдалить
  15. а понятно. Мне надо на IIS на обоих серваках создать одинаковые сайты с внешним именем для autodiscover и к нему привязать сертификат ?

    ОтветитьУдалить
  16. В 2022 году это актуально? а как быть если сервера exchange стоят в разных датацентрах и между собой общаются в сети vpn как тут обеспечить отказоустойчивость?

    ОтветитьУдалить
  17. В 2022 это решение актуально, но надо вносить некоторые правки. Навскидку - lvs был удален из ядра, надо его чем-либо заменить. Хотя подход останется примерно тем же.

    Для балансировки между датацентрами это решение не подойдет. Можно сделать балансировку на уровне датацентров как на схеме + сверху, например, AWS Route53 или любой аналогичный.

    ОтветитьУдалить