[TOC]
0x00 记一次在K8s集群搭建的MySQL主从无法正常启动之数据迁移恢复实践 描述: 在K8s集群中里利用bitnami
提供的mysql:5.7.32-debian-10-r61
镜像并利用helm进行MySQL集群的部署安装, 在进行网络调整后发现mysql-master-0
pod无法正常启动,导致MySQL数据库无法访问,同时设定的root密码被更改导致无法提取持久化目录中相关数据信息,我们可以依据如下方式进行错误排查以及数据恢复。
前置知识
环境说明:
[TOC]
0x00 记一次在K8s集群搭建的MySQL主从无法正常启动之数据迁移恢复实践 描述: 在K8s集群中里利用bitnami
提供的mysql:5.7.32-debian-10-r61
镜像并利用helm进行MySQL集群的部署安装, 在进行网络调整后发现mysql-master-0
pod无法正常启动,导致MySQL数据库无法访问,同时设定的root密码被更改导致无法提取持久化目录中相关数据信息,我们可以依据如下方式进行错误排查以及数据恢复。
前置知识
环境说明: 1 2 3 4 5 6 7 Kubernetes 集群版本: v1.22.2 mysql 镜像及其版本: docker.io/bitnami/mysql:5.7.32-debian-10-r61 kubectl get pod -n database -l app=mysql
操作流程:
Step 0.操作任何数据之前,第一要务就是必须要进行数据备份,防止在操作的过程中对数据造成破坏。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 $ kubectl get pvc -n database | grep "mysql" data-mysql-master-0 Bound pvc-4bef6f99-8a7a-47f4-8517-18721fa5d724 8Gi RWO nfs-devops 304d data-mysql-slave-0 Bound pvc-2e5de4c5-a1a4-4c79-8e5b-fc21b66d6221 8Gi RWO nfs-devops 304d $ kubectl describe pv -n database pvc-4bef6f99-8a7a-47f4-8517-18721fa5d724 | grep "Path" Path: /Kubernetes/pvc/devops/database-data-mysql-master-0-pvc-4bef6f99-8a7a-47f4-8517-18721fa5d724 $ cp -a /Kubernetes/pvc/devops/database-data-mysql-master-0-pvc-4bef6f99-8a7a-47f4-8517-18721fa5d724 /tmp/mysql-backup $ ls /tmp/mysql-backup/data | head -n 15 auto.cnf ca-key.pem ca.pem client-cert.pem client-key.pem auth ib_buffer_pool ibdata1 ib_logfile0 ib_logfile1 ibtmp1 msg my_database mysql mysql-bin.000001
Step 1.K8s中资源服务清单部署的应用无法启动错误信息排查思路。1 2 3 4 5 6 7 8 kubectl get sts -n database mysql-master kubectl logs -f --tail 50 -n database mysql-master-0 kubectl describe pod -n database mysql-master-0 kubectl get pod -n database -l app=mysql
Step 2.通过前面错误信息我知道了,mysql-master-0 Pod无法启动的原因是,因为该资源清单了设置Pod健康检查即Liveness
探针与Readiness
探针,而正是因为root密码被修改导致Pod无法重新启动,从而导致无法正常提供服务。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 livenessProbe: exec : command : - sh - -c - | password_aux="${MYSQL_ROOT_PASSWORD:-} " if [ -f "${MYSQL_ROOT_PASSWORD_FILE:-} " ]; then password_aux=$(cat $MYSQL_ROOT_PASSWORD_FILE ) fi mysqladmin status -uroot -p$password_aux failureThreshold: 3 initialDelaySeconds: 120 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 readinessProbe: exec : command : - sh - -c - | password_aux="${MYSQL_ROOT_PASSWORD:-} " if [ -f "${MYSQL_ROOT_PASSWORD_FILE:-} " ]; then password_aux=$(cat $MYSQL_ROOT_PASSWORD_FILE ) fi mysqladmin status -uroot -p$password_aux failureThreshold: 3 initialDelaySeconds: 30 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1
Step 3.查看database名称空间下的secrets资源中设定的mysql相关凭据(默认以Base64编码)。1 2 3 4 5 6 7 $ kubectl get secrets -n database mysql -o yaml apiVersion: v1 data: mysql-password: dXNlcnBhc3N3ZA== mysql-replication-password: cmVwbGljYXRpb24= mysql-root-password: cm9vdHBhc3N3ZA== .....
Step 4.分别查看database名称空间下的mysql-master
和mysql-slave
的configMap配置文件(实际上配置差不多)。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 $ kubectl get cm -n database mysql-master -oyaml $ kubectl get cm -n database mysql-slave -oyaml apiVersion: v1 data: my.cnf: |- [mysqld] bind -address=0.0.0.0 port=3306 skip-name-resolve explicit_defaults_for_timestamp basedir=/opt/bitnami/mysql plugin_dir=/opt/bitnami/mysql/plugin socket=/opt/bitnami/mysql/tmp/mysql.sock datadir=/bitnami/mysql/data tmpdir=/opt/bitnami/mysql/tmp pid-file=/opt/bitnami/mysql/tmp/mysqld.pid log -error=/opt/bitnami/mysql/logs/mysqld.log character-set-server=UTF8 collation-server=utf8_general_ci max_allowed_packet=160M default_authentication_plugin=mysql_native_password [client] port=3306 socket=/opt/bitnami/mysql/tmp/mysql.sock default-character-set=UTF8 plugin_dir=/opt/bitnami/mysql/plugin [manager] port=3306 socket=/opt/bitnami/mysql/tmp/mysql.sock pid-file=/opt/bitnami/mysql/tmp/mysqld.pid
Step 5.前面说到由于mysql数据库的root密码被修改无法通过Pod容器探针检测所以无法启用, 所以我们可以先将资源清单中的livenessProbe与readinessProbe这两部分先停用,以恢复业务正常运行,等待晚上访问流量较小时,关闭应用进行停机维护重置root密码,此时我们可以进行如下操作。
1 2 kubectl edit cm -n database mysql-master
Step 6.等待 mysql-master-0
Pod运行成功正常后进入到容器内部shell之中,随之执行如下命令。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 kubectl exec -it -n database mysql-master-0 bash mysql -u root -p mysql> status; mysql> update mysql.user set authentication_string = password("rootpasswd" ) where user="root" ; mysql> update mysql.user set authentication_string = password("userpasswd" ) where user="user" ; mysql> update mysql.user set authentication_string = password("replication" ) where user="replicator" ; mysql> flush privileges; mysql> select host,user,authentication_string from mysql.user; +-----------+---------------+-------------------------------------------+ | host | user | authentication_string | +-----------+---------------+-------------------------------------------+ | % | user | *FBBDC6FD2E******A97D36A86BEAC3 | | % | root | *88CFEE431A******C570D24CEB3C7A167F | | localhost | mysql.sys | *THISISNOTA******SSWORDTHATCANBEUSEDHERE | | % | replicator | *32005F59F5******E5AA8898DE51D456CD90 | | localhost | mysql.session | *THISISNOTA******ORDTHATCANBEUSEDHERE | +-----------+---------------+-------------------------------------------+ 5 rows in set (0.00 sec)
Step 7.修改完成后将 mysql-master 的 configMap 设置的 my.cnf 配置文件中的 skip-grant-tables
字符串去掉,重启Pod即可。1 2 3 4 kubectl get pod -n database -l app=mysql
至此, MySQL集群故障恢复完成! 除此之外我们还可以通过独立的Docker容器将其数据备份出来,例如下节的数据迁移恢复 。
数据迁移恢复
Step 1. 准备一份配置文件给docker单独部署的容器进行数据恢复使用,我们需要在配置中加入 skip-grant-tables 参数, 忽略root密码进行登陆到mysql中。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 tee /tmp/my.cnf <<'EOF' [mysqld] bind -address=0.0.0.0port=3306 skip-grant-tables skip-name-resolve explicit_defaults_for_timestamp basedir=/opt/bitnami/mysql socket=/opt/bitnami/mysql/tmp/mysql.sock datadir=/bitnami/mysql/data tmpdir=/opt/bitnami/mysql/tmp pid-file=/opt/bitnami/mysql/tmp/mysqld.pid log -error=/opt/bitnami/mysql/logs/mysqld.logcharacter-set-server=UTF8 collation-server=utf8_general_ci max_allowed_packet=16M default_authentication_plugin=mysql_native_password [client] port=3306 socket=/opt/bitnami/mysql/tmp/mysql.sock default-character-set=UTF8 [manager] port=3306 socket=/opt/bitnami/mysql/tmp/mysql.sock pid-file=/opt/bitnami/mysql/tmp/mysqld.pid EOF
Step 2.执行如下命令,并利用前面备份的持久化数据的文件创建一个新的MySQL数据库容器。1 2 3 4 5 6 7 8 9 10 11 12 13 14 docker run -d --name mysql \ -e BITNAMI_DEBUG=true \ -e ALLOW_EMPTY_PASSWORD=yes \ -e MYSQL_AUTHENTICATION_PLUGIN=mysql_native_password \ -e MYSQL_USER=user -e MYSQL_PASSWORD=userpasswd \ -v /tmp/mysql-backup/data:/bitnami/mysql/data \ -v /tmp/my.cnf:/opt/bitnami/mysql/conf/my.cnf \ -v /tmp/logs:/opt/bitnami/mysql/logs \ -p 32160:3306 \ bitnami/mysql:5.7.32-debian-10-r61 docker logs -f --tail 50 mysql
Step 3.同样进入到mysql容器内部shell中执行如下命令, 查看并导出相应数据库的sql文件。1 2 3 4 5 6 7 8 9 10 11 12 docker exec -it mysql bash mysql -u root -p mysql> show databases; | auth | | msg | | my_database | cd /opt/bitnami/mysql/logsmysqldump -uroot -p --default-character-set=UTF8 --databases auth --hex-blob --result-file=auth.sql mysqldump -uroot -p --default-character-set=UTF8 --databases msg --hex-blob --result-file=msg.sql mysqldump -uroot -p --default-character-set=UTF8 --databases my_database --hex-blob --result-file=my_database.sql
Step 4.在本机的/tmp/logs
目录中我们可以查看到mysqldump出的sql文件。1 2 ls /tmp/logs auth.sql msg.sql my_database.sql mysqld.log
Step 5.如果需要外部使用该Docker搭建的MySQL数据库,你需要更改用户对应的账号密码并刷新权限,在my.cnf配置文件中去除skip-grant-tables
字段,并重启容器即可。1 2 3 4 $ docker restart mysql $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c72268dc95cf bitnami/mysql:5.7.32-debian-10-r61 "/opt/bitnami/script…" 11 days ago Start (0) 29 hours ago 0.0.0.0:3306 mysql
至此,K8s集群搭建的MySQL数据库迁移恢复实践完毕!