Docker 最佳实战:Docker 部署单节点 MySQL 实战

Docker 最佳实战:Docker 部署单节点 MySQL 实战

2024 年云原生运维实战文档 99 篇原创计划 第 006 篇 |Docker 最佳实战「2024」系列 第 006 篇

前言

你好,欢迎来到运维有术。

今天分享的内容是 Docker 最佳实战「2024」 系列文档中的 Docker 部署单节点 MySQL 实战。

内容导图

Docker 最佳实战:Docker 部署单节点 MySQL 实战-每日运维

实战服务器配置 (架构 1:1 复刻小规模生产环境,配置略有不同)

主机名 IP CPU(核) 内存(GB) 系统盘(GB) 数据盘(GB) 用途
docker-node-1 192.168.9.81 4 16 40 100 Docker 节点 1
docker-node-2 192.168.9.82 4 16 40 100 Docker 节点 2
docker-node-3 192.168.9.83 4 16 40 100 Docker 节点 3
合计 3 12 48 120 300

实战环境涉及软件版本信息

  • 操作系统:openEuler 22.03 LTS SP3
  • Docker:24.0.7
  • Containerd:1.6.27
  • MySQL:5.7.44

1. 前提说明

主流的 MySQL 有 5.7.x 和 8.0.x 两个版本,具体选择哪个版本需要根据项目需求确定,如果不确定或是新开发的项目,建议选择 8.0 的最新版。

考虑到后续的实战课程,本文选择了 5.7.x 的最新版 5.7.44。

目前主流的 mysql 5.7.x 容器化部署方案可用的容器有以下几种:

  • docker 官方提供:mysql:5.7.44
  • bitnami 提供:bitnami/mysql:5.7.43

本系列实战文档选择镜像的策略是:优先使用 docker 官方或软件提供商官方镜像。

因此,本文选择 docker 官方提供的 mysql:5.7.44 镜像。

2. 单节点 MySQL 部署实战

2.1 创建 MySQL 数据目录

mkdir -p /data/containers/mysql/{data,config}
  • data 目录:存储容器持久化数据
  • config 目录: 配置文件目录

2.2 创建 MySQL 自定义配置文件

默认安装的 MySQL 使用的 my.cnf 配置文件,适配的使用场景有限,所以自定义 MySQL 配置文件是必然要做的一项配置。

这里我随机找了一份配置文件,仅仅是为了实现自定义配置的功能,请根据自己的使用场景自定义配置文件。

创建自定义 MySQL 配置文件,vi /data/containers/mysql/config/mysqld.conf

[mysqld]
# performance setttings
lock_wait_timeout = 3600
open_files_limit = 65535
back_log = 1024
max_connections = 512
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
thread_stack = 512K
sort_buffer_size = 4M
join_buffer_size = 4M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
thread_cache_size = 768
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M
max_heap_table_size = 32M
innodb_open_files = 1024
​
# TLS 配置
tls_version = TLSv1.2

2.3 创建 docker-compose 文件

version: '3'
​
services:
  mysql:
    container_name: mysql
    image: mysql:5.7.44
    ulimits:
      nofile:
        soft: 65536
        hard: 65536
    environment:
      - TZ=Asia/Shanghai
      - MYSQL_ROOT_PASSWORD=Db@2024!
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/lib/mysql
      - ${DOCKER_VOLUME_DIRECTORY:-.}/config:/etc/mysql/conf.d/
    ports:
      - 3306:3306
    restart: always
​
networks:
  default:
    name: mysql-tier
    driver: bridge

参数说明:

  • MYSQL_ROOT_PASSWORDD: 默认管理员 root 用户密码
  • volumes 将自定义的 MySQL 配置文件挂载到容器中的 /etc/mysql/conf.d/ 目录下
  • ulimits 设置最大的文件打开数,用于提高 MySQL 服务的性能

2.4 创建并启动 MySQL 服务

  • 启动服务
cd /data/containers/mysql
docker compose up -d
  • 正确启动的结果如下
[root@docker-node-1 mysql]# docker compose up -d
[+] Running 1/2
 ⠼ Network mysql-tier  Created                                                                                                                                  0.4s
 ✔ Container mysql     Started

2.5 验证容器状态

  • 查看 mysql 容器状态
