STONITH (Shoot The Other Node In The Head)
재설정하거나 전원을 차단하여 문제가 생긴 노드를 클러스터에서 제외 시키는 테크닉
multi-DC 구조에서 ProxySQL이 routing 과 proxying 을 해주는데 DC1 번의 primary MySQL 노드에서 잠시 이상이 생겼을 때 Orachestrator health check 에서 이상이 생김을 감지하고 DC2 의 다른 노드를 primary로 승격시킬 수 있다.
하지만 잠깐 동안 발생했던 문제의 DC1 의 노드가 정상으로 돌아올 때 문제가 발생할 수 있다. ProxySQL이 이 노드를 다시 read-write 가 가능하다고 지정하려는 경쟁적인 상황이 발생할 수 있고, Orchestrator 가 다시 node를 먼저 찾게 도록 ProxySQL 에서 offline 기간을 늘릴 수 있다. 이 때 예측 가능한 행위를 할 수 있도록하는 추가적인 계층이 필요한데 이게 STONITH로 노드가 cluster 에서 제외되면서 발생할 수 있는 위험성을 줄이기 위해 사용한다.
Orchestrator hook 을 이용하지만 ProxySQL 의 내장된 Scheduler를 통해서 더 쉽게 구현할 수 있다. downtimed로 마킹된 노드를 Orchestrator를 참조하여 proxysql 에서 동일하게 표시되도록 하는 proxy-oc-tool.sh 스크립트를 활용한다.
- MySQL node1이 fail 상태일 때 Orchestrator는 node2를 새로운 Primary로 선택한다.
- node1 이 read_only 상태를 변경하거나 replication을 업데이트할 수 없는 연결 불가 상태일 때 복구 불가 상태로 downtimed 로 표시된다.
- node1 이 online 이 되면 ProxySQL이 Orchestrator 보다 먼저 확인하여 다시 클러스터에 조인 시킬 수 있다. 이 때 호스트 그룹에 2개의 쓰기 가능 노드가 생길 수 있다.
- 이 상황을 방지하기 위해 Orachestrator가 downtime으로 마킹하자마자 스크립트는 OFFLINE_SOFT로 변경하고 ProxySQL에서 쓰기가능한 그룹에 조인되지 못하도록 한다.
- 여기서 node1을 한번 수정하면 replica로 다시 붙여지고 downtimed 표시가 삭제된다. 그리고 자동으로 ONLINE 으로 표시를 변경한다.
- 또한 DC1이 DC2 및 AWS에서 완전히 연결이 끊긴 경우 Orchestrator의 raft-leader에 연결할 수 없으며 모든 노드를 OFFLINE_SOFT로 설정하여 DC1에서 isolated 쓰기를 방지한다.
ProxySQL에 스크립트를 추가하는 방법
* 권한 조정
https://gist.githubusercontent.com/dotmanila/1a78ef67da86473c70c7c55d3f6fda89/raw/b671fed06686803e626c1541b69a2a9d20e6bce5/proxy-oc-tool.sh
chmod 0755 proxy-oc-tool.sh
mv proxy-oc-tool.sh /usr/bin/
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
export ORCHESTRATOR_API="$1"
OC=orchestrator-client
PSQL='mysql --defaults-file=/etc/proxysql/user.cnf -P6032 -h127.1'
VER=$(date +%s)
$OC -c raft-leader > /dev/null 2>&1
HASQUORUM=$?
if [ "x${HASQUORUM}" != "x0" ]; then
echo "Orchestrator quorum is lost!"
sessions=$($PSQL -BNe "select SessionID from stats_mysql_processlist" | xargs)
echo "Terminating existing connections $sessions"
if [ ! -z "$sessions" -a "$sessions" != " " ]; then
for session in $sessions; do
echo "KILL CONNECTION $session"
$PSQL -e "KILL CONNECTION $session";
done
fi
echo "Setting ALL to OFFLINE_SOFT"
$PSQL -BNe "UPDATE mysql_servers SET status = 'OFFLINE_SOFT', comment = 'proxysql-oc-helper-${VER}'"
$PSQL -BNe "LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;"
exit 0
fi
for h in $($OC -c downtimed|cut -d':' -f1); do
echo "Setting $h to OFFLINE_SOFT"
$PSQL -BNe "UPDATE mysql_servers SET status = 'OFFLINE_SOFT', comment = 'proxysql-oc-helper-${VER}' WHERE hostname = '$h'"
_status=$($PSQL -BNe "SELECT DISTINCT status FROM runtime_mysql_servers WHERE hostname = '$h'")
if [ "x${_status}" != 'xOFFLINE_SOFT' -a "x${_status}" != 'x' ]; then
$PSQL -BNe "LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;"
fi
done
_sql="SELECT hostname FROM mysql_servers WHERE status = 'OFFLINE_SOFT' AND comment LIKE 'proxysql-oc-helper-%' AND comment <> 'proxysql-oc-helper-${VER}'"
for h in $($PSQL -BNe "${_sql}"); do
echo "Setting $h back to ONLINE"
$PSQL -BNe "UPDATE mysql_servers SET status = 'ONLINE' WHERE hostname = '$h'"
$PSQL -BNe "LOAD MYSQL SERVERS TO RUNTIME; SAVE MYSQL SERVERS TO DISK;"
done
* ProxySQL 에서 scheduler 설정
INSERT INTO scheduler (interval_ms, filename)
VALUES (5000, '/usr/bin/proxy-oc-tool.sh');
LOAD SCHEDULER TO RUNTIME;
SAVE SCHEDULER TO DISK;
제외되는 노드는 read-only check 가 완료되기까지 약 10초 소요되기 때문에 이 간격을 ProxySQL에서 5초로 셋팅한다. 이 방법으로 ProxySQL보다 앞서 죽은 노드를 OFFLINE-SOFT로 마킹할 수 있도록 한다.
참조 :
https://www.percona.com/blog/2019/04/02/simple-stonith-proxysql-orchestrator/
'Database > MySQL, MariaDB' 카테고리의 다른 글
[MY-000068] [Server] unknown option '---'. (0) | 2022.09.13 |
---|---|
MySQL Group Replication 설정 순서 (0) | 2022.09.04 |
ProxySQL 2.3 - 향상된 Group 복제 운영 방식 (0) | 2022.09.04 |
MySQL HA (Orchestrator, ProxySQL, Consul) (0) | 2022.09.03 |
MySQL 백업, 복원 비교 (xtrabackup/mysqldump) (0) | 2019.03.28 |