Повышаем доступность прокси-сервера Squid с помощью UCARP с балансировкой нагрузки между двумя виртуальными серверами на базе Ubuntu Server 14.04.2

imageНесмотря на довольно стабильную работу прокси-сервера Squid в средах с большим количеством пользователей, может возникнуть желание повышения уровня доступности такого важного на сегодняшний день информационного ресурса, как доступ в Интернет для конечных пользователей. В этой заметке будет рассмотрен пример настройки двух прокси-серверов Squid для повышения доступности с параллельным распределением нагрузки между этими серверами.

За основу мы возьмём идею изложенную в статье Pinkhamster.net - High-Availability SMTP with UCARP on Debian, то есть для организации повышения доступности и балансировки нагрузки будем устанавливать и настраивать на наших прокси-серверах пакет UCARP. Тезисно общий смыл настройки и последующей работы UCARP можно отразить так:

  • На двух прокси серверах будет настроено два одинаковых виртуальных IP адреса (vIP) на интерфейсе направленном во внутреннюю локальную сеть (LAN-интерфейс)
  • Каждый vIP на любой определённый момент времени активен (в понятиях ucarp имеет статус MASTER) на одном сервере, и неактивен (статус BACKUP) на другом сервере.
  • В целях распределения нагрузки один из двух vIP активен на одном сервере, а второй vIP активен на другом сервере. При этом в DNS будет создано две A-записи с одинаковым именем и адресами vIP
  • Как только один из серверов становится недоступен, на втором сервере vIP имеющий статус BACKUP меняет статус на MASTER и начинает работать. При этом специальными arp-сообщениями оповещается сетевое оборудование (коммутатор/маршрутизатор) о том, что теперь для данного IP используется другой MAC адрес.

Серверы в нашем примере будут представлять собой виртуальные машины Hyper-V Gen2 с гостевой ОС Ubuntu Server 14.04.2 и уже и настроенным Squid 3.5.4. IP адресация vIP на серверах будет распределена следующим образом:

KOM-AD01-GW20 – MASTER для vIP 10.16.8.23 и BACKUP для vIP 10.16.8.22
KOM-AD01-GW21 – MASTER для vIP 10.16.8.22 и BACKUP для vIP 10.16.8.23

Для большей наглядности приведу простейшую схему нашей конечной конфигурации:

image


Учитывая то, что в нашем случае серверы виртуальные, первым делом нам потребуется изменить свойства сетевых адаптеров этих виртуальных машин – разрешить спуфинг MAC-адресов

image

Если этого не сделать, ucarp в нашей виртуальной среде корректно работать не будет.

***

Подключимся к гостевой ОС наших виртуальных серверов и посмотрим информация о текущей версии пакета ucarp доступного в репозитории Ubuntu

apt-cache show ucarp