[root@docker-node-1 mysql]# docker compose ps
NAME      IMAGE          COMMAND                  SERVICE   CREATED         STATUS         PORTS
mysql     mysql:5.7.44   "docker-entrypoint.s…"   mysql     7 seconds ago   Up 6 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp
  • 查看 mysql 服务日志
# 通过日志查看 mysql 是否有异常,结果略
docker compose logs -f

3. MySQL 服务可用性测试

为了测试 MySQL 服务的可用性,利用 Docker 创建一个 MySQL 客户端容器实例,并执行几个简单的查询命令。

  • 创建 MySQL 客户端实例
docker run -it --rm --network mysql-tier mysql:5.7.44 mysql -h 192.168.9.81 -uroot -p
  • 查看进程列表
mysql> show processlist;
+----+------+------------------+------+---------+------+----------+------------------+
| Id | User | Host             | db   | Command | Time | State    | Info             |
+----+------+------------------+------+---------+------+----------+------------------+
|  4 | root | 172.26.0.1:46442 | NULL | Query   |    0 | starting | show processlist |
+----+------+------------------+------+---------+------+----------+------------------+
1 row in set (0.00 sec)
  • 查看当前连接情况
mysql> show status like '%conn%';
+-----------------------------------------------+---------------------+
| Variable_name                                 | Value               |
+-----------------------------------------------+---------------------+
| Aborted_connects                              | 2                   |
| Connection_errors_accept                      | 0                   |
| Connection_errors_internal                    | 0                   |
| Connection_errors_max_connections             | 0                   |
| Connection_errors_peer_address                | 0                   |
| Connection_errors_select                      | 0                   |
| Connection_errors_tcpwrap                     | 0                   |
| Connections                                   | 5                   |
| Locked_connects                               | 0                   |
| Max_used_connections                          | 1                   |
| Max_used_connections_time                     | 2024-04-02 14:12:17 |
| Performance_schema_session_connect_attrs_lost | 0                   |
| Ssl_client_connects                           | 0                   |
| Ssl_connect_renegotiates                      | 0                   |
| Ssl_finished_connects                         | 0                   |
| Threads_connected                             | 1                   |
+-----------------------------------------------+---------------------+
16 rows in set (0.01 sec)

4. 自动化 Shell 脚本

全文所有的操作,我都整理成了自动化脚本:

  • 配环境变量模式 deploy-mysql.sh
#!/bin/bash
# author:@运维有术
set -e
​
# 设置 mysql 服务名称,必须修改
services_name=${1:-"mysql"}
​
# 设置 containers 基础目录,可选修改
docker_container_dir=${2:-"/data/containers"}
​
# 创建基础目录
mkdir -p ${docker_container_dir}/${services_name}/{data,config}
​
# 创建 mysql 配置文件
function deploy_services_config(){
cat > ${docker_container_dir}/${services_name}/config/mysqld.cnf <<-EOF
[mysqld]
# performance setttings
lock_wait_timeout = 3600
open_files_limit = 65535
back_log = 1024
max_connections = 512
max_connect_errors = 1000000
table_open_cache = 1024
table_definition_cache = 1024
thread_stack = 512K
sort_buffer_size = 4M
join_buffer_size = 4M
read_buffer_size = 8M
read_rnd_buffer_size = 4M
bulk_insert_buffer_size = 64M
thread_cache_size = 768
interactive_timeout = 600
wait_timeout = 600
tmp_table_size = 32M
max_heap_table_size = 32M
innodb_open_files = 1024
​
# TLS 配置
tls_version = TLSv1.2
​
EOF
}
​
# 创建 docker-compose 文件
function deploy_compose_config(){
cat > ${docker_container_dir}/${services_name}/docker-compose.yml <<-EOF
version: '3'
​
services:
  ${services_name}:
    container_name: ${services_name}
    image: mysql:5.7.44
    environment:
      - TZ=Asia/Shanghai
      - MYSQL_ROOT_PASSWORD=Db@2024!
    volumes:
      - ${DOCKER_VOLUME_DIRECTORY:-.}/data:/var/lib/mysql
      - ${DOCKER_VOLUME_DIRECTORY:-.}/config:/etc/mysql/conf.d/
    ports:
      - 3306:3306
    restart: always
​
networks:
  default:
    name: ${services_name}-tier
    driver: bridge
EOF
}
​
# 创建 mysql 服务
function deploy_services(){
  cd ${docker_container_dir}/${services_name}
  docker compose up -d
}
​
# 验证 mysql 服务
function check_services(){
  cd ${docker_container_dir}/${services_name}
  docker compose ps
}
​
echo -e "\033[1;32m [1].Deploy ${services_name} services config.\n \033[0m"
deploy_services_config
​
echo -e "\033[1;32m [2].Deploy docker compose config.\n \033[0m"
deploy_compose_config
​
echo -e "\033[1;32m [3].Deploy ${services_name} service.\n \033[0m"
deploy_services
​
echo -e "\033[1;32m [4].Check ${services_name} service status. \033[0m"
check_services

