关于高可用负载均衡的探索
本文于3月22日晚由张新峰,杭州爱医康架构师技术分享整理而成。本次分享介绍了如何使用负载均衡达到一个对用户友好(稳定无感)、对运维友好(傻瓜高效)、对架构友好(追溯监控)的高可用状态。
搜索微信号RancherLabs,或文末扫码,添加Rancher小助手为好友,可加入官方技术交流群,实时参加下一次分享~
引 言
我们今天要说的是一个老生常谈的问题:负载均衡。有点运维经验的人都对这个很了解了,可你的负载均衡有没有完美呢?在微服务大行其道的今天,每个公司几十上百个服务都很常见,更不用说多条产品线并存的公司了,这么多服务如何在扩缩容的时候实现服务发现和高可用,每天频繁升级更新的时候有没有实现用户无感知?当然每个人对于完美的定义不同,我们今天要说的是指对用户友好(高可用无感)、对运维友好(高效傻瓜)、对架构友好(追溯监控)的完美状态。
核心组件
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服务添加如下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直接访...。
接下来我们部署一个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并发...。因为页面是活动的所以一定要加-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服务,上线运行半年左右,一直很稳定。
以上就是今天的分享,如有不严谨的地方,请多指正!谢谢大家!
Q&A环节
Q1:请问多个服务用了同一个host标签,traefik会怎么选择转到哪个服务?
A1:服务的容器运行在哪些主机上是Rancher的调度服务所负责的,和Traefik无关。Traefik链接的是服务,这个服务的容器不管在哪些主机上运行都会被连接过来。
补充:我们目前没有遇到多个服务配置相同域名的情况,相比只会有一个服务生效,改天试一试看。实际应用时还说要避免这种情况吧。
Q2:请问一下这个负载均衡适合哪些环境和应用?
A2:据官方压测结果显示Traefik可以和Nginx相媲美,所以Nginx适合的环境Traefik都适合。目前官方说Traefik只适合HTTP和HTTPS应用,不知道后期会不会支持TCP负载均衡。
Q3:请问你们在生产环境中除了用阿里云slb做流量接入,后面接着Traefik的HA集群,中间是否还用到了nginx做代理,如果有,一般用了多少台呢?
A3:Traefik就相当于Nginx了,而且还比Nginx好用,我们生产环境就没有用Nginx了。Traefik HA集群用了2台主机,自动适应的主备结构。
Q4:我想问一个跟traefik能访问远程的docker吗?docker API可以配置认证吗?
A4:只要是使用HTTP协议的API都可以使用Traefik代理。
Q5:请问下dnsmasq怎么实现的主备?
A5:我们目前的DNSmasq只是用在公司内网,由于没有什么压力,所以没有考虑DNSmasq的高可用。生产环境使用的是域名服务商的DNS服务器,这种服务器想必都有高可用吧,比如阿里云的DNS服务器有2个:223.5.5.5和223.6.6.6
Q6:我想问一下,rancher自带的负载均衡除了ui上有些痛点,性能上有什么不足么?
A6:Rancher自带的负载均衡基于haproxy,也是很成熟的负载均衡解决方案,本来不存在性能很差的问题,但是Rancher默认的内部的网络交互上存在性能损耗问题。大家可以根据今天的压测思路,部署一个Rancher自带的负载均衡,用压测看看性能。同时也对比一下把服务直接在主机上暴露端口访问的性能,三者之间对比,性能对比还是比较明显的。
Q7:请说下Traefik的HA集群怎么部署?
A7:Traefik的HA集群是基于consul后端做存储,启动多台Traefik连接到consul,Traefik会自动选举一个节点作为主节点,其他做备用节点。具体教程请查看官方说明:https://docs.traefik.io/user-...
Q8:有尝试lvs加traefik吗?
A8:我们目前是把Traefik的HA集群的多台主机都加入到一个阿里云SLB的虚拟服务器组,流量接入阿里云SLB后,自动负载到Traefik的集群,然后再路由到后端服务。目前没有使用LVS。
Q9:traefix在https上部署容易吗?
A9:Traefik部署https应用还是很方便的,只要添加SSL证书先关配置即可。还有一个很有吸引力的特性,只要配置了ACME,就可以对SSL证书自动续费。对于想小范围使用免费SSL证书的环境非常友好。
Q10:用了阿里云的slb还需要自己traefik的高可用么?阿里的Slb不是支持健康检查的么,我想的是可不可以利用这个来做高可用?
A10:阿里云SLB是流量接入端,如果在阿里云SLB上配置域名路由不仅麻烦(每个域名都手动添加一条记录),而且只能配置后端到某个服务或者服务器组,这样不利于服务的高效利用呀。所以还是需要像Traefik这样的自动适配代理来做域名适配转发。为了避免traefik这个核心域名路由转发节点的单点故障,所以最好是做traefik的HA集群。当然流量小的情况下,可以先不用HA集群。健康检查是说如果发现某个后端不健康,就把这个后端从负载均衡中移除。如果后端只有一个traefik,万一这个traefik不健康,阿里云SLB不就断了后路了么?所以说至少用两个traefik来做HA,就是避免单点故障。
Q11:请问你们的网络是如何规划的,比如,我们有DMZ区对外访问,核心区放置Server,不同应用服务分不同网段?
A11:我们阿里云环境是用专有网络的,对外都是使用SLB做接入的。专有网络自己可以设置网段,比如10.8.1.0/24是容器服务器分区,10.8.2.0/24是数据库服务器,在公司路由器上做路由跳转,公司内网指定的电脑才可以直接访问生产服务器。不应应用分不同网段,便于管理,也便于问题定位,建议做网段划分。
Q12:dns的ttl设置有讲究么?
A12:DNS服务的TTL是指在DNS服务器上缓存时间,设置越小,DNS的变动就可以更快在全网生效,然而运营商的DNS设置TTL都是有限制的,默认600秒,想要设置更短,就要购买高级服务了。
Q13:单个服务支持多个域名吗?服务的label怎么配置呢?
A13:单个服务支持多个域名,多个域名用英文逗号分隔即可。
Q16:目前贵司后端服务发布 有什么灰度发布的方案吗?
A16:目前使用的Rancher的升级机制实现的灰度发布,每个服务在至少2个容器的情况下,升级发布服务的时候就可以保证服务不中断,因为Rancher会先停止一个容器,马上启动一个容器,保证这个新容器启动成功,才会停止升级下一个容器。这个策略基本满足了灰度发布的需要。经过简单压力测试,这种服务升级发布过程中,traefik的前端是没有遇到请求错误的。
微信号:RancherLabs