在Docker中部署GreatSQL并构建MGR集群

  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
为了方面社区用户体验GreatSQL,我们同时还提供Docker镜像,本文详细介绍如何在Docker中部署GreatSQL,并且构建一个MGR集群。
本文涉及的运行环境如下:
[root@greatsql]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)[root@greatsql]# uname -a Linux GreatSQL 3.10.0-1160.11.1.el7.x86_64 #1 SMP Fri Dec 18 16:34:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

1、安装Docker 直接用yum安装docker,非常省事。
[root@greatsql]# yum install -y docker

之后启动 docker 服务,并设置开机自启动。
[root@greatsql]# systemctl enable docker [root@greatsql]# systemctl start docker

2、拉取GreatSQL镜像,并创建容器 2.1 拉取镜像 拉取GreatSQL官方镜像:
[root@greatsql]# docker pull greatsql/greatsql docker pull greatsql/greatsql Using default tag: latest Trying to pull repository docker.io/greatsql/greatsql ... latest: Pulling from docker.io/greatsql/greatsql ... Digest: sha256:63eff1b099a75bb4e96b2c5bc7144889f6b3634a6163b56642a71a189183966c Status: Downloaded newer image for docker.io/greatsql/greatsql:latest

检查是否成功:
[root@greatsql]# docker images REPOSITORYTAGIMAGE IDCREATEDSIZE docker.io/greatsql/greatsqllatestd1963ef0c4033 days ago582 MB

2.2 创建新容器 之后,就可以直接创建一个新的容器了,先用常规方式。
[root@greatsql]# docker run -d \ --name mgr1 --hostname=mgr1 \ -p 3306:3306 -p 33060:33060 -p 33061:33061 \ -e MYSQL_ALLOW_EMPTY_PASSWORD=1 \ -e MYSQL_IBP=1G \ -e MYSQL_MGR_NAME='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa1' \ -e MYSQL_MGR_LOCAL='172.17.0.2:33061' \ -e MYSQL_MGR_SEEDS='172.17.0.2:33061,172.17.0.3:33061,172.17.0.4:33061' \ -e MYSQL_INIT_MGR=1 \ -e MYSQL_MGR_USER='repl' \ -e MYSQL_MGR_USER_PWD='repl' \ greatsql/greatsql

几个参数分别解释如下:
【在Docker中部署GreatSQL并构建MGR集群】在Docker中部署GreatSQL并构建MGR集群
文章图片

greatsql/greatsql,是镜像名,也可以指定为镜像的ID,例如 d1963ef0c403。
如果不想让 root 账户使用空密码,可以把 MYSQL_ALLOW_EMPTY_PASSWORD=1 参数替换成诸如 MYSQL_ROOT_PASSWORD='GreatSQL3#)^' 或者指定随机密码 MYSQL_RANDOM_ROOT_PASSWORD=1 即可。
当启用选项 MYSQL_INIT_MGR=1 时,会自动创建MGR所需的账户,并执行 CHANGE MASTER TO 指定MGR复制通道。
若没有同时指定 MYSQL_MGR_USER 或 MYSQL_MGR_USER_PWD 的话,则采用各自的默认值创建MGR账户。
这就成功创建一个新的容器了,并且会自动完成GreatSQL的初始化并启动。
2.3 容器管理 先确认容器的状态:
[root@greatsql]# docker ps -a CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 2e277c852f52d1963ef0c403"/docker-entrypoin..."4 minutes agoUp 12 minutes3306/tcp, 33060-33061/tcpmgr1

看到容器状态是Up的,表示已正常启动了。
再进入容器查看:
[root@greatsql]# docker exec -it mgr1 /bin/bash [root@mgr1 ~]# mysqladmin ver mysqladminVer 8.0.23-14 for Linux on x86_64 (GreatSQL (GPL), Release 14, Revision) ... Server version8.0.23-14 Protocol version 10 ConnectionLocalhost via UNIX socket UNIX socket/data/GreatSQL/mysql.sock Uptime:11 min 19 secThreads: 2Questions: 2Slow queries: 0Opens: 120Flush tables: 3Open tables: 36Queries per second avg: 0.002