说明: 由于调试过程中没有解决 EOF 报错的问题,function 里 cat 部分的内容没有缩进,看着不美观,但是不影响使用。

5. 常见问题

5.1 问题 1

  • 问题现象

MySQL 日志里有如下告警信息 :

[Warning] A deprecated TLS version TLSv1 is enabled. Please use TLSv1.2 or higher.
[Warning] A deprecated TLS version TLSv1.1 is enabled. Please use TLSv1.2 or higher.
  • 解决方案

这个只是 TLS 配置的告警信息,不影响实际使用,从 MySQL 5.7.35 开始,TLSv1 和 TLSv1.1 连接协议已弃用,使用 TLS 1.2 几更高版本加密客户端与 MySQL 数据库实例的连接,并且在未来的 MySQL 版本中将删除对它们的支持。

MySQL 进行 SSL/TLS 连接的更多信息,请参阅 MySQL 文档中的使用加密连接。

# 在 my.cnf 配置文件中添加配置项,设置仅允许 tls 1.2, 可通过逗号设置多个 tls 版本
echo "tls_version = TLSv1.2" >> /etc/my.cnf 

5.2 问题 2

  • 问题现象

MySQL 日志里有如下告警信息 :

[Warning] Could not increase number of max_open_files to more than 64 (request: 65535)
  • 解决方案

由于容器启动时没有使用 ulimit 设置文件资源限制,因此受默认的文件描述符限制 mysql 配置文件中的 open_files_limit 配置项不生效。需要在启动容器时增加 ulimits 配置项。

# 默认的 ulimit 配置,看着很大实际没生效。
bash-4.2# ulimit -a
core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 29604
max locked memory       (kbytes, -l) 65536
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1073741816
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) unlimited
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

# 在 docker-compose.yml 文件中加入以下内容
ulimits:
      nofile:
        soft: 65536
        hard: 65536

6. 课后练习

根据本文所学,请完成以下实战任务。

  • 手工部署单节点 MySQL 服务
  • 使用自动化脚本部署单节点 MySQL 服务
  • 修改自定义 mysql 配置文件,启动 MySQL 并验证参数是否正确配置
  • 使用命令行验证测试 MySQL 服务可用性及状态
  • 7. 总结

    本文分享了基于 Docker 官方提供的 MySQL 镜像部署 MySQL 服务的详细流程及注意事项。主要内容概括如下:

    • 单节点 MySQL 服务部署
    • 单节点 MySQL 服务自动化部署脚本编写
    • 自定义 MySQL 配置文件的实现方案
    • MySQL 服务可用性验证测试

    Get 本文实战视频(请注意,文档视频异步发行,请先关注)

    • B 站 运维有术

    免责声明:

    • 笔者水平有限,尽管经过多次验证和检查,尽力确保内容的准确性,但仍可能存在疏漏之处。敬请业界专家大佬不吝指教。
    • 本文所述内容仅通过实战环境验证测试,读者可学习、借鉴,但严禁直接用于生产环境。由此引发的任何问题,作者概不负责!

    结束语

    如果你喜欢本文,请分享、收藏、点赞、评论! 请持续关注 @ 运维有术,及时收看更多好文!

    欢迎加入 「运维有术·云原生实战训练营」 ,获取更多的 KubeSphere、Kubernetes、云原生运维、自动化运维等实战技能。

    版权声明

    • 所有内容均属于原创,感谢阅读、收藏,转载请联系授权,未经授权不得转载。