为了方面社区用户体验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
直接用yum安装docker,非常省事。
[root@greatsql]# yum install -y docker
之后启动 docker 服务,并设置开机自启动。
[root@greatsql]# systemctl enable docker [root@greatsql]# systemctl start docker
拉取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 REPOSITORY TAG IMAGE ID CREATED SIZE docker.io/greatsql/greatsql latest d1963ef0c403 3 days ago 582 MB
之后,就可以直接创建一个新的容器了,先用常规方式。
[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
几个参数分别解释如下:
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的初始化并启动。
先确认容器的状态:
[root@greatsql]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2e277c852f52 d1963ef0c403 "/docker-entrypoin..." 4 minutes ago Up 12 minutes 3306/tcp, 33060-33061/tcp mgr1
看到容器状态是Up的,表示已正常启动了。
再进入容器查看:
[root@greatsql]# docker exec -it mgr1 /bin/bash [root@mgr1 ~]# mysqladmin ver mysqladmin Ver 8.0.23-14 for Linux on x86_64 (GreatSQL (GPL), Release 14, Revision) ... Server version 8.0.23-14 Protocol version 10 Connection Localhost via UNIX socket UNIX socket /data/GreatSQL/mysql.sock Uptime: 11 min 19 sec Threads: 2 Questions: 2 Slow queries: 0 Opens: 120 Flush tables: 3 Open tables: 36 Queries 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 | | | +---------------------------+-----------+-------------+-------------+--------------+-------------+----------------+
还可以把这个容器当做服务对其进行关闭、启动、重启、挂起等操作:
kill Kill one or more running containers pause Pause all processes within one or more containers ps List containers restart Restart one or more containers rm Remove one or more containers start Start one or more stopped containers stop Stop one or more running containers unpause Unpause all processes within one or more containers update Update configuration of one or more containers wait Block until one or more containers stop, then print their exit codes
可以自行挨个尝试。
如果想要销毁该容器,需要先停止该容器后,再执行 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 1c95278033575062b7f15e3e3f1319290d8dcfc7caba1c50b47592f665ba5456 Total reclaimed space: 13.08 GB
跨宿主机之间的docker容器网络通信相对麻烦一些,为了简单起见,本次先在单机环境下构建由3个docker容器组成的MGR集群。
首先创建一个用于MGR集群的网络:
[root@greatsql]# docker network create mgr-net [root@greatsql]# docker network ls NETWORK ID NAME DRIVER SCOPE 70c3ac08c7a9 bridge bridge local 3a480a3ec570 host host local 191d6d902b26 mgr-net bridge local 1e3e6267dcda none null local
查看这个子网的配置信息:
[root@greatsql]# docker inspect mgr-net [ { "Name": "mgr-net", ... "Subnet": "172.18.0.0/16", <-- 网段 "Gateway": "172.18.0.1" <-- 网关 ...
分别启动三个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 ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1bcd23c6f378 d1963ef0c403 "/docker-entrypoin..." 2 minutes ago Up 2 minutes 3306/tcp, 33060-33061/tcp mgr3 9d12ab273d81 d1963ef0c403 "/docker-entrypoin..." 2 minutes ago Up 2 minutes 3306/tcp, 33060-33061/tcp mgr2 56fd564a1789 d1963ef0c403 "/docker-entrypoin..." 4 minutes ago Up 4 minutes 3306/tcp, 33060-33061/tcp mgr1
分别查看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/hosts 127.0.0.1 localhost.localdomain localhost 127.0.0.1 localhost4.localdomain4 localhost4 ::1 localhost.localdomain localhost ::1 localhost6.localdomain6 localhost6 172.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
接下来准备初始化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';
在另外的两个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服务无法启动的常见原因有:
上述几种场景我都遇到过,可能还有其他更多情况,欢迎补充。
这就构建完毕了,可以尝试在 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 | +------+
如果觉得手工管理麻烦,也可以选用 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 Name Command State Ports 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 Name Command State Ports ---------------------------------------------------------------------------- mgr1 /docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp, 33061/tcp mgr2 /docker-entrypoint.sh mysqld Up 3306/tcp, 33060/tcp, 33061/tcp mgr3 /docker-entrypoint.sh mysqld Up 3306/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/GreatSQL-Docker,欢迎关注。
此外,GreatSQL Docker镜像文件也已发布到 https://hub.docker.com/r/greatsql/greatsql欢迎下载体验。
水平有限,也请各位读者大人帮忙看看哪些可以优化的地方,感谢。
最后要特别感谢近期在折腾docker、ansible中提供帮助的多位朋友,分别是谢恒忠、吕保成、Fan()、Coral、戴先森等(排名不分先后)。
Enjoy GreatSQL & Docker :)