Package: ucarp
Priority: optional
Section: universe/net
Installed-Size: 147
Maintainer: Ubuntu Developers 
Original-Maintainer: Eric Evans 
Architecture: amd64
Version: 1.5.2-1+nmu1ubuntu1
Depends: libc6 (>= 2.14), libpcap0.8 (>= 0.9.8), ifupdown (>= 0.7.1)
Recommends: iproute
Filename: pool/universe/u/ucarp/ucarp_1.5.2-1+nmu1ubuntu1_amd64.deb
Size: 29254
MD5sum: 86938a564c703ac242b609200ec7f39d
SHA1: 1a5e76a013626d3dcf7a39760d9d7986e7da6880
SHA256: d6cfcabf372356374bfd1714538f3353c59b0a7898a031ea1ed35154c56c029e
Description-en: user-space replacement to VRRP -- automatic IP fail-over
 UCARP allows a pair of hosts to share common virtual IP addresses in
 order to provide automatic fail-over. It is a portable user-land
 implementation of the secure and patent-free Common Address Redundancy
 Protocol (CARP, OpenBSD's alternative to the VRRP).
 .
 Strong points of the CARP protocol are: very low overhead,
 cryptographically signed messages, interoperability between different
 operating systems and no need for any dedicated extra network link
 between redundant hosts.
Description-md5: 36fd006163fed0383d5b8b48eaccd4c3
Homepage: http://ucarp.org
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Origin: Ubuntu

На обоих серверах устанавливаем ucarp вместе с пакетом-зависимостью iproute:

sudo apt-get install iproute ucarp

Открываем на редактирование конфигурационный файл описывающий сетевые интерфейсы:

sudo nano -Y sh /etc/network/interfaces

Добавляем строки настройки ucarp для LAN-интерфейса (eth0) на первом сервере (KOM-AD01-GW20) (тёмно красным выделены внесённые в файл изменения):

#
# LAN
#
auto eth0
iface eth0 inet static
        address 10.16.8.20
        netmask 255.255.255.0
        network 10.16.8.0
        broadcast 10.16.8.255
        # dns-* options are implemented by the resolvconf package, if installed
        dns-nameservers 10.16.8.9 10.16.1.8
        dns-search holding.com
        up route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.16.8.1
        #
        # up first virtal ip interface (as backup)
        #
        up ucarp --interface=eth0 --srcip=10.16.8.20 \
        --vhid=22 --pass=StR0nG_PwD --addr=10.16.8.22 \
        --upscript=/etc/ucarp/vip-22-up.sh \
        --downscript=/etc/ucarp/vip-22-down.sh \
        --advskew=200 --shutdown --daemonize
        #
        # up second virtal ip interface (as master)
        #
        up ucarp --interface=eth0 --srcip=10.16.8.20 \
        --vhid=23 --pass=StR0nG_PwD --addr=10.16.8.23 \
        --upscript=/etc/ucarp/vip-23-up.sh \
        --downscript=/etc/ucarp/vip-23-down.sh \
        --advskew=100 --preempt --shutdown --daemonize
        #
        # kill all ucarp process if eth0 down
        #
        down pkill ucarp
        #

Второй сервер (KOM-AD01-GW21) настраиваем по аналогии, только меняем значение параметров --srcip, а также меняем местами значения в параметрах --advskew (ну и комментарий соответственно) и обращаем внимание на параметр --preempt:

#
# LAN
#
auto eth0
iface eth0 inet static
        address 10.16.8.21
        netmask 255.255.255.0
        network 10.16.8.0
        broadcast 10.16.8.255
        # dns-* options are implemented by the resolvconf package, if installed
        dns-nameservers 10.16.8.9 10.16.1.8 
dns-search holding.com up route add -net 10.0.0.0 netmask 255.0.0.0 gw 10.16.8.1 # # up first virtal ip interface (as master) # up ucarp --interface=eth0 --srcip=10.16.8.21 \ --vhid=22 --pass=StR0nG_PwD --addr=10.16.8.22 \ --upscript=/etc/ucarp/vip-22-up.sh \ --downscript=/etc/ucarp/vip-22-down.sh \ --advskew=100 --preempt --shutdown --daemonize # # up second virtal ip interface (as backup) # up ucarp --interface=eth0 --srcip=10.16.8.21 \ --vhid=23 --pass=StR0nG_PwD --addr=10.16.8.23 \ --upscript=/etc/ucarp/vip-23-up.sh \ --downscript=/etc/ucarp/vip-23-down.sh \ --advskew=200 --shutdown --daemonize # # kill all ucarp process if eth0 down # down pkill ucarp #

Здесь важно обратить внимание на правильные значения параметра --advskew (определяет вес при выборе приоритетного владельца vIP) а также его сосуществование с параметром --preempt (разрешает сразу же активировать vIP на текущем сервере как MASTER).

***

Далее на обоих серверах создаём папку для хранения скриптов ucarp, в ней создаём файлы скриптов для активации и деактивации vIP и делаем их исполняемыми для root.

sudo mkdir /etc/ucarp
sudo touch /etc/ucarp/vip-22-up.sh
sudo touch /etc/ucarp/vip-22-down.sh
sudo touch /etc/ucarp/vip-23-up.sh
sudo touch /etc/ucarp/vip-23-down.sh
sudo chmod 0700 /etc/ucarp/*.sh

Настраиваем скрипты на обоих серверах одинаково…

Наполняем содержимым скрипт активации первого vIP /etc/ucarp/vip-22-up.sh:

#! /bin/sh
exec 2> /dev/null

/sbin/ip addr add 10.16.8.22/24 dev "$1"

Наполняем содержимым скрипт деактивации первого vIP /etc/ucarp/vip-22-down.sh:

#! /bin/sh
exec 2> /dev/null

/sbin/ip addr del 10.16.8.22/24 dev "$1"

Наполняем содержимым скрипт активации второго vIP /etc/ucarp/vip-23-up.sh:

#! /bin/sh
exec 2> /dev/null

/sbin/ip addr add 10.16.8.23/24 dev "$1"

Наполняем содержимым скрипт деактивации второго vIP /etc/ucarp/vip-23-down.sh:

#! /bin/sh
exec 2> /dev/null

/sbin/ip addr del 10.16.8.23/24 dev "$1"

***

В локальной доменной зоне прямого просмотра DNS, обслуживающей клиентов локальной сети создадим две A-записи с одинаковым именем, например KOM-AD01-GWCL, и IP-адресами используемыми в конфигурации ucarp (vIP) 

image

В результате при попытке клиентов разрешить имя единой точки входа KOM-AD01-GWCL в IP адрес, DNS сервер будет возвращать список из двух IP (vIP) адресов поочередно меняя их приоритет при каждом последующем ответе клиенту (DNS Round Robin) реализуя таким образом в конечном счёте возможность распределения клиентов по разным прокси-серверам.

***

Далее перейдём к конфигурации Squid. На обоих серверах нам может потребоваться внести изменения в squid.conf. Если конфигурация squid настроена по аналогии с представленным ранее примером, то директива http_port заставляет squid при запуске создавать TCP-прослушиватель на конкретных локальных IP адресах сервера:

# NETWORK OPTIONS 
# -----------------------------------------------------------------------------
#
http_port 10.16.8.20:3128
http_port 127.0.0.1:3128

#

Как же быть с этой директивой если мы планируем использовать ucarp в связке c squid для повышения доступности последнего? В голову сразу может прийти мысль о том, что можно добавить на оба наши прокси-сервера оба адреса vIP в директиву http_port. Однако с такой конфигурацией у нас может возникнуть проблема доступности соответствующих TCP-прослушивателей, так как один и тот же vIP (как MASTER) может перемещаться между двумя серверами в случаях failover/failback. То есть, например, при запуске squid на сервере KOM-AD01-GW20 в системе не будет доступен vIP интерфейс ucarp 10.16.8.22, так как на этот момент времени он запущен на другом сервере (KOM-AD01-GW21), и поэтому squid не создаст прослушиватель 10.16.8.22:3128. При ситуации failover (недоступности сервера KOM-AD01-GW21) интерфейс vIP 10.16.8.22 будет поднят на сервере KOM-AD01-GW20, но squid никак на это не отреагирует. Здесь возникнет ситуация, когда часть пользователей пытающихся подключиться к 10.16.8.22:3128 получат сообщение о недоступности прокси-сервера. Выйти из этой ситуации можно, например, добавив в конец up/down-скриптов ucarp команду “передёргивания” squid (sudo squid3 –k reconfigure). Однако такое решение может вызвать кратковременные пиковые нагрузки на прокси-сервер в тот момент, когда squid будет сбрасывать свои кэши, что само по себе может стать проблемой при большом количестве пользователей.    

Другим вариантом, который мне кажется более правильным с точки зрения равномерности нагрузки на прокси-сервер, является изменение директивы http_port в значение по умолчанию:

# NETWORK OPTIONS 
# ----------------------------------------------------------------------------- 
# 
http_port 3128
#

При этом варианте оба наших прокси сервера будут успешно принимать подключения на оба vIP в независимости от ситуаций failover/failback.

После внесения изменений заставим squid перечитать конфигурацию и проверим состояние TCP-прослушивателей:

sudo squid3 -k reconfigure
sudo netstat -tnlp | grep 3128

tcp        0      0 0.0.0.0:3128            0.0.0.0:*               LISTEN      20715/squid3

Очевидно, что такой вариант имеет свою оборотную сторону. Получается так, что в данной конфигурации TCP-прослушиватель squid потенциально способен принимать подключения на порт 3128 не только со стороны LAN-интерфейса но и со стороны WAN-интерфейса, что уже само по себе не очень хорошо. Однако, данный вариант можно считать вполне приемлемым в случае соблюдения как минимум двух дополнительных условий:

  • корректная настройка директив acl (правильно описаны локальные сети, с которых можно подключаться к прокси-серверу) и http_access (правильно ограничен доступ к прокси-серверу) в конфигурационном файле squid.conf;
  • активный брандмауэр с политикой блокировки всех соединений со стороны WAN, за исключением тех которые разрешены явно.

Первое условие соблюдается при базовой настройке директив squid.conf, про которую мы говорили ранее. Второе условие достигается базовой настройкой iptables, однако иногда могут возникать ситуации, когда на пусть даже непродолжительное время по какой-то причине (например в целях "траблшутинга") необходимо менять политику обработки входящих пакетов с DROP на ACCEPT. В такие моменты наш TCP-прослушиватель squid становится доступен на WAN-интерфейсе. Поэтому, чтобы полностью исключить возможность потенциальных угроз, добавим явное правило iptables запрещающее внешние подключения к порту squid (подразумевается, что eth1 это WAN-интерфейс):

sudo iptables -A INPUT -p tcp --dport 3128 -i eth1 -j DROP
sudo service iptables-persistent save

После всех проделанных изменений перезагружаем оба сервера. После перезагрузки убеждаемся в том, что на обоих серверах на LAN-интерфейсах (eth0) появились адреса vIP и они распределены по серверам именно таким образом, как мы задумали изначально:

На сервере KOM-AD01-GW20:

sudo ip addr show | grep inet

    inet 127.0.0.1/8 scope host lo
    inet 10.16.8.20/24 brd 10.16.8.255 scope global eth0
    inet 10.16.8.23/24 scope global secondary eth0
    inet 99.99.99.20/24 brd 99.99.99.255 scope global eth1

На сервере KOM-AD01-GW21:

sudo ip addr show | grep inet

    inet 127.0.0.1/8 scope host lo
    inet 10.16.8.21/24 brd 10.16.8.255 scope global eth0
    inet 10.16.8.22/24 scope global secondary eth0
    inet 99.99.99.21/24 brd 99.99.99.255 scope global eth1

***

Теперь нам нужно проверить корректность перемещения адресов vIP между серверами в случае недоступности одного из серверов. Сначала проверим сервер KOM-AD01-GW20. Необходимо убедиться в том, что при выключении сервера KOM-AD01-GW21 на сервере KOM-AD01-GW20 поднимется vIP, принадлежащий в данный момент серверу KOM-AD01-GW21 (10.16.8.22). Запустим с клиентского компьютера ping этого vIP, на сервере KOM-AD01-GW20 запустим вывод сообщений из syslog и выключим (Power Off) виртуальную машину KOM-AD01-GW21:

sudo tail -f /var/log/syslog | grep ucarp

May  8 11:04:38 KOM-AD01-GW20 ucarp[657]: [WARNING] Switching to state: MASTER
May  8 11:04:38 KOM-AD01-GW20 ucarp[657]: [WARNING] Spawning [/etc/ucarp/vip-22-up.sh eth0 10.16.8.22]

Как видим, в логе появились записи о том, что vIP поменял свой статус с BACKUP на MASTER и был запущен скрипт активации этого vIP. При этом утилита ping запущенная на клиентском компьютере для данного адреса покажет потерю одного-двух пакетов. Проверим на KOM-AD01-GW20 как изменилась ситуация с сетевыми интерфейсами:

sudo ip addr show | grep inet

    inet 127.0.0.1/8 scope host lo
    inet 10.16.8.20/24 brd 10.16.8.255 scope global eth0
    inet 10.16.8.23/24 scope global secondary eth0
    inet 10.16.8.22/24 scope global secondary eth0
    inet 99.99.99.20/24 brd 99.99.99.255 scope global eth1

Как видим, на данный момент оба адреса vIP активны на единственном доступном сервере.

Теперь включим обратно сервер, чтобы убедиться в том, что успешно отрабатывает процедура failback (то есть адрес vIP возвращается на предпочтительный сервер сразу при начале его доступности). При этом на севере KOM-AD01-GW20 в логе появляются сообщения говорящие об изменении статуса соответствующего vIP с MASTER на BACKUP:

sudo tail -f /var/log/syslog | grep ucarp

May  8 11:16:42 KOM-AD01-GW20 ucarp[657]: [WARNING] Switching to state: BACKUP
May  8 11:16:42 KOM-AD01-GW20 ucarp[657]: [WARNING] Spawning [/etc/ucarp/vip-22-down.sh eth0 10.16.8.22]
May  8 11:16:42 KOM-AD01-GW20 ucarp[657]: [WARNING] Preferred master advertised: going back to BACKUP state
sudo ip addr show | grep inet

    inet 127.0.0.1/8 scope host lo
    inet 10.16.8.20/24 brd 10.16.8.255 scope global eth0
    inet 10.16.8.23/24 scope global secondary eth0
    inet 99.99.99.20/24 brd 99.99.99.255 scope global eth1

Как видим процедура failback отработала успешно.

Проверяем аналогичным образом передачу второго vIP выключая и обратно включая на время сервер KOM-AD01-GW20. В процессе проверки параллельно убеждаемся в том, что на клиентских компьютерах по прежнему работает доступ в Интернет через единую точку входа:
KOM-AD01-GWCL.holding.com:3128.

Таким образом мы добились желаемого результата – получили повышение доступности такого информационного ресурса, как доступ в Интернет для конечных пользователей с дополнительной возможностью распределения нагрузки между двумя прокси-серверами. При всей прелести данного решения стоит понимать, что оно будет эффективно только в случае возникновения проблем доступности на уровне отдельно взятого прокси-сервера, но не на уровне squid как приложения.

PS: В первоисточнике, который был взят за основу для реализации решения повышения доступности наряду с ucarp использовалась утилита arping из пакета iputils-arping, однако, как показала практика, всё вполне успешно работает и без её использования.

Дополнительные источники информации: 

Pinkhamster.net - High-Availability SMTP with UCARP on Debian
Habrahabr.ru - Отказоустойчивые службы при помощи CARP

Всего комментариев: 8 Комментировать

  1. Обратная ссылка: Повышаем доступность веб-сервера Apache с помощью UCARP с балансировкой нагрузки между двумя виртуальными серверами на базе Ubuntu Server 14.04.2 | Блог IT /

  2. Обратная ссылка: Настройка подключения к двум и более интернет-провайдерам (Multi-WAN) на Ubuntu Server 14.04.2 LTS для Squid | Блог IT-KB /

  3. Обратная ссылка: Распределение трафика между двумя прокси-серверами Squid (на Ubuntu Server 14.04.2 LTS) подключёнными к двум интернет-провайдерам (Multi-WAN). Обновлённый ва /

  4. Neri /

    А что происходит с построениями отчетов через LightSquid, на 1-ом прокси своя половина, на 2-ом прокси своя?

    1. Алексей Максимов / Автор записи

      Да.

  5. Сергей /

    Подскажите по работе прокси сервера на Microsoft 2012 R2 Hyper-V. На нем стоит виртуалка с CentOS, все службы для работы с Hyper-V стоят в виртуалке, на виртуалке стоит squid 3.5.3, в какой то момент когда нагрузка очень выросла виртуалка начала себя вести очень странно, выросли пинги внутри локалки от любого ПК к прокси, выросли значительно от 1ms до 1500ms, пинги не стабильны. В какой то момент сеть может отвалиться, помогает только перезапус сети. В интернете встречал подобные проблемы на Hyper-V 2008 но у меня 2012 а по симптомам ведет себя так же. На этом же Hyper-V есть другие виртуалки с CentOS которые полностью идетничны с виртуалкой прокси сервера, за исключением сервисов которые на ней установлены с ними такой проблемы нет. Нагрузка на прокси сервер минимальна по процессору и памяти но сеть очень активно пользуется. Вот тут графики от zabbix http://itmages.ru/image/view/2915089/cefbf388 Интересны Ваши мысли по такой проблеме. Спасибо.

  6. aprogrammer /

    Спасибо за статью. Очень полезная штука - настраивал под Ubuntu (http://sysadm.pp.ua/linux/carp-ubuntu.html) кластер из трех серверов - до сих пор на проде работает. Не подскажите, если ли возможность(технология) для geodistributed redundent IP, может сталкивались ? Заранее спасибо.

  7. Anton /

    Какой смысл делать ucarp, если используется DNS RR?

Добавить комментарий