优步工程团队对容器化MySQL的应用

  1. 创建MySQL主数据库并等待其就绪
  2. 创建第一个从属数据库,并将其连接至主数据库
  3. 针对其余从属数据库重复该操作

当然,最终获得的效果与上述操作类似,但我们并不需要明确关注操作的执行顺序,只需要根据需求创建能反映最终结果的目标状态即可:

“schemadock01-mezzanine-cluster1-db1”: {       “data”: {           “disabled”: false,           “role”: “master”,     “port”: 7335,          “size”: “all”   }},“schemadock02-mezzanine-cluster1-db2”: {   “data”: {     “master_host”: “schemadock01”,     “master_port”: 7335,     “disabled”: false,     “role”: “minion”,     “port”: 7335,     “size”: “all” }},“schemadock03-mezzanine-cluster1-db3”: {   “data”: {     “master_host”: “schemadock01”,     “master_port”: 7335,     “disabled”: false,     “role”: “minion”,     “port”: 7335,     “size”: “all” }}

上述信息会以随机的顺序推送给相关代理,随后代理会开始执行操作。为达到目标状态可能需要重试多次,者主要取决于执行顺序。通常可以在几次重试或实现目标状态,但某些操作可能需要重试上百次。举例来说,如果首先处理的是从属数据库,此时将无法连接至主数据库,并只能稍后重试。由于主数据库可能要等一段时间才能启动并正常运行,因此从属数据库可能需要重试多次:

(点击放大图像)

两个从属数据库先于主数据库启动的范例。最初的启动阶段(第1和第2步)中,从属数据库无法从获得主数据库的快照,因此启动过程失败。随后主数据库在第3步中顺利启动,从属数据库即可通过第4和第5步连接并同步数据。

Docker运行时的使用体验

我们的大部分宿主机运行了Docker 1.9.1,并使用LVM中的devicemapper作为存储。我们发现使用LVM中的devicemapper在执行效果方面要比回调(Loopback)的devicemapper更好。devicemapper在性能和可靠性方面有不少问题,但AuFS和OverlayFS等替代品的问题也不少[3]。这意味着整个社区对最佳存储选项方面还有不少的争议。目前OverlayFS的改进最多,似乎已经逐渐变得稳定了,因此我们准备在升级到Docker 1.12.1之后切换为使用OverlayFS。

升级Docker最大的痛苦之一在于需要重启动,并且需要重启动所有容器。这意味着升级过程必须进行必要的控制,确保升级宿主机时没有处于运行状态的主数据库。希望Docker 1.12能成为我们必须关注这个问题的最后一个版本。1.12提供了在不重启动容器的前提下重启动并升级Docker守护进程(Daemon)的选项。

每个新版本在带来大量改进和新功能的同时,也不可避免引入了一些瑕疵和问题。1.12.1看起来比老版本改进了很多,但我们依然面临一些局限:

  • Docker成功运行多天后,遭遇docker inspect时不时挂起的情况。
  • 配合Userland代理(Proxy)使用桥接网络会遇到TCP连接终止的怪异问题。无论配置多长的超时值,客户端连接有时候会完全无法收到RST信号并始终保持打开状态。
  • 容器进程偶尔会重置(Reparented)至Pid 1(init),这意味着Docker与容器的连接丢失。
  • 我们经常看到Docker守护进程新建容器所需的时间变得很长。

总结

优步对存储集群的管理有下列几个需求:

  1. 同一台宿主机运行多个容器
  2. 自动化
  3. 单点管理和访问

现在我们已经可以通过一个界面用简单的工具执行日常维护操作,所有操作均不需要直接访问宿主机:

管理控制台截图。在这里可以追踪目标状态进度,本例中我们首先添加第2个集群,随后断开复制链接,借此将一个集群一分为二。

通过在一台宿主机上运行多个容器,可以更充分地利用宿主机资源,借此即可用受控的方式对整个环境进行升级。Docker的使用让我们可以更快速实现这一切,Docker还使得我们能够在本地测试环境中运行完整的集群配置工作,借此对各种操作过程进行实验。