{{tag>linux}} === MariaDB Galera Cluster === ---- == Подготовка == Разворачиваем три сервера ubuntu последней версии, назначаем статические ip (для трёх серверов понадобиться 4 штуки). Далее каждый отдельный сервер (из этих трёх) мы будем называть нода, а три сервера работающие вместе в унисон - кластер. Для удобства папку /var/lib/mysql делаем отдельным диском, чтобы всегда наглядно знать сколько занимают базы данных и сколько осталось, командой: df -h | grep --color=never 'mysql\|Filesystem' Пусть мы развернули три ноды: mdb01 192.168.7.32 mdb02 192.168.7.33 mdb03 192.168.7.34 На DNS сервере настроим такие имена: 192.168.7.32 mdb01.mosigra.su 192.168.7.33 mdb02.mosigra.su 192.168.7.34 mdb03.mosigra.su 192.168.7.35 mdbc01.mosigra.su На каждой ноде, начальная инициализация: dpkg-reconfigure tzdata && dpkg-reconfigure locales apt update && apt upgrade -y rm -Rf /var/lib/mysql/lost+found На случай полной деградации сети в hosts прописываем все три ноды: cat >> /etc/hosts << 'EOT' 192.168.7.32 mdb01.mosigra.su mdb01 192.168.7.33 mdb02.mosigra.su mdb02 192.168.7.34 mdb03.mosigra.su mdb03 EOT проверяем, перезагружаем: cat /etc/hosts reboot ---- == Установка MariaDB == добавление репозитория, установка curl, mariadb, мне нравится ещё устанавливать tree, но это по желанию apt install -y curl curl -LSsO https://r.mariadb.com/downloads/mariadb_repo_setup chmod u+x ./mariadb_repo_setup ./mariadb_repo_setup apt install -y mariadb-server mariadb-client mariadb-common tree проверяем версию MariaDB: mariadb --version == Настройка MariaDB == в файле /etc/mysql/mariadb.conf.d/50-server.cnf включим Планировщик событий, это пригодится для //партиционирования// (секционирования) Базы данных для Zabbix event_scheduler = ON == Настройка Galera == на всех нодах: cat >> /etc/mysql/mariadb.conf.d/60-galera.cnf << 'EOT' wsrep_on = ON wsrep_provider = /usr/lib/galera/libgalera_smm.so wsrep_cluster_name = "MariaDB Galera Cluster 01" wsrep_cluster_address = "gcomm://mdb01,mdb02,mdb03" binlog_format = row default_storage_engine = InnoDB innodb_autoinc_lock_mode = 2 innodb_force_primary_key = 1 innodb_doublewrite = 1 # Allow server to accept connections on all interfaces. bind-address = 0.0.0.0 port = 13306 # Optional settings wsrep_slave_threads = 2 innodb_flush_log_at_trx_commit = 0 wsrep_node_name = mdb01 wsrep_node_address = "192.168.7.32" # By default, MariaDB error logs are sent to journald, which can be hard to digest sometimes. # The following line will save error messages to a plain file. log_error = /var/log/mysql/error.log EOT Обратите внимание, параметры: ''wsrep_node_name'' и ''wsrep_node_address'' для каждой ноды должны быть свои Останавливаем MariaDB: systemctl stop mariadb systemctl status mariadb Только на первой ноде: galera_new_cluster На всех запускаем MariaDB и проверяем: systemctl start mariadb systemctl status mariadb ss -anoltup мы должны увидеть вместо стандартного mysql порта 1306 - наш 13306 Далее только на первой ноде, создаём супер администратора steller и пользователя для haproxy (чтобы он мог оценивать на сколько MariaDB жива): sudo mysql CREATE USER 'steller'@'%' IDENTIFIED BY 'very_secret_password'; CREATE USER 'haproxy'@'%'; GRANT ALL PRIVILEGES ON *.* TO 'steller'@'%' WITH GRANT OPTION; FLUSH PRIVILEGES; QUIT; не забудьте поменять пароль very_secret_password на ещё более секретный проверяем: echo "SELECT @@hostname;" | mariadb -h mdb03 -u steller -N -P 13306 -pvery_secret_password попробовать залогиниться на все сервера, попробовать на каждом создать базу данных и увидеть что она появляется на всех остальных Статус локальной ноды в кластере: echo "SELECT * FROM information_schema.GLOBAL_STATUS WHERE \`VARIABLE_NAME\` LIKE 'WSREP_LOCAL_STATE_COMMENT';" | mariadb Важнейший параметр кластера: echo "SELECT * FROM information_schema.GLOBAL_STATUS WHERE \`VARIABLE_NAME\` LIKE 'WSREP_CLUSTER_WEIGHT';" | mariadb показывает количество рабочих серверов в кластере по мнению локальной ноды == Установка, настройка haproxy и keepalived == https://kifarunix.com/configure-highly-available-haproxy-with-keepalived-on-ubuntu/ apt install haproxy файл /etc/haproxy/haproxy.cfg должен выглядеть примерно так: global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners stats timeout 30s user haproxy group haproxy daemon # Default SSL material locations ca-base /etc/ssl/certs crt-base /etc/ssl/private # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384 ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 errorfile 400 /etc/haproxy/errors/400.http errorfile 403 /etc/haproxy/errors/403.http errorfile 408 /etc/haproxy/errors/408.http errorfile 500 /etc/haproxy/errors/500.http errorfile 502 /etc/haproxy/errors/502.http errorfile 503 /etc/haproxy/errors/503.http errorfile 504 /etc/haproxy/errors/504.http # stats dashboard listen stats_mdb01 bind :8080 mode http acl localhost src 192.168.7.32 127.0.0.1 stats enable if localhost stats realm Haproxy\ Statistics stats uri / stats refresh 10s listen galera_cluster bind *:3306 balance source mode tcp option mysql-check user haproxy option tcplog server mdb01 mdb01:13306 check weight 1 server mdb02 mdb02:13306 check weight 1 server mdb03 mdb03:13306 check weight 1 от ноды к ноде будут меняться только эти две строки: listen stats_mdb01 acl localhost src 192.168.7.32 127.0.0.1 запускаем, проверяем: systemctl is-enabled haproxy.service systemctl restart haproxy.service systemctl status haproxy.service ss -anoltup мы должны увидеть стандартный mysql порт 1306 - это наш балансировщик haproxy прикидывается сервером mysql когда настроим keepalived можно будет заходить на http://mdbc01.mosigra.su:8080/ и смотреть статистику активного балансировщика, но уже сейчас можно посмотреть по каждой ноде отдельно: http://mdb01.mosigra.su:8080/ http://mdb02.mosigra.su:8080/ http://mdb03.mosigra.su:8080/ устанавливаем keepalived apt install keepalived sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf sysctl -p настраиваем, для этого файл /etc/keepalived/keepalived.conf приводим к такому виду: # Global Settings for notifications global_defs { enable_snmp_vrrp enable_snmp_checker enable_snmp_rfc enable_traps } # Define the script used to check if haproxy is still working vrrp_script chk_haproxy { script "/usr/bin/killall -0 haproxy" interval 2 weight 2 } # Configuration for Virtual Interface vrrp_instance LB_VIP { interface eth0 state BACKUP # set to BACKUP on the peer machine priority 99 # set to 99 on the peer machine virtual_router_id 52 authentication { auth_type AH auth_pass sP41XTy6 # Password for accessing vrrpd. Same on all devices } unicast_src_ip 192.168.7.32 # Private IP address of master unicast_peer { 192.168.7.33 # Private IP address of the backup haproxy 192.168.7.34 } # The virtual ip address shared between the two loadbalancers virtual_ipaddress { 192.168.7.35 } # Use the Defined Script to Check whether to initiate a fail over track_script { chk_haproxy } } параметр virtual_router_id и блок authentication должен быть одинаковым на всех нодах, virtual_ipaddress тоже, это тот самый четвёртый вымышленный ip адрес который будет забирать себе активная нода для первой ноды state MASTER для остальных BACKUP priority - для первой 101, второй - 100, третьей - 99 unicast_src_ip - для каждой ноды свой ip адрес unicast_peer - для каждой ноды оставшиеся два ip адреса других нод запускаем, проверяем: systemctl is-enabled keepalived.service systemctl status keepalived.service systemctl start keepalived.service systemctl status keepalived.service посмотреть статус keepalived можно так: kill -USR2 $(cat /var/run/keepalived.pid) sleep 3 cat /tmp/keepalived.stats у BACKUP ноды значение Became master равно значению Released master у MASTER ноды значение Became master на один или более (не знаю как может получиться более) больше значения Released master не самый удобный способ смотреть статус keepalived поэтому вот косвенные способы: ip -br a s выполнить на всех нодах, та на которой высветится наш вымышленный ip та и MASTER нода. ещё вариант зайти на http://mdbc01.mosigra.su:8080/ и посмотреть имя узла статистики, во время настройки haproxy мы специально к имени stats добавили имя сервера == Мониторинг == cat /etc/sudoers.d/zabbix zabbix ALL = (root) NOPASSWD: /usr/local/sbin/keepalived_json.sh cat /usr/local/sbin/keepalived_json.sh #!/bin/bash kill -s $(keepalived --signum=JSON) $(cat /run/keepalived.pid) cat /tmp/keepalived.json rm /tmp/keepalived.json # tail -v -n +1 /etc/zabbix/zabbix_agentd.d/*.conf ==> /etc/zabbix/zabbix_agentd.d/Galera_by_Zabbix_agent.conf <== UserParameter=galera.json,echo "SELECT JSON_OBJECTAGG(VARIABLE_NAME, VARIABLE_VALUE) FROM information_schema.GLOBAL_STATUS WHERE \`VARIABLE_NAME\` LIKE 'WSREP%'; FLUSH STATUS;" | mysql -N ==> /etc/zabbix/zabbix_agentd.d/Keepalived_by_Zabbix_agent.conf <== UserParameter=keepalived.json,sudo /usr/local/sbin/keepalived_json.sh ==> /etc/zabbix/zabbix_agentd.d/Linux_lxc_by_Zabbix_agent.conf <== UserParameter=ct.memory.size[*],free -bw | awk '$ 1 == "Mem:" {total=$ 2; used=($ 3+$ 6+$ 7); pused=(($ 3+$ 6+$ 7)*100/$ 2); free=$ 4; buffers=$ 6; cached=$ 7; available=$ 8; pavailable=($ 8*100/$ 2); if("$1" == "") {printf("%.0f", total )} else if("$1" == "pused" || "$1" == "pavailable") {printf("%f", $1 "" )} else {printf("%.0f", $1 "" )} }' | sed 's/,/./' UserParameter=ct.swap.size[*],free -b | awk '$ 1 == "Swap:" {total=$ 2; used=$ 3; free=$ 4; pfree=($ 4*100/$ 2); pused=($ 3*100/$ 2); if("$1" == "") {printf("%.0f", free )} else if ("$1" == "pfree" || "$1" == "pused") {printf("%f", $1 "" )} else {printf("%.0f", $1 "" )} }' | sed 's/,/./' UserParameter=ct.cpu.load[*],uptime | awk -F', +| +' '{avg1=$(NF-2); avg5=$(NF-1); avg15=$(NF)}{ if ("$1" == "percpu") {print $2/'$(nproc)'} else {print $2}}' | sed 's/,/./' UserParameter=ct.uptime,cut -d"." -f1 /proc/uptime ==> /etc/zabbix/zabbix_agentd.d/MySQL_by_Zabbix_agent.conf <== #template_db_mysql.conf created by Zabbix for "Template DB MySQL" and Zabbix 4.2 #For OS Linux: You need create .my.cnf in zabbix-agent home directory (/var/lib/zabbix by default) #For OS Windows: You need add PATH to mysql and mysqladmin and create my.cnf in %WINDIR%\my.cnf,C:\my.cnf,BASEDIR\my.cnf https://dev.mysql.com/doc/refman/5.7/en/option-files.html #The file must have three strings: #[client] #user='zbx_monitor' #password='' # UserParameter=mysql.ping[*], mysqladmin -h"$1" -P"$2" ping UserParameter=mysql.get_status_variables[*], mysql -h"$1" -P"$2" -sNX -e "show global status" UserParameter=mysql.version[*], mysqladmin -s -h"$1" -P"$2" version UserParameter=mysql.db.discovery[*], mysql -h"$1" -P"$2" -sN -e "show databases" UserParameter=mysql.dbsize[*], mysql -h"$1" -P"$2" -sN -e "SELECT COALESCE(SUM(DATA_LENGTH + INDEX_LENGTH),0) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='$3'" UserParameter=mysql.replication.discovery[*], mysql -h"$1" -P"$2" -sNX -e "show slave status" UserParameter=mysql.slave_status[*], mysql -h"$1" -P"$2" -sNX -e "show slave status" == Проверка == С удалённого компа: echo "SELECT @@hostname;" | mariadb -h mdbc01.mosigra.su -u steller -N -pvery_secret_password увидим имя сервера который реально обработал SQL запрос