docker部署主从数据库

下载docker

笔者是mac版本的docker,下载官网是官网,请各位自行下载

开启k8s

笔者在开启k8s的时候总是显示starting但是就是启动不起来。一番查找之后找到了原因,由于众所周知的原因,启动 Kubernetes 所需的镜像往往会下载失败,于是点击 Apply 后,该配置页面的右下角始终显示 Kubernetes is starting,无法正常启动。

Docker Desktop for Mac 开启并使用 Kubernetes 为该问题提供了解决方案。

我们先将该仓库拉取到本地:

git clone git@github.com:maguowei/k8s-docker-desktop-for-mac.git

然后确认一下 Docker Desktop 自带的 Kubernetes 的版本。点击 Docker 图标,选择 About Docker Desktop,看到如下界面:

image-20200314214514924

可以看到 Kubernetes 的版本是 v1.15.5。

我们用下面命令切换 v1.15.5 分支 git checkout v1.15.5

在 Mac 上执行如下脚本

./load_images.sh

等待更换完成

image-20200314214933763

然后重启docker可以看到已经成功启动

image-20200314215047476

创建mysql-3307(master)

我们先拉去mysql最近镜像文件docker pull mysql:latest

然后在/docker/mysql/mysql-3307下创建配置文件夹,笔者创建了三个文件夹,data:用来存放数据,conf:用来配置mysql配置,bash:用来存放开启命令

 mkdir -p /docker/mysql/mysql-3308/conf
 mkdir -p /docker/mysql/mysql-3308/mysql-files
 mkdir -p /docker/mysql/mysql-3308/data
 cd /docker/mysql/mysql-3308/conf

我们先创建配置文件,图中的mysql-3307.cnf

[mysqld]
user=mysql
character-set-server=utf8mb4
default_authentication_plugin=mysql_native_password
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
port=3307

切记运行mysql命令之前,先将你的配置文件路径放到docker设置中FILE SHARING中,然后重启

image-20200314220605825

然后开启mysql

docker run -d -p 3307:3307 --privileged=true -v /docker/mysql/mysql-3307/conf/my-3307.cnf:/etc/mysql/my.cnf -v /docker/mysql/mysql-3307/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 --name mysql-3307 mysql:latest

参数说明

  • -p 3307:3307:端口映射,将本地3307端口映射到mysql3307端口

  • --privileged=true:容器内的root拥有真正root权限,否则容器内root只是外部普通用户权限

  • -v /docker/mysq/mysql-3307/conf/my-3307.cnf:/etc/mysql/my.cnf:映射配置文件

  • -v /docker/mysql/mysql-3307/data:/var/lib/mysql:映射数据目录

  • -e MYSQL_ROOT_PASSWORD=123456 :设置root账户密码123456

  • --name mysql-3307:设置容器名称mysql-3307

这里出现了一个错误,mysql没有启动起来,我们看到是因为/var/lib/mysql-file,查询得知当指定了外部配置文件与外部存储路径时,也需要指定 /var/lib/mysql-files的外部目录,所以在 主机新建/docker/mysql/mysql-3307/mysql-files目录,

image-20200314214230475

重新执行新的命令

docker run -d -p 3307:3307 --privileged=true -v /docker/mysql/mysql-3307/conf/my-3307.cnf:/etc/mysql/my.cnf -v /docker/mysql/mysql-3307/data:/var/lib/mysql -v /docker/mysql/mysql-3307/mysql-files:/var/lib/mysql-files/ -e MYSQL_ROOT_PASSWORD=123456 --name mysql-3307 mysql:latest
e95e247dc96d547bf37b8ee388e9d351e196c4e92cee88441f74efd510527962 --镜像

我们可以用 docker ps 来查看进程,状态显示up,表示已经成功启动,

image-20200314222155737

我们在用navicate连接测试一下

image-20200314222355460

创建mysql-3308(slave)

和前面的主库差不多,不过从库的配置文件变了

 mkdir -p /docker/mysql/mysql-3308/conf
 mkdir -p /docker/mysql/mysql-3308/mysql-files
 mkdir -p /docker/mysql/mysql-3308/data
cd /docker/mysql/mysql-3308/conf
sudo touch my-3308.cnf
//mysql-3308.cnf
[mysqld]
user = mysql
character-set-server = utf8mb4
default_authentication_plugin = mysql_native_password

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
port=3308

docker run -d -p 3308:3308 --privileged=true -v /docker/mysql/mysql-3308/conf/my-3308.cnf:/etc/mysql/my.cnf -v /docker/mysql/mysql-3308/data:/var/lib/mysql -v /docker/mysql/mysql-3308/mysql-files:/var/lib/mysql-files/ -e MYSQL_ROOT_PASSWORD=123456 --name mysql-3308 mysql:latest


我们使用docker ps来查看时候启动

image-20200314225719550

配置master的slave访问用户

//进入mysql-3307的docker命令行
sudo docker exec -it mysql-1 bash
mysql -uroot -p123456

