월간 보관물: 2017 11월

galera cluster recovery scenario

galera cluster recovery scenario

 

http://galeracluster.com/documentation-webpages/gettingstarted.html 참조함.

galera cluster install
node 3대 준비.

귀찮으므로 3대 다 보안설정 없앰.
# systemctl stop firewalld
# setenforce 0

– yum repository 준비. 3 node 전부
[root@galera1 ~]# cat /etc/yum.repos.d/galera.repo
[galera]
name=galera
baseurl=http://ftp.kaist.ac.kr/mariadb//mariadb-10.0.33/yum/centos7-amd64/
gpgcheck=0
enabled=1
[root@galera1 ~]#

– install 3 node 전부
# yum install MariaDB-Galera-server MariaDB-client galera

– config file (node name과 node address 확인)
[root@galera1 ~]# grep -iv ‘^#\|^$’ /etc/my.cnf
[client-server]
!includedir /etc/my.cnf.d
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
binlog_format=ROW
bind-address=0.0.0.0
default_storage_engine=innodb
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=122M
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_provider_options=”gcache.size=300M; gcache.page_size=300M”
wsrep_cluster_name=”youngju_cluster”
wsrep_cluster_address=”gcomm://galera1,galera2,galera3
wsrep_sst_method=rsync
wsrep_node_name=galera1
wsrep_node_address=”10.11.10.171″
[mysql_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[root@galera1 ~]#

– mysql wsrep start
[root@galera1 ~]# service mysql start –wsrep-new-cluster
[root@galera1 ~]# tail -f /var/lib/mysql/galera1.test.dom.err

[root@galera1 mysql]# mysql -e “show status like ‘wsrep_%’; ” |grep -i ‘size\|stat’
wsrep_local_state_uuid 0889b7dd-d107-11e7-a4ab-5fe94a6d7f29
wsrep_local_state 4
wsrep_local_state_comment Synced
wsrep_cert_index_size 0
wsrep_evs_state OPERATIONAL
wsrep_cluster_size 1
wsrep_cluster_state_uuid 0889b7dd-d107-11e7-a4ab-5fe94a6d7f29
wsrep_cluster_status Primary
[root@galera1 mysql]#
– node 2
[root@galera2 ~]# grep -iv ‘^$\|^#’ /etc/my.cnf
[client-server]
!includedir /etc/my.cnf.d
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
binlog_format=ROW
bind-address=0.0.0.0
default_storage_engine=innodb
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=122M
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_provider_options=”gcache.size=300M; gcache.page_size=300M”
wsrep_cluster_name=”youngju_cluster”
wsrep_cluster_address=”gcomm://galera1,galera2,galera3
wsrep_sst_method=rsync
wsrep_node_name=galera2
wsrep_node_address=”10.11.10.172″
[mysql_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[root@galera2 ~]#

[root@galera2 ~]# service mysql start
[root@galera2 mysql]# mysql -e “show status like ‘wsrep_%’; ” |grep -i ‘size\|stat’
wsrep_local_state_uuid 0889b7dd-d107-11e7-a4ab-5fe94a6d7f29
wsrep_local_state 4
wsrep_local_state_comment Synced
wsrep_cert_index_size 0
wsrep_evs_state OPERATIONAL
wsrep_cluster_size 2
wsrep_cluster_state_uuid 0889b7dd-d107-11e7-a4ab-5fe94a6d7f29
wsrep_cluster_status Primary
[root@galera2 mysql]#
– node 3
[root@galera3 ~]# grep -iv ‘^$\|^#’ /etc/my.cnf
[client-server]
!includedir /etc/my.cnf.d
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
binlog_format=ROW
bind-address=0.0.0.0
default_storage_engine=innodb
innodb_autoinc_lock_mode=2
innodb_flush_log_at_trx_commit=0
innodb_buffer_pool_size=122M
wsrep_provider=/usr/lib64/galera/libgalera_smm.so
wsrep_provider_options=”gcache.size=300M; gcache.page_size=300M”
wsrep_cluster_name=”youngju_cluster”
wsrep_cluster_address=”gcomm://galera1,galera2,galera3
wsrep_sst_method=rsync
wsrep_node_name=galera3
wsrep_node_address=”10.11.10.173″
[mysql_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
[root@galera3 ~]#

[root@galera3 mysql]# mysql -e “show status like ‘wsrep_%’; ” |grep -i ‘size\|stat’
wsrep_local_state_uuid 0889b7dd-d107-11e7-a4ab-5fe94a6d7f29
wsrep_local_state 4
wsrep_local_state_comment Synced
wsrep_cert_index_size 0
wsrep_evs_state OPERATIONAL
wsrep_cluster_size 3
wsrep_cluster_state_uuid 0889b7dd-d107-11e7-a4ab-5fe94a6d7f29
wsrep_cluster_status Primary
[root@galera3 mysql]#
– galera cluster restart scenario
https://dba.stackexchange.com/questions/151941/how-to-restart-mariadb-galera-cluster
Solution 2:
Another way to restart a MariaDB Galera Cluster is to use –wsrep-new-cluster parameter.
1) Kill all mysql processes:
killall -KILL mysql mysqld_safe mysqld mysql-systemd
2) On the most up to date node start a new cluster:
/etc/init.d/mysql start –wsrep-new-cluster
3) Now other nodes can be connected:
service mysql start –wsrep_cluster_address=”gcomm://192.168.0.101,192.168.0.102,192.168.0.103” \
–wsrep_cluster_name=”my_cluster”

galera cluster restart scenario in kolla-ansible

kolla환경 galera cluster는 grastate.dat file에 seqno를 비교해서 가장 높은 놈을 mariadb bootstrap container로 만들어서 올린다. 이 때 safe_to_bootstrap가 0일 경우 1로 만들지는 않는다. galera는 wsrep_cluster_size가 1일 경우, 즉 마지막으로 살아남은 cluster member일 경우 safe_to_bootstrap을 1로 set한다. 만약 3 node 모두 seqno가 같고 safe_to_bootstrap가 0일 경우 kolla-ansible mariadb_recovery로 복구 불가능 하게 된다. 반드시 시간차를 두고 내리자. galera node 3대를 동시에 내릴 경우 이렇게 될 수 있는데 이러면 좀 난감한 상황이 된다.
이렇게 됐을 때 해결하는 방법에 대해 고민을 해봤다.

아래는 kolla-ansible mariadb_recovery가 실행하는 ansible playbook중 seqno를 비교 하는 구문이다.
# cat /usr/share/kolla-ansible/ansible/roles/mariadb/tasks/recover_cluster.yml

– name: Comparing seqno value on all mariadb hosts
shell: “if [[ {{ hostvars[inventory_hostname][‘seqno’] }} -lt {{ hostvars[item][‘seqno’] }} ]]; then echo {{ hostvars[item][‘seqno’] }}; fi”
with_items: “{{ groups[‘mariadb’] }}”
changed_when: false
register: seqno_compare

이게 controller01부터 controller03까지 순서대로 seqno를 각각 3번씩 총 9번을 비교하는데, 다 같으니까 결국엔 controller03이 bootstrap node가 되어버린다.

kolla환경 galera cluster의 경우 controller03 node의 mariadb docker container 에 –wsrep-new-cluster 가 하드코딩 되어 있어 항상 controller03이 먼저 start 되어야 한다. 그렇다면 controller03이 항상 가장 마지막에 멈추어야 seqno가 가장 높을 것이다.
kolla-ansible mariadb_recovery -i /etc/kolla/multinode 를 실행 하고 “TASK [mariadb : Waiting for MariaDB service to be ready]” 여기에서 진행이 안될텐데 이유는 controller03의 mariadb가 살아났다가 safe_to_bootstrap가 0이라서 바로 죽어버린것이 원인이다.
다음은 bootstrap이 된 node와 안그런 node의 docker inspect mariadb 의 diff 뜬 값이다.
[root@controller03 ~]# diff -u mariadb2 mariadb3
— controller02-docker-inspect-mariadb 2017-11-24 15:00:08.372199741 +0900
+++ controller03-docker-inspect-mariadb 2017-11-24 14:59:47.565970708 +0900

