HAProxy + MariaDB Galera Cluster 구성을 하고 테스트를 진행하니 문제가 발생해서 글을 남겨본다.
HAProxy
haproxy.cfg 설정파일에서 아래 옵션을 사용
option mysql-check user haproxy
이 옵션은 TCP 포트로의 접속가능 여부만 판단해서 health check를 한다.
Galera Cluster의 경우 노드가 복구될 때 쿼리를 하면 아래 메시지가 출력된다.
WSREP has not yet prepared node for application use
따라서 이 경우는 HAProxy에서 노드를 살려줘서는 안된다.
MariaDB Galera Cluster
MariaDB [(none)] > show global status where variable_name='wsrep_local_state';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| wsrep_local_state | 4 |
+-------------------+-------+
동기화가 완료되서 사용이 가능한 상태값이다.
다른 상태값은 아래 링크에서 확인한다.
https://mariadb.com/docs/ent/ref/mdb/status-variables/wsrep_local_state/
HAProxy external-check
기존에 mysql-check를 외부 스크립트를 이용하도록 변경한다.
외부 스크립트는 wsrep_local_state 값을 읽어서 원하는 값이면 exit 0 을 리턴하고 다른값이면 exit 255를 리턴시켜주면 된다.
/etc/haproxy/haproxy.cfg
global
log /dev/log local0
log /dev/log local1 notice
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
external-check
insecure-setuid-wanted
frontend mysql-front
bind *:3306
mode tcp
default_backend mysql-back
backend mysql-back
mode tcp
#option mysql-check user haproxy
option external-check
external-check path "/usr/bin:/bin"
external-check command /etc/haproxy/script/check_node.sh
balance roundrobin
server db1 172.16.0.20:3306 check
server db2 172.16.0.21:3306 check backup weight 2
server db3 172.16.0.22:3306 check backup weight 1
- global 항목에 external-check 값이 추가되었다.
- external-check를 사용하기위해서 insecure-setuid-wanted 값을 추가해야한다
https://www.haproxy.com/blog/announcing-haproxy-2-2/#security-hardening - backend 항목에 기존 mysql-check 항목을 external-check로 변경
- external-check path 추가
- external-check command 추가
/etc/haproxy/script/check_node.sh
#!/bin/bash
MYSQL_HOST="$3"
MYSQL_PORT="$4"
MYSQL_USERNAME="haproxy"
MYSQL_PASSWORD=""
MYSQL_BIN="/bin/mysql"
MYSQL_OPTS="--no-defaults --connect-timeout=10 -snNE"
CMDLINE="$MYSQL_BIN $MYSQL_OPTS --host=$MYSQL_HOST --port=$MYSQL_PORT --user=$MYSQL_USERNAME -e"
WSREP_LOCAL_STATE_CHK=`$CMDLINE "SHOW GLOBAL STATUS WHERE VARIABLE_NAME='wsrep_local_state'" | tail -1`
if [ "$WSREP_LOCAL_STATE_CHK" != "4" ]; then
exit 255
fi
exit 0
파라메터 정보
$1 = Virtual Service IP (VIP)
$2 = Virtual Service Port (VPT)
$3 = Real Server IP (RIP)
$4 = Real Server Port (RPT)
$5 = Check Source IP
$3, $4를 이용해서 노드의 상태를 읽는다.