看到容器已经完成初始化,并且可以直接无密码登入。
查看MGR账户及相应复制通道:
[root@GreatSQL][(none)]> show grants for repl; +----------------------------------------------+ | Grants for repl@%| +----------------------------------------------+ | GRANT REPLICATION SLAVE ON *.* TO `repl`@`%` | | GRANT BACKUP_ADMIN ON *.* TO `repl`@`%`| +----------------------------------------------+[root@GreatSQL][none]> select * from performance_schema.replication_group_members; +---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME| MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier |||NULL | OFFLINE||| +---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+

还可以把这个容器当做服务对其进行关闭、启动、重启、挂起等操作:
killKill one or more running containers pausePause all processes within one or more containers psList containers restartRestart one or more containers rmRemove one or more containers startStart one or more stopped containers stopStop one or more running containers unpauseUnpause all processes within one or more containers updateUpdate configuration of one or more containers waitBlock until one or more containers stop, then print their exit codes

可以自行挨个尝试。
2.4 容器销毁 如果想要销毁该容器,需要先停止该容器后,再执行 docker rm [容器ID|容器名] 命令即可:
[root@greatsql]# docker stop mgr1

[root@greatsql]# docker rm mgr1

如果是想销毁某个镜像,运行 docker rmi [镜像ID|镜像名] 命令即可,不过要先确保该镜像目前没有被其他容器所使用后,方可删除:
[root@greatsql]# docker rmi greatsql/greatsql

销毁容器、镜像之后,相应的数据目录也不再需要了,可以执行下面的命令清除:
[root@greatsql]# docker volume prune WARNING! This will remove all volumes not used by at least one container. Are you sure you want to continue? [y/N] y Deleted Volumes: 5a68a6286361f92430dbc4c1a2d1bd65a2db707274bd4d3dd9d53cdf58a5ac5f 3ae2211c61187371c312a606e36bc361e549e830ab5896356e7a920266574666 cbbfa248d2fc827d92ceac231b52b61ab7cfe92479f2e84969bd516dd211416f 1c95278033575062b7f15e3e3f1319290d8dcfc7caba1c50b47592f665ba5456Total reclaimed space: 13.08 GB

3、构建MGR集群 跨宿主机之间的docker容器网络通信相对麻烦一些,为了简单起见,本次先在单机环境下构建由3个docker容器组成的MGR集群。
3.1 创建专用子网 首先创建一个用于MGR集群的网络:
[root@greatsql]# docker network create mgr-net[root@greatsql]# docker network ls NETWORK IDNAMEDRIVERSCOPE 70c3ac08c7a9bridgebridgelocal 3a480a3ec570hosthostlocal 191d6d902b26mgr-netbridgelocal 1e3e6267dcdanonenulllocal

查看这个子网的配置信息:
[root@greatsql]# docker inspectmgr-net [ { "Name": "mgr-net", ... "Subnet": "172.18.0.0/16",<-- 网段 "Gateway": "172.18.0.1"<-- 网关 ...

3.2 创建3个新容器 分别启动三个docker容器:
[root@greatsql]# docker run -d \ --name mgr1 --hostname=mgr1 --net=mgr-net \ -e MYSQL_ALLOW_EMPTY_PASSWORD=1 \ -e MYSQL_MGR_LOCAL='172.18.0.2:33061' \ -e MYSQL_MGR_SEEDS='172.18.0.2:33061,172.18.0.3:33061,172.18.0.4:33061' \ -e MYSQL_INIT_MGR=1 \ greatsql/greatsql

