Uber 的 Docker Mysql 应用

时间:2022-05-07
本文章向大家介绍Uber 的 Docker Mysql 应用,主要内容包括背景介绍、解决方案、为什么选用Docker、无状态的MySQL镜像、容器编排和拓扑配置、小结、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。

背景介绍

Uber的MySQL集群规模很大,超过1000个集群,共有4000多个数据库服务器。

问题

起初是使用Puppet管理,写了很多脚本,再加上一些人工操作,在集群数量比较小时,这个管理方法比较实用,但现在这个规范已经完全不适用了,所以需要其他的管理方案。

对于MySQL集群的管理,有几点基本的需求:

  • 可以在每个主机上运行多个数据库
  • 全自动化
  • 有一个统一入口来管理所有数据中心中的所有集群

解决方案

最后决定基于Docker设计一套解决方案,命名为 Schemadock

在Docker容器中运行MySQL,形成一个一个的节点,这些节点如何构成集群拓扑结构,由配置文件来定义。

例如有一个集群 Cluster A,配置文件中便会对其进行说明,指定包含了几个数据库,是哪几个,哪个是 master。

节点有了,拓扑结构说明书也有了,谁来按照说明把集群构建起来呢?由另一个重要角色 agents 代理 来完成。

Schemadock 中还有一个中心化的服务,进行整体的维护和监控,检查各个实例的状态和偏差。

为什么选用Docker

通过容器化的方式,使得在一台主机上运行多个数据库非常容易,可以是不同版本不同配置的,甚至一台主机上可以运行一个小型集群,这样就节省了很多主机资源。

因为MySQL是运行在容器中,容器运行在主机中,对于主机来讲,他们的功能统一了,就是运行容器,所以主机的角色一致了,可以移除Puppet中的依赖关系了。

Docker非常便于测试,在测试环境中就可以执行起集群搭建步骤,实验所有的操作流程。

Docker虽好,但Uber也给出了一点建议:

在规模不够大时,不要轻易使用Docker,因为使用Docker之后,你需要处理更多的事情,例如 镜像的构建管理、容器的监控、Docker升级、日志处理、网络规划 ……,所以,规模较小时,使用 PuppetAnsible 这类的工具就够用了,例如Uber的情况,MySQL集群数量在16个以下时,用 Puppet 管理就比较轻松。

无状态的MySQL镜像

MySQL镜像被设计为完全无状态的,构建镜像时,不会包含任何逻辑,比如复制逻辑、状态检查等,创建出来的容器就是无状态的,容器的具体角色是通过环境变量来指定,使容器与逻辑分离。

数据也不在容器中,是挂载在主机目录下的。

这样,容器是非常独立的,这会带来很多好处,例如:

  • 某个容器出现问题后,不再复用,直接删掉,用同样的参数创建一个新的容器。
  • 升级MySQL非常简单,使用新版本的镜像创建容器,替代老版本容器。
  • 配置的变化很容易控制。

容器编排和拓扑配置

MySQL镜像需要被启动为容器,指定容器的角色,并放置到复制拓扑结构中的正确位置。

这些工作由 agents 来完成,每台主机中都会运行一个 agent,接收目标说明信息,根据说明来创建和配置容器。

说明信息示例:

“schemadock01-mezzanine-mezzanine-us1-cluster8-db4”: {

   “app_id”: “mezzanine-mezzanine-us1-cluster8-db4”,

   “state”: “started”,

   “data”: {

     “semi_sync_repl_enabled”: false,

     “name”: “mezzanine-us1-cluster8-db4”,

     “master_host”: “schemadock30”,

     “master_port”: 7335,

     “disabled”: false,

     “role”: “minion”,

     “port”: 7335,

     “size”: “all”

 }

}

含义是主机schemadock01上会运行一个Mezzanine数据库,角色是从服务器,端口为7335,可以占用主机所有资源,其master是schemadock30:7335

agents 是一个无限循环运行的进程,每30秒执行一次,每次循环中会根据目标说明来检查实际状况是否正确。

例如:

  • 检查容器是否正常运行,如果没有,就根据说明创建一个,并配置好。
  • 检查容器是否在正确的复制拓扑位置,如果不是,就对其进行调整,例如:之前的一个从服务器要变更为master,就需要确保其是安全的,会检查旧master是否为只读,并且GTID是否被全部接收并执行,如果是,就移除和旧master的连接并变为可写。
  • 根据角色检查一系列参数,例如,master应该是可写的。
  • 启动或关闭一些支持型的容器,如 心跳和死锁的监控。

在创建MySQL复制关系时是有序的,但 agents 是不关心其管理的容器间的顺序的。

例如正常的构建复制过程这样的:

  1. 创建master,并等待其就绪
  2. 创建第一个slave,连接到master
  3. 重复创建slave

agents 工作时,不会先找角色为master的来配置,先遇到谁就配置谁。

如果先遇到了slave,配置时发现master还没有,就停止配置,继续处理下一个,然后等下一个工作循环中再次检查其master是否就绪,如果就绪了,就继续配置,完成了对这个容器的工作。

例如下图:

执行DB3时,DB1还不可用,就等着,直到某个工作循环中发现DB1可用时才配置完成。

小结

通过以上内容,我们可以对Uber的MySQL Docker方案有个大概了解,主要由以下4部分构成:

  1. 无状态的MySQL容器
  2. 整体集群拓扑结构的配置文件
  3. agents,每台主机上的工作者,负责本机上容器的创建、配置、状态检查与修正
  4. 服务中心,负责整体的维护和监控

实现了最初的目标:单机运行多数据库、自动化、统一管理入口。

2016年初开始迁移到Docker,到现在已经运行着1500台Docker服务器,2300个MySQL数据库。

内容整理自Uber官方博客,原文地址:https://eng.uber.com/dockerizing-mysql