基于Docker运行弹性集群的五个关键点之:运行高可用模式

当前技术世界的发展形势就是让开发人员从繁琐的应用配置和管理中解放出来,使用容器镜像来处理复杂的程序运行依赖库的需求,保证代码运行环境的一致性。既然这样的好处是如此清晰,但为何企业中的基础设施环境没有往容器集群切换呢?关键问题仍是风险,新技术意味着未经检验的技术和实践经验的缺少,这就会带来不少不可预知的风险。前端

当企业的运维团队去维护一个弹性的容器集群时,传统的软件部署方式须要向容器迁移,这个过程当中须要有风险预判和规避之道。而Docker和Rancher正是提供了解决这些风险问题的解决方案,好比基于Rancher的Catalog功能就能快速的完成一些基础软件的部署(好比ElasticSearch)。在风险管理方面,咱们能够看看基于Docker和Rancher来运行弹性集群的五个关键点:java

  1. 运行Rancher高可用模式 (本文将介绍)mysql

  2. Rancher中使用负载均衡服务git

  3. Rancher中的服务监控和监控检查github

  4. 开发者自定义针对Rancher的安装部署web

  5. 讨论利用Convoy对数据的管理redis

我本来但愿展示一下用一台老式笔记本部署Rancher Server,而后用docker-machine加入几个树莓派节点部署Rancher Agent,这样来构建一个Rancher集群。可是这样会有些问题,就是大部分Docker镜像都是基于Intel CPU构建的,这会和树莓派的ARM CPU很不兼容。因此我仍是老老实实的用AWS的虚机来构建Rancher集群吧。sql

初始安装,咱们暂时先部署一台Rancher Server和一台Rancher Agent,而后再部署一个简单的多实例应用。docker

图片描述

上面这张图展示了个人整个集群的设置,我选择AWS是由于我我的比较熟悉,固然你彻底能够选择你擅长的云提供商。数据库

图片描述

咱们能够尝试建立一个Wordpress,顺带来检测一下Rancher是否正确部署了。

图片描述

这样咱们的应用就运行起来了,试想,若是Rancher Server所在服务器出现故障,或者有网络中断问题发生,会对应用产生什么影响,Wordpress还能继续接受请求么?

图片描述

为了确认咱们的疑问,我将会按照下面的步骤执行,而后记录一下其中的运行结果:

  1. 阻断Rancher Server和Rancher Agent间的网络

  2. 中止Rancher Server的容器

  3. 瞧一瞧Rancher Server的容器里面到底有什么

最终咱们要解决这些问题,那就要看看Rancher HA来怎样解决这些风险。

阻断Rancher Server和Rancher Agent间的网络

进入AWS,而后看我各类犀利的操做:

  1. 阻断Rancher Server和Rancher Agent间的访问

  2. 记录一下发生了什么

  3. 干掉几个WordPress的实例

  4. 恢复原先的网络

观察结果

首先,网络阻断后没过多久Rancher Host就出现了reconnecting状态

图片描述

此时我依然能够正常访问Wordpress的地址,服务没有中断,IPSec隧道网络还存储,Wordpress实例仍是能够正常访问数据库。

如今咱们要停掉一个Wordpress实例,看看会发生什么?由于咱们已经没法从Rancher UI上管理这些容器了,因此仍是到对应的主机上执行docker命令吧。

图片描述

很遗憾Wordpress容器没有从新启动,这有点麻烦了。咱们仍是把Rancher Server弄回来吧,看看它能不能感知到其中一个Wordpress容器已经被停掉了。

在各类犀利的操做和等待以后,Rancher Server与Agent从新链接了,Wordpress容器就被从新启动了。完美~

因此咱们能够看,Rancher Server仍是可以处理间歇性的网络问题,能够实现Rancher Server和Agent的故障重连。可是若是要让网络中断对Rancher的影响进一步减少,那么部署多个Rancher Server就比较重要了。

咱们仍是回过来,按照先前计划看看Rancher Server 容器停掉后会发生什么?咱们会所以失去对这些Rancher Host的管理能力么?看看如何!