后面的两个实例,只把 --name 和 --hostname 参数中的mgr1改成mgr2、mgr3,并且把 -e MYSQL_MGR_LOCAL='172.18.0.2:33061' 参数的的IP地址递增,例如 -e MYSQL_MGR_LOCAL='172.18.0.3:33061'。
查看容器运行状态:
[root@greatsql]# docker ps -a CONTAINER IDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 1bcd23c6f378d1963ef0c403"/docker-entrypoin..."2 minutes agoUp 2 minutes3306/tcp, 33060-33061/tcpmgr3 9d12ab273d81d1963ef0c403"/docker-entrypoin..."2 minutes agoUp 2 minutes3306/tcp, 33060-33061/tcpmgr2 56fd564a1789d1963ef0c403"/docker-entrypoin..."4 minutes agoUp 4 minutes3306/tcp, 33060-33061/tcpmgr1

分别查看3个容器的IP地址:
[root@greatsql]# docker inspect mgr1 | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "172.18.0.2", "IPAddress": "172.18.0.2",

第一个容器的IP地址是 172.18.0.2,另外两个容器分别是 172.18.0.3、172.18.0.4(递增关系)。
因为我启动容器时指定的新创建的网络 mgr-net,所以是 172.18.0.0/24 网段。如果不指定新创建的网络,则默认应该是 172.17.0.0/24 网段,注意区别。
编辑三个容器下的 /etc/hosts 文件,加入所有节点的hostname配置:
172.18.0.2 mgr1 172.18.0.3 mgr2 172.18.0.4 mgr3

提醒:docker容器重启后,容器里的 /etc/hosts 文件内容会重置,所以建议用映射volumes的方式挂进来。
在宿主机上编辑好一个文件 /data/docker/hosts:
[root@greatsql]# cat /data/docker/hosts127.0.0.1 localhost.localdomain localhost 127.0.0.1 localhost4.localdomain4 localhost4::1 localhost.localdomain localhost ::1 localhost6.localdomain6 localhost6172.18.0.2 mgr1 172.18.0.3 mgr2 172.18.0.4 mgr3

在创建docker容器时映射挂载到容器的 /etc/hosts 文件:
[root@greatsql]# docker run -d \ ... -v /data/docker/hosts:/etc/hosts \ ... greatsql/greatsql

也可以在创建容器时,直接用 --add-host 指定,例如:
[root@greatsql]# docker run -d \ ... --add-host "mgr1:172.18.0.2" --add-host "mgr2:172.18.0.3" --add-host "mgr3:172.18.0.4"\ ... greatsql/greatsql

3.3 初始化MGR集群 接下来准备初始化MGR集群。
选择第一个容器 mgr1 作为 PRIMARY节点,设置该容器的MGR的引导,然后启动MGR服务:
[root@greatsql]# docker exec -it mgr1 /bin/bash [root@mgr1 ~]# mysql -S/data/GreatSQL/mysql.sock ... #设置本节点为MGR引导启动节点,【注意】其他节点无需执行本操作 SET GLOBAL group_replication_bootstrap_group=ON; #启动MGR服务 START GROUP_REPLICATION; #启动完MGR服务后,关闭引导参数 SET GLOBAL group_replication_bootstrap_group=OFF;

因为在创建容器时已经完成了创建账户及授权等操作,所以可以直接启动MGR服务。
如果在创建容器时未指定 -e MYSQL_INIT_MGR=1 选项,则还需要手动执行下面的命令创建账户,授权,并创建MGR复制通道:
SET SQL_LOG_BIN=0; CREATE USER repl IDENTIFIED with mysql_native_password BY 'repl4MGR'; GRANT REPLICATION SLAVE, BACKUP_ADMIN ON *.* TO repl; CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl4MGR' FOR CHANNEL 'group_replication_recovery';

3.4 启动MGR服务 在另外的两个docker容器里,记住不要设置 group_replication_bootstrap_group=ON,直接启动 MGR服务即可。
查看所有节点都启动后的MGR服务状态:
[root@GreatSQL][(none)]> select * from performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME| MEMBER_ID| MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier | 63b55594-da80-11eb-94bf-0242ac120003 | mgr2|3306 | ONLINE| SECONDARY| 8.0.23| | group_replication_applier | 6d33eb83-da80-11eb-91ed-0242ac120004 | mgr3|3306 | ONLINE| SECONDARY| 8.0.23| | group_replication_applier | 7b1e33b1-da7f-11eb-8157-0242ac120002 | mgr1|3306 | ONLINE| PRIMARY| 8.0.23| +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+