“StdinOnce”: false,
“Env”: [
“KOLLA_SERVICE_NAME=mariadb”,
+ “BOOTSTRAP_ARGS=–wsrep-new-cluster,
“KOLLA_CONFIG_STRATEGY=COPY_ALWAYS”,
“PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin“,
“KOLLA_BASE_DISTRO=centos”,

자 이제 controller03에서 /var/lib/docker/volumes/mariadb/_data/grastate.dat 안에 safe_to_bootstrap 을 1로 셋팅하자
이제 controller01과 controller02에서 계속 reboot되고 있는 mariadb를 docker stop mariadb로 죽인 후,
다시 kolla-ansible mariadb_recovery -i /etc/kolla/multinode를 실행 하면 잘 끝날 것이다.

또 생길 수 있는 경우가 비정상 종료를 해서 seqno가 모두 -1인 경우이다.
이러면 좀 수고롭게 찾아야 되는데 각 node에서 galera.cnf file에서 아래 두줄을 comment처리를 하고 1 node에서만 돌게끔 한다.
[root@controller02 ~]# vim /etc/kolla/mariadb/galera.cnf

#wsrep_cluster_address = gcomm://10.10.10.11:4567,10.10.10.12:4567,10.10.10.13:4567
#wsrep_provider_options = gmcast.listen_addr=tcp://10.10.10.12:4567;ist.recv_addr=10.10.10.12:4568

[root@controller02 ~]# docker start mairadb
[root@controller02 ~]# docker exec -it -u root mariadb mysql -u root -e “show status like ‘wsrep_last_committed’; ” -p
Enter password:
+———————-+———+
| Variable_name | Value |
+———————-+———+
| wsrep_last_committed | 3281877 |
+———————-+———+
이렇게 찾을 수 가 있다.

각 3 node에서 모두 seqno를 찾은 후 가장 높은 node의 /var/lib/docker/volumes/mariadb/ directory를 controller03의 /var/lib/docker/volumes/mariadb/ 으로 교체한다.
[root@controller03 volumes]# mv /var/lib/docker/volumes/mariadb{,-`date +%Y%m%d`-backup}
[root@controller03 volumes]# ls -altd /var/lib/docker/volumes/mariadb*
drwxr-xr-x 3 42434 42434 18 11월 24 20:50 /var/lib/docker/volumes/mariadb-20171125-backup

[root@controller02 ~]# scp -rp /var/lib/docker/volumes/mariadb/ controller03:/var/lib/docker/volumes/mariadb/

[root@controller03 volumes]# chwon -R 42434:42434 /var/lib/docker/volumes/mariadb

[root@cloud-deploy ~]# kolla-ansible mariadb_recovery -i /etc/kolla/multinode
root user로 scp를 이용하여 file을 옮겼기 때문에 owner가 root로 되어 있는데 반드시 42434(mysql)로 바꾸어 준다.

1개 node의 db만 있으면 복구가 가능하다.
[root@controller01 ~]# rm -rf /var/lib/docker/volumes/mariadb/_data/*
[root@controller03 ~]# rm -rf /var/lib/docker/volumes/mariadb/_data/*
[root@controller02 ~]# scp /var/lib/docker/volumes/mariadb/_data/grastate.dat controller03:/var/lib/docker/volumes/mariadb/_data/grastate.dat
[root@controller02 ~]# scp /var/lib/docker/volumes/mariadb/_data/grastate.dat controller01:/var/lib/docker/volumes/mariadb/_data/grastate.dat
[root@controller01 ~]# sed -i -e ‘s/seqno.*/seqno: -1/’ -e ‘s/safe_to_bootstrap: 1/safe_to_bootstrap: 0/’ /var/lib/docker/volumes/mariadb/_data/grastate.dat
[root@controller01 ~]# chown 42434:42434 -R /var/lib/docker/volumes/mariadb/_data/grastate.dat
[root@controller03 ~]# sed -i -e ‘s/seqno.*/seqno: -1/’ -e ‘s/safe_to_bootstrap: 1/safe_to_bootstrap: 0/’ /var/lib/docker/volumes/mariadb/_data/grastate.dat
[root@controller03 ~]# chown 42434:42434 -R /var/lib/docker/volumes/mariadb/_data/grastate.dat
[root@cloud-deploy ~]# kolla-ansible mariadb_recovery -i /etc/kolla/multinode
db 복구가 잘 되는것을 볼 수 있을 것이다.
이 때 grastate.dat file이 없으면 kolla-ansible mariadb_recovery가 진행 되지 않으므로 scp로 copy해서 위와 같은 작업을 하여 dummy file을 만들어 주자.