停掉Rancher Server

此次我须要登入到Rancher Server的host上手动中止Rancher Server,其实Rancher Server通常是设置 –restart=always,因此本身有必定的恢复能力。但咱们能够假设好比磁盘写满了后,Rancher Server真的起不来了。

观察结果

执行docker stop rancher-server以后,Wordpress仍是可以正常工做,可是Rancher UI是不能访问了,这可不行,得赶忙把Rancher Server弄回来。

再执行docker start rancher-server,Rancher Server启动后又一切恢复正常,这很酷啊,这是什么魔法?赶忙着,麻溜地分析起来!

揭开Rancher Server的神秘面纱

咱们来一次对Rancher Server的简要探究之旅,看一看Rancher Server的Dockerfile。

图片描述

# Dockerfile contents
FROM ...  
...
...
CMD ["/usr/bin/s6-svscan", "/service"]

咱们能够看到使用了s6-svscan,它能够运行指定的目录结构内的程序,目录内的主要文件就是Run、Down、Finish。下面这张图能看到会运行两个服务cattle(Rancher的核心调度器)和mysql。

图片描述

其实在容器内部咱们也能够看到起了哪些服务。

PID TTY      STAT   TIME COMMAND
    1 ?        Ss     0:00 /usr/bin/s6-svscan /service
    7 ?        S      0:00 s6-supervise cattle
    8 ?        S      0:00 s6-supervise mysql
    9 ?        Ssl    0:57 java -Xms128m -Xmx1g -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/var/lib/cattle/logs -Dlogback.bootstrap.level=WARN -cp /usr/share/cattle/1792f92ccdd6495127a28e16a685da7
  135 ?        Sl     0:01 websocket-proxy
  141 ?        Sl     0:00 rancher-catalog-service -catalogUrl library=https://github.com/rancher/rancher-catalog.git,community=https://github.com/rancher/community-catalog.git -refreshInterval 300
  142 ?        Sl     0:00 rancher-compose-executor
  143 ?        Sl     0:00 go-machine-service
 1517 ?        Ss     0:00 bash
 1537 ?        R+     0:00 ps x

咱们能够看到Rancher的大脑,一个名叫Cattle的Java应用,它须要一个MySQL来存储对应的数据。这确实很方便,可是咱们发现这样会有单点故障,全部的数据存储在一个单点的mysql中。若是对mysql中的数据来一些不礼貌的操做,会发生什么呢?

破坏MySQL存储数据
进入容器中执行一些MySQL命令,咱们一块儿来干点坏事:

docker exec -it rancher-server bash
$ > mysql
mysql> use cattle;
mysql> SET FOREIGN_KEY_CHECKS = 0;
mysql> truncate service;
mysql> truncate network;

结果是可想而知的,Rancher不记得任何事了,你删掉一个Wordpress容器,它也不会恢复。

图片描述

并且我也删除了network表的数据,Wordpress也不知道如何找到它的MySQL服务了。

图片描述

显然,若要在生产环境运行Rancher,咱们须要一个方式来保护Rancher Server的数据,既然如此那咱们就讲一下Rancher HA吧。

Rancher HA安装过程

首先咱们要确保数据的安全,我选择了AWS的RDS服务,RDS能够提供一个信赖的MySQL服务,数据安全是能够保证的。固然你也可使用其余的,我只是对RDS更熟悉一些。

下面咱们继续Rancher HA的安装过程:

图片描述

按照咱们以前的约定,我是建立了RDS的MySQL实例,而后把它当作外部数据库和Rancher Server链接。

图片描述

图片描述

一旦咱们使用了外部数据库模式,UI上将会打开两个选项来设置HA。

图片描述

怎么办!选择困难症啊!不要紧,我来解释一下每一个选项的含义。

Cluster size,注意这里怎么都是奇数?由于在后端,Rancher会设置一个ZooKeeper Quorum保证锁同步,ZooKeeper推荐奇数集群,由于偶数节点数量不能提供额外的容错性。咱们这里就选择3个Host吧,这是一个可用和易用的平衡。