在这个阶段,MGR服务无法启动的常见原因有:
  • 没有在 /etc/hosts中正确设置各节点的 hostname,会提示无法连接远程主机。
  • 利用docker创建的子网超过了RFC 1918定义的保留私有网络地址范围(A 类:10.0.0.0~10.255.255.255,B 类:172.16.0.0~172.31.255.255,C 类:192.168.0.0~192.168.255.255)。
  • 除去在选择作为PRIMARY节点上设置 group_replication_bootstrap_group=ON 外,其他节点上也设置了,会造成启动一个新的PRIMARY节点。
  • 各节点创建MGR账号后,会产生BINLOG,因此要执行 SET SQL_LOG_BIN=0 或者创建账号后再执行 RESET MASTER,否则会提示本地节点比远程节点的事务数更多,无法加入集群。
上述几种场景我都遇到过,可能还有其他更多情况,欢迎补充。
3.5 写入测试数据 这就构建完毕了,可以尝试在 PRIMARY节点 中创建库表并写入测试数据:
#提醒:从这里开始要重新启动binlog记录 [root@GreatSQL][(none)]> SET SQL_LOG_BIN=1; [root@GreatSQL][(none)]> create database mymgr; [root@GreatSQL][(none)]> use mymgr; [root@GreatSQL][(mymgr)]> create table t1(id int primary key); [root@GreatSQL][(mymgr)]> insert into t1 select rand()*10240; [root@GreatSQL][mymgr]>select * from t1; +------+ | id| +------+ | 3786 | +------+

4、利用Docker-compose创建Docker容器 如果觉得手工管理麻烦,也可以选用 docker-compose ,它可以更方便的管理docker容器。
先用yum安装docker-compose,并确认版本号:
[root@greatsql]# yum install -y docker-compose[root@greatsql]# docker-compose --version docker-compose version 1.18.0, build 8dd22a9

编辑docker-compose的配置文件,其实就是把创建docker容器的命令行参数固化到配置文件而已:
[root@greatsql]# mkdir -p /data/docker-compose [root@greatsql]# vi /data/docker-compose/compose-mgr.yml version: '3'services: mgr1: image: greatsql/greatsql container_name: mgr1 hostname: mgr1 network_mode: bridge restart: unless-stopped environment: TZ: Asia/Shanghai MYSQL_ALLOW_EMPTY_PASSWORD: 1 MYSQL_INIT_MGR: 1 MYSQL_MGR_LOCAL: '172.17.0.2:33061' MYSQL_MGR_SEEDS: '172.17.0.2:33061,172.17.0.3:33061,172.17.0.4:33061' extra_hosts: - "mgr1:172.17.0.2" - "mgr2:172.17.0.3" - "mgr3:172.17.0.4" mgr2: image: greatsql/greatsql container_name: mgr2 hostname: mgr2 network_mode: bridge restart: unless-stopped depends_on: - "mgr1" environment: TZ: Asia/Shanghai MYSQL_ALLOW_EMPTY_PASSWORD: 1 MYSQL_INIT_MGR: 1 MYSQL_MGR_LOCAL: '172.17.0.3:33061' MYSQL_MGR_SEEDS: '172.17.0.2:33061,172.17.0.3:33061,172.17.0.4:33061' extra_hosts: - "mgr1:172.17.0.2" - "mgr2:172.17.0.3" - "mgr3:172.17.0.4" mgr3: image: greatsql/greatsql container_name: mgr3 hostname: mgr3 network_mode: bridge restart: unless-stopped depends_on: - "mgr2" environment: TZ: Asia/Shanghai MYSQL_ALLOW_EMPTY_PASSWORD: 1 MYSQL_INIT_MGR: 1 MYSQL_MGR_LOCAL: '172.17.0.4:33061' MYSQL_MGR_SEEDS: '172.17.0.2:33061,172.17.0.3:33061,172.17.0.4:33061' extra_hosts: - "mgr1:172.17.0.2" - "mgr2:172.17.0.3" - "mgr3:172.17.0.4"