mysql> use mysql;
mysql> select host, user, plugin from user;
+-----------+------------------+-----------------------+
| host      | user             | plugin                |
+-----------+------------------+-----------------------+
| %         | root             | mysql_native_password |
| localhost | mysql.infoschema | caching_sha2_password |
| localhost | mysql.session    | caching_sha2_password |
| localhost | mysql.sys        | caching_sha2_password |
| localhost | root             | mysql_native_password |
+-----------+------------------+-----------------------+

这里有个地方要注意一下 mysql8.0默认的身份验证插件是 caching_sha2_password, 旧版的navicat不支持这种身份验证插件,可以修改为mysql_native_password
在MySQL 5.7中,默认的身份验证插件是 mysql_native_password !
( ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY ‘123456’; )

由于我们在配置中预先设置了default_authentication_plugin = mysql_native_password
所以默认root的密码加密是mysql_native_password

//创建slave用户
mysql> CREATE USER 'slave_1'@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.13 sec)
//给新用户授权
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave_1'@'%';
Query OK, 0 rows affected (0.31 sec)
//刷新权限
mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.02 sec)

配置mysql-3307(master)的 my-3307.cnf

这边配置一下mysql-3307和mysql-3308的binlog设置 ,因为mysql实际是传输binlog(二进制日志)来达成复制的,具体的同步流程和原理可以百度一下

因为创建docker mysql的时候就把 /docker/mysql/mysql-3307/conf/my-3307.cnf 映射到了 /etc/mysql/my.cnf里,所以直接修改/docker/mysql/mysql-3307/conf/my-3307.cnf 再重启就完事了

[mysqld]
user=mysql
character-set-server=utf8mb4
default_authentication_plugin=mysql_native_password
[client]
default-character-set=utf8mb4
[mysql]
default-character-set=utf8mb4
[mysqld]
port=3307

# 设备编号 不能与其他mysql相同
server-id = 1
# 开启 binlog
log-bin = mysql-bin
# 复制的数据库
binlog-do-db = test_school
# 不复制的数据库
binlog_ignore_db = mysql
# 从复制的格式(mixed,statement,row,默认格式是statement)
binlog-format = mixed
# 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days = 7  

重启一下mysql-3307(master)

sudo docker restart mysql-1
sudo docker exec -it mysql-1 bash
mysql -uroot -p123456
mysql> show master status;
+------------------+----------+--------------+-------------------------------------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB                                | Executed_Gtid_Set |
+------------------+----------+--------------+-------------------------------------------------+-------------------+
| mysql-bin.000001 |      155 | test_school  | sys,mysql,information_schema,performance_schema |                   |
+------------------+----------+--------------+-------------------------------------------------+-------------------+
1 row in set (0.00 sec)

可以看到mysql-3306(master)binlog生效了

配置mysql-3308(slave)的 my.cnf

同理修改mysql-3308(slave)的配置文件

[mysqld]
user = mysql
character-set-server = utf8mb4
default_authentication_plugin = mysql_native_password

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
port=3308

bind-address = 0.0.0.0

#skip-name-resolve

# 设备编号 不能与其他mysql相同
server-id = 2
# 开启 binlog 以备Slave作为其它Slave的Master时使用
log-bin = mysql-slave1-bin
# 复制的数据库
binlog-do-db = test_school
# 不复制的数据库
binlog_ignore_db = mysql
# 从复制的格式(mixed,statement,row,默认格式是statement)
binlog-format = mixed
# 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days = 7

配置mysql-3308(slave)的mysql同步信息

sudo docker restart mysql-3308
sudo docker exec -it mysql-2 bash
mysql -uroot -p123456

//修改要同步的master的配置, 用之前在mysql-3308(master)创建的slave_1用户
mysql> CHANGE MASTER TO
    -> MASTER_HOST='*.*.*.*',
    -> MASTER_USER='slave_1',
    -> MASTER_PASSWORD='123456',
    -> MASTER_PORT=33061,
    -> MASTER_LOG_FILE='mysql-bin.000001',
    -> MASTER_LOG_POS=155;
Query OK, 0 rows affected, 2 warnings (0.45 sec)

MASTER_LOG_FILE 就是master里的File, MASTER_LOG_POS就是master里的Position

关于MSTER_HOST的指向问题

这里是用docker做的主从复制,必须要是用外网IP才可以连接,内网IP或者localhost都是不行的! 在docker里面用内网IP连不上另一个docker的mysql,必要要用外网IP,外网IP,外网IP!

查看同步状态

先开启 slave

mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

mysql> show slave status 
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: *.*.*.*
                  Master_User: slave_1
                  Master_Port: 33061
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 155
               Relay_Log_File: 1675298fc92a-relay-bin.000004
                Relay_Log_Pos: 369
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            ...

1 row in set (0.00 sec)

看到 Slave_IO_Running, Slave_SQL_Running 都为YES的情况 就是主从复制设置成功了
当然你也可以在主库表中插入一条数据,看看从库是否有同步

这里有可能存在的错误:

  • 网络不通

  • 账号密码错误

  • master_log_file 或者 master_log_pos 错误

  • 端口未开放(防火墙)

WRITTEN BY: