Pull to refresh

NGINX как балансировщик нагрузки для MySQL или MariaDB Galera Cluster

Reading time 6 min
Views 25K
Данная статья является переводом оригинальной статьи с сайта Severalnines.

Nginx хорошо известен всем за свои расширенные возможности и эффективность в качестве прокси и/или балансировщика веб-приложений с низким потреблением памяти. Как правило, nginx используется на первой “линии обороны” веб приложений, чтобы распределять нагрузку на сервера бекенда, периодически проверяя их работоспособность. Данная технология довольно популярна для приложений, которым требуется повышенная отказоустойчивость.



Недавно nginx 1.9 анонсировали поддержку балансировки TCP, примерно тоже самое, что до этого реализовывалось с использованием HAProxy. Одним из самых больших недостатков будет то, что nginx не поддерживает расширенную проверку работоспособности серверов. Данная функция необходима, если вы используете MySQL Galera Cluster. Мы расскажем об этом подробнее в следующей главе. Стоит обратить внимание, что в платной версии (под названием NGINX Plus) данного ограничения нет.

В этой статье мы используем nginx, как прокси для MySQL Galera Cluster и попробуем получить высокую производительность. Мы подняли кластер Galera, используя ClusterControl, на CentOS 7.1; установим nginx на “свежий” хост, как указано на диаграмме:



Проверка работоспособности


С появлением синхронно-реплицируемых кластеров, как Galera или NDB, использование TCP прокси в качестве балансировщика нагрузки стало довольно популярным. Все ноды MySQL обрабатываются одинаково, так как со всех них можно читать, а также на всех них можно записывать. Разделение между мастером и слейвом больше не требуется, как это было с классической репликацией MySQL. Nginx не предназначен для баз данных, поэтому придется прибегнуть к дополнительным конфигурациям, чтобы заставить кластер возвращать “понятный” ответ на проверку работоспособности.

Если вы используете HAProxy, скрипт проверки работоспособности на каждом сервере MySQL должен уметь возвращать HTTP статус. К примеру, если MySQL сервер “чувствует себя хорошо” — скрипт вернет HTTP статус 200 OK. В обратном случае — скрипт вернет 503 Service unavailable. С такими настройками HAProxy может обновлять список роутинга и исключать “проблематичные” сервера. К сожалению, для проверки работоспособности, HAProxy использует xinetd в качестве демона, слушающего на 9200 порту. Этих конфигураций пока нет в nginx.

Данная блок-схема иллюстрирует процесс определения работоспособности кластера Galera с настройкой мульта-мастер:



На момент написания статьи, NGINX Plus (платный) также поддерживал проверку работоспособности серверов, но без настройки кастомного порта.

Использование clustercheck-iptables


Чтобы обойти ограничения, мы создали скрипт для проверки работоспособности под названием clustercheck-iptables. Это фоновый скрипт, который проверяет работоспособность ноды Galera и добавляет перенаправляющий порт, используя iptables, если нода работает как положено (вместо того чтобы возвращать HTTP ответ). Данный скрипт можно использовать с другими TCP балансерами, с ограниченными возможностями проверки работоспособности, таких как nginx (>1.9), IPVS, keepalived, piranha, distributor, balance или pen.

Как он работает? Скрипт проверяет работоспособность на каждой ноде кластера Galera, раз в секунду. Если нода работает в штатном режиме (wsrep_cluster_state_comment=Synced и read_only=OFF) или (wsrep_cluster_state_comment=Donor и wsrep_sst_method=xtrabackup/xtrabackup-v2), будет поднят порт переадресации, используя iptables (3308 по умолчанию, с переадресацией на 3306):

$ iptables -t nat -A PREROUTING -s $0.0.0.0/0 -p tcp --dport 3308 -j REDIRECT --to-ports 3306

В обратном случае, это правило будет удалено из списка правил iptables. На балансире необходимо установить порт 3308 вместо порта по умолчанию 3306. Если нода нездорова, порт 3308 будет недоступен, балансеру в таком случает, стоит удалить эту ноду из списка балансировки.

Давайте установим скрипт и посмотрим, как он работает на практике:

1. На серверах БД — выполните следующие команды, для установки скрипта:

$ git clone https://github.com/ashraf-s9s/clustercheck-iptables
$ cp clustercheck-iptables/mysqlchk_iptables /usr/local/sbin

2. По умолчанию скрипт будет использовать пользователя MySQL “mysqlchk_user” с паролем “mysqlchk_password”. Нам стоит убедиться, что пользователь существует и имеет необходимые права для проверки работоспособности. Выполните эти команды на одной из нод кластера (Galera выполнит их на остальных нодах).

mysql> GRANT PROCESS ON *.* TO 'mysqlchk_user'@'localhost' IDENTIFIED BY 'mysqlchk_password';
mysql> FLUSH PRIVILEGES;

** Если вы хотите использовать другого пользователя или пароль, укажите их в аргументах -u и -p. Вот тут есть пример.