启动三个实例:
[root@greatsql]# docker-compose -f /data/docker-compose/compose-mgr.yml up -d NameCommandStatePorts Creating mgr1 ... done Creating mgr2 ... done Creating mgr3 ... done Creating mgr2 ... Creating mgr3 ...

查看运行状态:
[root@greatsql]# docker-compose -f /data/docker-compose/compose-mgr.yml up -d NameCommandStatePorts ---------------------------------------------------------------------------- mgr1/docker-entrypoint.sh mysqldUp3306/tcp, 33060/tcp, 33061/tcp mgr2/docker-entrypoint.sh mysqldUp3306/tcp, 33060/tcp, 33061/tcp mgr3/docker-entrypoint.sh mysqldUp3306/tcp, 33060/tcp, 33061/tcp

进入被选为PRIMARY节点的容器mgr1,启动MGR服务:
[root@greatsql]# docker exec -it mgr1 bash [root@mgr1 /]# mysql ... [root@GreatSQL][(none)]> set global group_replication_bootstrap_group=ON; [root@GreatSQL][(none)]> start group_replication;

进入其他SECONDARY节点的容器,直接启动MGR服务:
[root@greatsql]# docker exec -it mgr2 bash [root@mgr2 /]# mysql ... [root@GreatSQL][(none)]> start group_replication; Query OK, 0 rows affected (2.76 sec)#查看MGR服务状态 [root@GreatSQL][(none)]>select * from performance_schema.replication_group_members; +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | CHANNEL_NAME| MEMBER_ID| MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION | +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+ | group_replication_applier | f0bd73d4-dbcb-11eb-99ba-0242ac110002 | mgr1|3306 | ONLINE| PRIMARY| 8.0.23| | group_replication_applier | f1010499-dbcb-11eb-9194-0242ac110003 | mgr2|3306 | ONLINE| SECONDARY| 8.0.23| +---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+

照旧,继续启动mgr3节点,一个三节点的MGR集群就完成了。
GreatSQL-Docker相关文档已经发布到https://gitee.com/GreatSQL/Gr...,欢迎关注。
此外,GreatSQL Docker镜像文件也已发布到 https://hub.docker.com/r/grea...欢迎下载体验。
水平有限,也请各位读者大人帮忙看看哪些可以优化的地方,感谢。
最后要特别感谢近期在折腾docker、ansible中提供帮助的多位朋友,分别是谢恒忠、吕保成、Fan()、Coral、戴先森等(排名不分先后)。
Enjoy GreatSQL & Docker :)
文章推荐: GreatSQL MGR FAQ
https://mp.weixin.qq.com/s/J6...
万答#12,MGR整个集群挂掉后,如何才能自动选主,不用手动干预
https://mp.weixin.qq.com/s/07...
『2021数据技术嘉年华·ON LINE』:《MySQL高可用架构演进及实践》
https://mp.weixin.qq.com/s/u7...
一条sql语句慢在哪之抓包分析
https://mp.weixin.qq.com/s/AY...
万答#15,都有哪些情况可能导致MGR服务无法启动
https://mp.weixin.qq.com/s/in...
技术分享 | 为什么MGR一致性模式不推荐AFTER
https://mp.weixin.qq.com/s/rN...
关于 GreatSQL GreatSQL是由万里数据库维护的MySQL分支,专注于提升MGR可靠性及性能,支持InnoDB并行查询特性,是适用于金融级应用的MySQL分支版本。
Gitee:
https://gitee.com/GreatSQL/Gr...
GitHub:
https://github.com/GreatSQL/G...
Bilibili:
https://space.bilibili.com/13...
微信&QQ群:
可搜索添加GreatSQL社区助手微信好友,发送验证信息“加群”加入GreatSQL/MGR交流微信群
QQ群:533341697
微信小助手:wanlidbc
本文由博客一文多发平台 OpenWrite 发布!

    推荐阅读