OS : CentOS 7.9 64bit
MySQL : 8.0.30 - commercial
Replica Set : 1(Soure), 2(Replica)
Server : 10.64.23.239 (Source, HAproxy), 10.64.23.240(Replica), 10.64.23.242(Replica), 10.64.23.243(VIP)
지난 포스팅에서, MySQL Replication 환경의 MHA 구축을 다루었습니다.
이번에는, MySQL Enterprise에서 사용할 수 있는 MySQL Router 처럼, 오픈소스인 HAproxy를 이용해 부하 분산 테스트를 하도록 하겠습니다.
MySQL Router와 같이, 기존의 하드웨어 스위치를 대체하는 소프트웨어 로드 밸런서입니다.
여기서 로드 밸런싱이란, 부하 분산을 위해서 여러 대의 서버에 접속을 분배하는 기능을 말합니다.
쉽게 말해, 실사용자가 Replica Set 중 어떤 Node에 접근할지 판단해주는 중간 프록시 역할입니다.
HAProxy는 HTTP 웹소켓 통신에서도 자주 사용됩니다.
이번 포스팅을 HAproxy + MHA로 묶은 이유는, MHA의 VIP를 이용한 자동 HA 구현과 동시에, 앞서 소개한 HAproxy의 로드 밸런싱을 모두 잡기 위함입니다.
앞서 HAproxy를 소개할 때 MySQL Router를 잠깐 언급했는데요. MySQL Router와 HAproxy는 기능적으로 Read/Write 서비스를 분산한다거나 하는 로드 밸런싱이 주 목적인 것은 같습니다.
하지만 개인적인 생각으로, MySQL Router는 벤더 공식 제품인 Group Replication을 이용한 Innodb Cluster에 초점이 맞춰져 있다고 생각됩니다.
대표적으로 Read/Write 서비스를 단순 Replication + MySQL Router 세트로 가져갈 때, Primary Failover와, Replica Health Check를 따로 진행하지 않습니다.
물론 라우터 옵션의 routing_strategy를 first_available, round-robin-with-fallback 등으로 사용하여 이용 가능하긴 하지만, 직관적인 관리가 힘듭니다.
routing_strategy = first-available
mode = read-write
destinations = node1, node2, node3
....
routing_strategy = round-robin-with-fallback
mode = read-only
destinations = node1, node2, node3
추가로, MySQL Router는 DB Connection을 체크 할 뿐이지, 이 Node가 Primary인지 Replica인지 구분하지 않으므로 위 예시의 read-write 서비스의 경우 replica node 접근 시 write 서비스가 불가능 할 수 있습니다.
(물론 이 경우는 HAproxy도 MHA를 쓰지 않는 환경이라면 같습니다.)
HAproxy는 지정된 스크립트로 기록된 노드의 상태를 지정한 시간마다 체크하여 Health Check합니다.
커스텀 스크립트는 자율적으로 사용할 수 있으므로, Primary / Replica는 물론, 디테일하게 이 Node가 어떤 Node 인지도 판단할 수 있습니다.
listen mysql-primary-write
bind *:3307
mode tcp
option external-check
external-check path "/usr/bin:/bin"
## 아래 작업으로 주기적 체크 진행
external-check command /etc/haproxy/script/mysql_primary_chk.sh
option allbackups
server primary 10.64.23.243:3306 check inter 1s on-marked-down shutdown-sessions
...
listen mysql-secondary
bind *:3309
mode tcp
balance roundrobin
option external-check
external-check path "/usr/bin:/bin"
## 아래 작업으로 주기적 체크 진행
external-check command /etc/haproxy/script/mysql_replica_chk.sh
option allbackups
server node1 10.64.23.239:3306 check inter 1s on-marked-down shutdown-sessions
server node2 10.64.23.240:3306 check inter 1s on-marked-down shutdown-sessions
server node3 10.64.23.242:3306 check inter 1s on-marked-down shutdown-sessions
HAproxy의 설치 과정은 HAproxy Github의 tarball 이나, rpm을 풀어 설치하면 되는데, 설치 과정은 많은 포스팅에 있기에...
생략하고 MySQL의 HAproxy 환경에서의 중요 확인사항을 확인하겠습니다.
HAproxy는 그저 바인딩 된 IP:Port로 커넥션 유입 시, 위 예시처럼 아래의 노드를 체크하여 커넥션을 맺어주는 역할입니다.
그래서 Primary, Replica Node의 Health Check 커스텀 스크립트가 가장 중요한데요, 해당 스크립트는 Hoing 님 포스팅에서, 아주 좋은 예시가 있습니다.
상용 버전을 사용중이라 그런지.. MySQL Version 체크 부분에서 오류가 발생했습니다.
Primary 체크 중 45번 째 라인에서 발생한 오류입니다.
SELECT substr(version(),5,3);
+-----------------------+
| substr(version(),5,3) |
+-----------------------+
| 30- |
+-----------------------+
커뮤니티 버전을 테스트해보진 않았는데, 마이너 버전 30 이후로 하이픈(-)까지 나오는 현상이 있어, 혹여 Health Check 중 Integer 관련 오류가 발생한다면, 해당 스크립트를 (5,3)이 아닌 (5,2)로 변경하면 됩니다.
HAproxy는 기본적으로 statstics 페이지를 제공하는데요, 현재 구성은 아래와 같습니다.
listen stats
bind *:9000
mode http
option dontlog-normal
stats enable
stats realm Haproxy\ Statistics
stats uri /haproxy
stats refresh 1s
http-request use-service prometheus-exporter if { path /metrics }
해당 URL(http://10.64.23.239:9000/haproxy)로 접근하면 현재 관제 대상인 Node들의 상태를 확인할 수 있습니다.
mysql-secondary의 node1이 DOWN(빨간색)으로 표기 된 이유는, 현재 node1이 Primary Node이기 때문입니다.
기존 HAproxy와 다른 점은, write service(mysql primary-write 섹션)의 Node 체크를 VIP를 통해 이루어집니다.
listen mysql-primary-write
...
server primary 10.64.23.243:3306 check inter 1s on-marked-down shutdown-sessions
HAproxy를 구성 후, Load Blancing이 정상적으로 이루어지는지, sysbench로 테스트 해보겠습니다.
현재 상태는 위 HAproxy Stastics 페이지와 같으며, 세부 정보는 아래와 같습니다.
Primary(node1) : 10.64.23.239 (10.64.23.243)
Replica(node2) : 10.64.23.240
Replica(node3) : 10.64.23.242
PMM이나 MySQL Enterprise Monitor 등 모니터링 툴로 관제도 가능하지만, general log를 통해 디테일하게 수행 과정을 확인하겠습니다.
(node 2, 3) - General Log
SELECT @@general_log;
+---------------+
| @@general_log |
+---------------+
| 0 |
+---------------+
1 row in set (0.00 sec)
SET GLOBAL general_log= 1;
mysql> SELECT @@general_log;
+---------------+
| @@general_log |
+---------------+
| 1 |
+---------------+
tail -f로 general_log의 변경분을 실시간 체크하겠습니다.
(node 1) - sysbench
Prepare 진행 후 Run
sysbench --mysql-host=10.64.23.239 --mysql-port=3309 --mysql-user=test --mysql-password=123 --report-interval=2 --mysql-db=sysbench --table_size=5000000 --warmup-time=120 --threads=4 --tables=10 /sysbench/sysbench/share/sysbench/oltp_read_only.lua run
해당 커맨드 수행 시, 10.64.23.239:3309로 접근하여 olte_read_only 테스트를 수행합니다.
여기서 3309 포트는, haproxy에 설정된 Replica Node 포트입니다.
node2와, node3에 Round-Robin 형식으로 sbtest 테이블, 즉 sysbench 테스트가 진행됨을 볼 수 있습니다.
이번 포스팅은 MHA로 Failover를 테스트하지 않고, 그저 HAproxy를 사용하여 Replica의 Read Service 부하 분산 테스트를 해보았습니다.
sysbench는 테스트 도중 오류가 발생하면 테스트를 중단하는데요, ignore-errors를 적용하여 진행해도 테스트 결과 제대로 진행되지 않았습니다.
다음 포스팅은, jmeter를 사용하여 부하분산 테스트 중, Primary(node 1)를 shutdown 시켜, node2를 Primary로 승격하여 무중단 테스트가 가능한지 포스팅 하도록 하겠습니다.