Host registration URL,这里是填写一个Rancher Cluster入口的FQDN,推荐使用外部负载均衡服务或者DNS服务(round robin策略)。好比图中我使用的是支持SRV记录的DNS服务,经过DNS来作三个Rancher Server的负载均衡:

图片描述

SSL Certificates是列表中的最后一个选项,若是你有域名的SSL证书能够配置在这里,不然Rancher会自动生成一个自签名证书。

全部都填完后,就会给你提供一个rancher-ha.sh的脚原本下载。
有了脚本就能够到每一个Rancher Server节点上执行了,执行前还须要注意目前只能支持docker v1.10.3。安装指定版本的Docker Engine,能够参考下面的方式:

#!/bin/bash
apt-get install -y -q apt-transport-https ca-certificates  
apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D  
echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" > /etc/apt/sources.list.d/docker.list  
apt-get update  
apt-get install -y -q docker-engine=1.10.3-0~trusty

# run the command below to show all available versions
# apt-cache showpkg docker-engine

Docker安装以后,就要确认一下端口开放了,须要开放哪些端口能够看这里,不过若是是第一次安装,我建议你把端口所有开放吧,省得坑太深被活埋。

一切准备稳当以后,能够执行脚本,执行后能看到这样的输出:

...
ed5d8e75b7be: Pull complete  
ed5d8e75b7be: Pull complete  
7ebc9fcbf163: Pull complete  
7ebc9fcbf163: Pull complete  
ffe47ea37862: Pull complete  
ffe47ea37862: Pull complete  
b320962f9dbe: Pull complete  
b320962f9dbe: Pull complete  
Digest: sha256:aff7c52e52a80188729c860736332ef8c00d028a88ee0eac24c85015cb0e26a7  
Status: Downloaded newer image for rancher/server:latest  
Started container rancher-ha c41f0fb7c356a242c7fbdd61d196095c358e7ca84b19a66ea33416ef77d98511  
Run the below to see the logs

docker logs -f rancher-ha

执行过程当中会下载一些额外的镜像,毕竟要支持HA特性么。另外Host的内存建议至少4G,执行完毕后经过docker ps能够看看都启动了什么:

图片描述

常见的问题和解决方案

正常来讲,通常咱们会在日志中能看到各个成员加入到Rancher HA Cluster中:

time="2016-07-22T04:13:22Z" level=info msg="Cluster changed, index=0, members=[172.30.0.209, 172.30.0.111, ]" component=service  
...
time="2016-07-22T04:13:34Z" level=info msg="Cluster changed, index=3, members=[172.30.0.209, 172.30.0.111, 172.30.0.69]" component=service

但有时候会有意外,好比会看到一些error信息:

time="2016-07-23T14:37:02Z" level=info msg="Waiting for server to be available" component=cert  
time="2016-07-23T14:37:02Z" level=info msg="Can not launch agent right now: Server not available at http://172.17.0.1:18080/ping:" component=service

这个问题产生的背后缘由有不少,我阅读了一些Github上的issue和各类论坛的帖子,帮你们整理了一些产生此问题的根本缘由。

网络设置问题

有时候容器自动获取了节点的错误的IP,这时候你须要强制指定正确的IP。

ZooKeeper没有正常启动

Zookeeper的容器是分布在每一个节点上的,若是节点之间的问题致使Zookeeper容器不能通讯,就会致使这个问题,若是要确认这个问题,能够参考这样的日志输出。

目录/var/lib/rancher/state下有残留文件

若是屡次运行Rancher-ha.sh这个脚本,那么你须要运行前清理一下这个目录下残留文件。

屡次尝试后HA状态被破坏

删库重试,重启大法好。

机器资源不足

内存至少须要4GB,此外mysql的链接数也要足够,能够按照每一个HA节点须要50个链接数来计算。若是你看到下面的错误,那么此问题确信无疑。

