核心组件
>> Rancher 1.6
>> Traefik 1.5.3
>> dnsmasq
>> ab
必备知识
■ 了解Rancher的安装部署和基本使用
■ 了解DNS相关的网络基本常识
背 景
目前公司有3大产品线,十多个小产品,再加上用于运营分析的内部服务和开发测试环境的各种系统和服务,有差不多上百个子域名。运维的职责之一就是要保证这么多域名稳定准确地指向相应的服务器或服务。这些服务中大部分是Web服务,还有Spring Cloud微服务。不管是用户通过浏览器访问Web服务,还是微服务之间的相互调用,稳定性肯定是衡量服务的首要指标。尤其是在向DevOps看齐的敏捷型团队,要想在每天频繁发布上线的时候也能保证服务的稳定,就必须使用负载均衡。
困 境
先看看我们测试环境的一个产品线使用Rancher自带的负载均衡时的效果 。
如果这个列表看着不是那么眼花缭乱,请看下图:
目前这个产品线部署了不到50个服务,如果这个界面看着也挺清爽,请再看看每次升级/编辑负载均衡规则的界面吧:
是不是彻底眼花缭乱了呢,这就是我之前每次维护负载均衡器的痛苦。 这里并不是在诋毁Rancher负载均衡的不好,只是这个管理方式在服务较少的时候还是方便的,服务很多的时候就不是那么方便了。
如果你想说谁让你把这么多服务放在一个负载均衡的,因为这是我们探索负载均衡过程中的其中一个阶段。
探 索
我们最初的做法是每次新增一个Web服务,就先在Rancher中部署好服务,然后在Rancher负载均衡中增加一个规则,最后还要去DNS服务器中新增一个A记录或者CNAME记录,这样用户才可以访问这个新的服务。虽然只有3步,经常有服务变动的时候也很累,还能不能更简便?
后来我们总结了生产环境不同服务使用不同二级域名但主域名都相同的规律,想到把所有有规律的相同分组(比如相同产品线)的域名泛解析到指定主机,只要在Rancher中将LB也调度到那个主机,后续需要在这个分组内新增Web服务就只需2步:
1部署好服务;
2在Rancher负载均衡中新增一个规则将想要的域名指向刚才部署,不需要添加A记录,用户就可以访问服务了。
这样着实方便了一些,但是一段时间后,服务越来越多,域名也相应越来越多,就遇到了上面管理负载均衡器界面眼花缭乱的困扰。我就在想有没有更简便的方案可以把手动管理负载均衡这一步也省略呢?能否实现每次新增或编辑一个Web服务只需要部署好服务这一步就可以了呢?
后来Traefik进入了我的视野,他可以整合各种KV存储解决方案和容器编排引擎,是实现自动负载均衡的绝佳选择。Traefik还原生支持Rancher的API,可以自发现Rancher上部署的服务。Rancher社区应用商店也提供了Traefik应用模板,按照模板部署Traefik服务以后,所有Web服务只要添加几个标签就可以自动注册到Traefik并且绑定好了制定的域名。再加上前面的经验,只要泛域名解析到了Traefik服务所在的服务器IP,即可实现了仅仅只需一个部署操作,用户就可以使用指定域名访问服务了。
实 操
实际操作前,必须要有一个搭建好的Rancher 1.6环境,我们下面只说Rancher的Agent主机需要以下几个服务器用来做实验,网络规划如下:
说明一点: 如果是生产环境或者需要公司外部用户访问内部网站,就需要在你的公网域名所在的DNS中设置相关域名解析,不需要单独部署DNS服务。 在公司内网部署一个独立DNS服务器的好处就是对公司内网用户友好,不用每个人记住枯燥的IP和端口了。还有一个好处就是可以实现域名拦截,比如公司内网开发测试环境想用一个花钱也搞不到的好域名,仅限内网,嘿嘿。。。
第一步,准备主机
将以上4台主机分别添加到Rancher,主机名没有要求。如果已经在Rancher集群里了,直接编辑主机按照上面网络规划分别添加标签。注意主机已经有的标签不要随意修改或删除,以免带来未知的问题。
四个节点都添加好的主机界面截图:
第二步,部署DNS服务器
如果你公司内部已经有DNS服务器,请在内部DNS上设置相关域名解析,可以略过这一步。如果对网络DNS了解不多,也请慎重操作,很容易引起你的电脑“无法上网”。
先添加一个应用,再添加服务,这里介绍一个自带Web管理界面的轻量级DNS服务器,镜像是:jpillora/dnsmasq,端口映射添加53和5380端口,分别对应容器53/udp和8080/tcp端口。注意53端口不能修改,必须是UDP协议。5380端口是DNS管理控制台,端口可以根据需要设置。如下图:
DNS服务启动好以后,打开DNS管理控制台http://10.0.1.10:5380,进行DNS配置: 最核心的一条泛解析配置address=/.aek.com/10.0.1.10可以把aek.com所有的子域名解析到10.0.1.10这个IP。
配置好的截图如下:
下一步在各个主机和用户电脑上的设置DNS,将主DNS设置为10.0.1.10。当然前提是用户的电脑是可以ping通10.0.1.10这个IP。如果公司有DHCP服务器,将DHCP分配的主DNS设置为10.0.1.10,DHCP管辖下的电脑重启后都会应用这个主DNS了。 Windows设置DNS效果:
Linux修改DNS命令:
sed -i '1 i nameserver 10.0.1.10' /etc/resolv.conf
RancherOS修改DNS命令:
sudo ros c set rancher.network.dns.nameservers [10.0.1.10]
sudo reboot
设置好以后,验证DNS是否生效。打开CMD,ping aek.com或者随便这个域名的子域名,看看解析是否都指向我们的gateway服务器10.0.1.10,如下图:
第三步,部署Traefik
关于Rancher部署Traefik服务的详细介绍,请查看Rancher官方教程 「Rancher部署Traefik实现微服务的快速发现」,这里只简单说一下。 在社区应用商店找到Traefik并部署,这里我们演示简单起见只需要修改Http Port端口为80,Https Port如果用到的话就改成443,端口配置界面如下:
为了高可用,一个重要的选项要留意,一定要启用健康检查:
其他选项暂时不需要修改,点击启动按钮启动一个traefik服务。 启动以后发现443端口并没有映射出来,估计是这个社区镜像的Bug,如果需要https,就升级一下traefik服务,添加443端口映射即可。
打开网址http://10.0.1.10:8000就可以看到一个清爽的Traefik界面了。管理界面就两个界面,一个Providers显示注册上来的Web服务,我们还没有部署Web服务,所以现在是空的:
还有一个界面Health显示负载均衡的健康状态,平均响应时间和状态码统计图都在这里。还有一个非常重要的统计信息就是实时HTTP错误列表,每次服务升级发布上线的时候,留意这里有没有忽然出现一大堆错误,你的服务架构升级是否稳定,有没有影响用户体验就体现在这里了!
至此,一个DNS服务,一个Traefik服务就部署好了,接下来我们就看看Traefik的神奇效果。
第四步,部署Web服务
Rancher的Traefik教程有一个细节需要更正,可能是教程里面的traefik版本和最新版本不同,所以教程里面说的关于域名的配置标签traefik.domain和traefik.alias并不好用。看了Traefik官方文档「Traefik配置Rancher后端」中的说明,经过我的实际验证,在Rancher中实现自动注册Web服务到Traefik需要添加以下3个标签:
比如我们想要使用域名http://traefik.aek.com直接访问Traefik的管理面板,只需要升级Traefik服务添加如下3个标签:
traefik.enable=true
traefik.port=8000
traefik.frontend.rule=Host:traefik.aek.com
这里有个技巧,Rancher设计很人性化的地方,一次性复制下面3个标签,在Rancher服务的标签界面点击“添加标签”以后,直接粘贴,刚才复制的3个标签已经全部填好了,如下图:
Traefik服务升级好以后,刷新Traefik的控制台,Providers里面就会多了一组负载均衡。
这个时候你就可以打开http://traefik.aek.com直接访问traefik的控制面板了。
接下来我们部署一个Web服务,看看自动注册并使用DNS解析的效果,使用我写的一个方便验证负载均衡后端和服务端的Web镜像zhangsean/hello-web已经发布到Docker Hub,容器内部暴露80端口,不需要添加端口映射,只需要添加以下3个标签,我们启动2个容器,以便看看有没有负载均衡的效果:
traefik.enable=true
traefik.port=80
traefik.frontend.rule=Host:web.aek.com
部署界面截图:
hello-web服务启动成功后,查看traefik控制台,会发现多了一组负载均衡规则:
这时候就可以打开网址 http://web.aek.com 访问刚部署的hello-web服务了。多次刷新,会看到Server Name在两个容器名之间轮换,说明2个服务后端都在提供服务了。
顺便说一下,很多业务后端服务需要记录客户端真实IP,后端应用通过HTTP请求头 HTTP_X_FORWARDED_FOR 或 HTTP_X_REAL_IP即可获取客户端真实IP,区别是前者可能包含多层代理的IP。 关于获取跨代理的客户端真实IP的详细讲解,请参考:HTTP 请求头中的 X-Forwarded-For,X-Real-IP
高可用验证
我们现在通过压力测试,验证这种负载均衡的高可用效果。我们选择老牌压力测试工具ab,容器化的ab镜像是jordi/ab,为了避免单次压力测试的不稳定情况,我们使用Rancher批量发起多组压力测试。
我们首先测试在服务后端扩缩容的时候,服务的可用情况。 新建一个应用HA-Test,然后添加服务ab-web,镜像指定jordi/ab,不需要映射端口,命令里填写测试命令-n 1000 -c 10 -l http://web.aek.com/使用10并发执行1000次请求测试。因为页面是活动的所以一定要加-l参数否则会看到很多失败请求,其实是ab检测到页面返回长度不一致认为请求失败了。自动重启选择“从不(仅启动一次)”,网络类型选择“主机”以便减少容器内部往来对压力测试造成的影响,添加一个标签test_node=true,调度规则也添加主机标签限制必须包含test_node=true,这样保证测试容器只会运行在node3上不会影响后端服务所在主机的性能。
新增ab-web服务:
网络设置:
标签设置:
调度规则:
启动服务以后,进入服务详情,看到服务是Started-Once,等待服务运行并自动停止,ab测试就完成了。查看服务日志即可看到测试结果。
测试结果:
现在想再测试一次,只需要手动启动服务或者给这个服务扩容即可。多运行几次压测,把这几个重要指标放到Excel中进行统计分析就可以知道服务的稳定性和性能了。
以上只是压测的介绍,压测时间才持续时间1秒钟肯定不能说明什么,我们通过调整-n参数来增加服务请求数,让压测持续一段时间,在此期间扩容服务,看看服务稳定性怎样。
选择ab-web服务,将其克隆,在新服务里面把服务名改成ab-web-1w,在命令里面把请求个数参数调整为-n 10000,启动压测服务。等服务进入Running状态后,把hello-web服务扩容到3个后端,确保hello-web扩容的后端启动成功,并且在Traefik控制台确认hello-web后端已经有3个server,这个时候也可以手动刷新 http://web.aek.com 看看Server Name是否出现第三个容器。这时候压测应该还在进行汇总,回到ab-web-1w服务查看日志,等待压测结束。 可以看到没有失败请求,说明扩容期间负载均衡服务很稳定。
我们再进行来验证服务缩容的时候负载均衡是否稳定,方法同上,将ab-web-1w克隆成ab-web-1w-2,其他参数不需要修改,启动服务,等待压测服务Running,把hello-web服务缩容到2个,在traefik控制台确认hello-web的后端只剩2个,查看压测服务日志,等待压测结束,确认是否有失败请求。 很庆幸,压测结果显示,没有任何失败请求!
再来看看Traefik控制台的健康状态,除了无法请求favicon出现的404错误(Hello-web镜像里面没有放favicon.ico文件),没有其他错误。这也印证了Traefik服务的高可用。
通过以上简单的压测,我们基本上验证了Traefik在服务扩缩容的过程中任然能够保持服务的稳定高可用。 再结合DNS泛解析,实现了对用户友好(高可用:升级服务过程中用户无感知)、对运维友好(部署简单高效操作傻瓜方便)、对架构友好(监控服务升级过程中有无异常)的简单高可用服务。
当然生产环境要比我们这个演示环境复杂的多,随机的并发流量,不稳定的网络等等因素也都在影响着负载均衡的高可用。 Traefik还提供了运行状态API,可以整合到监控系统里面实现更稳定持续的监控。Traefik自身也支持HA模式,避免Traefik单点故障。
我们公司在生产环境用阿里云SLB做流量接入,后面接着Traefik的HA集群做自动域名和服务发现的路由,再后端是各种Web服务,上线运行半年左右,一直很稳定。