3. Скрипту необходим iptables для работы. В данном примере мы используем CentOS 7, где по умолчанию установлен firewalld. Нам нужно установить iptables-services:

$ yum install -y iptables-services
$ systemctl enable iptables
$ systemctl start iptables

Затем, установим базовые правила для кластера MySQL Galera, так чтобы iptables не влиял на коммуникации с БД:

$ iptables -I INPUT -m tcp -p tcp --dport 3306 -j ACCEPT
$ iptables -I INPUT -m tcp -p tcp --dport 3308 -j ACCEPT
$ iptables -I INPUT -m tcp -p tcp --dport 4444 -j ACCEPT
$ iptables -I INPUT -m tcp -p tcp --dport 4567:4568 -j ACCEPT
$ service iptables save
$ service iptables restart

4. После установки правил, проверим их используя команду:

$ iptables -L -n

5. Протестируем mysqlchk_iptables:

$ mysqlchk_iptables -t
Detected variables/status:
wsrep_local_state: 4
wsrep_sst_method: xtrabackup-v2
read_only: OFF

[11-11-15 08:33:49.257478192] [INFO] Galera Cluster Node is synced.

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

$ mysqlchk_iptables -d
/usr/local/sbin/mysqlchk_iptables started with PID 66566.

7. Наши правила роутинга будут выглядеть примерно вот так:

$ iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:3308 redir ports 3306

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

8. Наконец-то, добавим запуск скрипта в /etc/rc.local, чтобы запускался на старте сервера:

$ echo '/usr/local/sbin/mysqlchk_iptables -d' >> /etc/rc.local

В некоторых дистибутивах стоит проверить, что у rc.local есть необходимые права для запуска скрипта:

$ chmod +x /etc/rc.local

На стороне приложения проверьте, что вы можете подключиться к БД на порту 3308. Повторите вышеперечисленные шаги (кроме 2) на всех (оставшихся) нодах кластера. Итак, мы закончили с проверками работоспособности, теперь займемся балансировкой.

Установка nginx в роли балансировщика нагрузки на кластер MySQL


1. На балансировщике (сервере) — установим необходимые пакеты:

$ yum -y install pcre-devel zlib-devel

2. Установим nginx 1.9 (из кода) с модулем TCP proxy:

$ wget http://nginx.org/download/nginx-1.9.6.tar.gz
$ tar -xzf nginx-1.9.6.tar.gz
$ ./configure --with-stream

3. Добавим следующие строки в файл конфигурации nginx (/usr/local/nginx/conf/nginx.conf):

stream {
      upstream stream_backend {
        zone tcp_servers 64k;
        server 192.168.55.201:3308;
        server 192.168.55.202:3308;
        server 192.168.55.203:3308;
    }

    server {
        listen 3307;
        proxy_pass stream_backend;
        proxy_connect_timeout 1s;
    }
}

4. Запустим nginx:

$ /usr/local/nginx/sbin/nginx

5. Убедимся, что nginx “слушает” на порту 3307, как мы указали в конфигурации. Подключения MySQL должны идти именно через этот порт, после чего, они будут переведены на порт 3308. Затем iptables (на ноде) переведет запрос на порт 3306, где “слушает” MySQL:

$ netstat -tulpn | grep 3307
tcp        0      0 0.0.0.0:3307            0.0.0.0:*               LISTEN      5348/nginx: master

Отлично! Мы установили nginx в роли балансировщика нагрузки на MySQL Galera Cluster. Переходим к тестированию.

Тестирование


Мы проводили следующие тесты, чтобы проверить балансировку nginx для кластера Galera:

1. Устанавливали read-only=ON и read_only=OFF на g1.local.
2. Убивали процесс mysql на g1.local и принуждали SST на запуске.
3. Убивали 2 другие ноды БД, чтобы g1.local стал non-primary.
4. Запускали g1.local из non-primary статуса.
5. Присоединяли другие 2 ноды.

Скринкаст ниже покажет вывод нескольких терминалов:

  • Терминал 1 (левый верхний угол): вывод iptables PREROUTING.
  • Терминал 2 (правый верхний угол): MySQL error.log на g1.local.
  • Терминал 3 (центр слева): вывод приложения при подключении к балансировщику nginx. Показывает date, hostname, wsrep_last_committed и wsrep_local_state_comment.
  • Терминал 4 (центр справа): вывод /var/log/mysqlchk_iptables.
  • Терминал 5 (левый снизу): вывод read_only и wsrep_sst_method на g1.local.
  • Терминал 6 (правый снизу): рабочая панель.



Заключение


Проверка работоспособности ноды кластера Galera была ограничена HAProxy, так как только HAProxy позволяла использовать кастомный порт. С этим скриптом можно использовать любой TCP балансировщик нагрузки и/или прокси для корректного мониторинга нод кластера Galera.
Tags:
Hubs:
+14
Comments 2
Comments Comments 2

Articles