time="2016-07-25T11:01:02Z" level=fatal msg="Failed to create manager" err="Error 1040: Too many connections"

rancher/server版本不匹配

rancher-ha.sh执行的时候默认是下载rancher/server:latest镜像,若是你没有host上的镜像不一致会致使不可思议的问题,最好执行的时候指定版本号。好比:

./rancher-ha.sh rancher/server:

docker0返回了错误的IP

这个错误具体就是在HA的安装过程当中会去检查agent健康状态,此时它获取了一个错误的docker0 IP地址,由于我先前已经将其设置成了172.17.42.1。

curl localhost:18080/ping
> pong
curl http://172.17.0.1:18080/ping
> curl: (7) Failed to connect to 172.17.0.1 port 18080: Connection refused

个人解决办法就是重装了个人AWS虚机,致使获取docker0 IP错误的缘由,我感受多是我在虚机里屡次安装了Docker。重装以后,一切就正常了,我也看到了期待的日志信息。

HA部署完毕后

咱们终于看到了求之不得的正确日志输出,和美好的UI展示:

time="2016-07-24T20:00:11Z" level=info msg="[0/10] [zookeeper]: Starting "  
time="2016-07-24T20:00:12Z" level=info msg="[1/10] [zookeeper]: Started "  
time="2016-07-24T20:00:12Z" level=info msg="[1/10] [tunnel]: Starting "  
time="2016-07-24T20:00:13Z" level=info msg="[2/10] [tunnel]: Started "  
time="2016-07-24T20:00:13Z" level=info msg="[2/10] [redis]: Starting "  
time="2016-07-24T20:00:14Z" level=info msg="[3/10] [redis]: Started "  
time="2016-07-24T20:00:14Z" level=info msg="[3/10] [cattle]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [cattle]: Started "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [go-machine-service]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [websocket-proxy]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [rancher-compose-executor]: Starting "  
time="2016-07-24T20:00:15Z" level=info msg="[4/10] [websocket-proxy-ssl]: Starting "  
time="2016-07-24T20:00:16Z" level=info msg="[5/10] [websocket-proxy]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[5/10] [load-balancer]: Starting "  
time="2016-07-24T20:00:16Z" level=info msg="[6/10] [rancher-compose-executor]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[7/10] [go-machine-service]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[8/10] [websocket-proxy-ssl]: Started "  
time="2016-07-24T20:00:16Z" level=info msg="[8/10] [load-balancer-swarm]: Starting "  
time="2016-07-24T20:00:17Z" level=info msg="[9/10] [load-balancer-swarm]: Started "  
time="2016-07-24T20:00:18Z" level=info msg="[10/10] [load-balancer]: Started "  
time="2016-07-24T20:00:18Z" level=info msg="Done launching management stack" component=service  
time="2016-07-24T20:00:18Z" level=info msg="You can access the site at https://" component=service

图片描述

若是使用了自签名证书且前端但愿经过HTTPS来访问,那么你须要把你的证书添加到你的受信任证书中。而后再等待数据库资源约束调整完毕后,三个节点的服务就彻底运行起来了。

结论

这比原来想象的要多了不少。这就是为何分布式系统一直是PHD的研究领域。解决全部的故障点后,我认为Rancher HA已经开始向顶尖分布式系统出发啦。

我最终会将Rancher HA的脚本配置成Ansible的一个简单任务,敬请关注!

附录

对于任何分布式系统来讲,基本的套路就是统一管理其中产生的状态和变化,这意味着多个服务须要一个进程来协调更新。

Rancher的处理方式就是把状态都放倒数据库中,须要同步状态时把状态信息放入到event中,发送event就能够向其余组件同步状态。因此当正在处理一个事件时,它有一个锁,事件未处理完前数据库中的状态是不能被修改的。

在单台服务器设置中,全部的协调都发生在主机上的内存中。一旦你涉及多服务器HA配置,像zookeeper和redis是必要的。


报名11.6成都Docker技术沙龙
图片描述

相关文章
相关标签/搜索