当前位置: 首页 > 科技观察

技术分享:Docker负载均衡与服务发现详解

时间:2023-03-16 11:20:03 科技观察

Docker是一个开源项目,诞生于2013年初,最初是dotCloud内部的一个业余项目。更名为DockerInc.Docker是一个用Go语言开发的开源应用容器引擎,由PaaS提供商dotCloud开源的容器引擎。Docker遵循Apache2.0协议,项目代码维护在GitHub上。简单的说,Docker就是一个可以分配资源的进程隔离模型。Docker项目的目标是实现一个轻量级的操作系统虚拟化解决方案。相关术语解释Dubbo:阿里巴巴开源的一个高性能、优秀的服务框架,使应用程序可以通过高性能的RPC实现服务的输出和输入功能,并可以与Spring框架无缝集成。LVS:LinuxVirtualServer的缩写,意为Linux虚拟服务器,是一种虚拟服务器集群系统。ipvs:IP虚拟服务器(IPVirtualServer,简称IPVS)。它是一种运行在LVSNginx下提供负载均衡功能的技术:一个轻量级的web服务器/反向代理服务器和电子邮件(IMAP/POP3)代理服务器。HAProxy:一种用C语言编写的免费开源软件[1],可通过TCP和HTTP提供高可用性、负载平衡和应用程序代理。南北通信:指整个容器集群入口处的通信。南北通信的特点是通信量比较大,所以我们先用SLB把流量分发到各个主机节点上。东西向通信:指容器之间和集群内部的通信方式。技术原理介绍容器化带来的问题在默认的网络模型中,容器每次重启后IP都会发生变化。在大型分布式系统中保证IP地址不变是比较复杂的。IP频繁变化,动态应用部署无法预知容器的IP地址。客户端如何发现服务器的访问端点?问题解决方案根据客户是否知道进行分类。客户端发现:客户端订阅注册中心,注册中心有固定的注册中心地址,客户端订阅一个服务的注册中心,注册中心根据注册中心向客户端推送一个服务的访问端点列表服务的运行状态。该方案的实现示例包括Dubbo、DNS解析等。服务器的发现:服务器为某项服务提供固定的访问端点,客户端可以直接访问该端点,从而达到与服务器通信的目的。转发到后端容器。该方案的实现实例有各种后端负载均衡的实现,包括LVS、Nginx、HAProxy等。我们可以认为下面的公式基本成立:“ServerDiscovery”=“LoadBalancer”+“AutomaticRoutingConfigurationUpdate””。按照Dubbo这样的面向服务的框架实现,这些应用或系统的客户端是不感知服务发现的,所以服务端的发现就显示出独特的优势。在客户端服务发现方式中,DNS是个例外,几乎所有的客户端都支持DNS。下面介绍客户端DNS和服务端负载均衡进行服务发现的几种方案。微服务发现方案DNS解析为多IP优势:Docker1.10以上版本原生支持容器集群内的DNS服务发现。缺点:由于DNSTTL的有效时间,无法实时得到解析结果。即使TTL设置为0,一些应用程序或方法库也会缓存DNS解析的结果,导致解析到无效地址。内核空间LVS/IPVS的优点:Docker在1.12版本采用了IPVS方案,后续会正式发布。响应内容不需要解析和处理7层HTTP协议,效率高。缺点:缺乏对第7层负载均衡的支持。一个服务的负载均衡会占用宿主机的一个端口。如果服务之间暴露的端口相同,就会发生冲突。Nginx在用户空间的优势:它同时支持四层和七层负载均衡代理。多进程模型促进了多核性能的使用。它具有缓存功能,也可以用作静态文件网络服务器。第7层可以根据HOST字段重用相同的80。端口,解决端口冲突问题。7层负载会解析HTTP协议,支持多层路由,包括按不同域名路由、按不同路径路由、内部重定向等HTTP协议层功能。缺点:负载均衡调度算法较少,后端健康检查策略较少。HAProxy在用户空间的优势:它同时支持用户空间的四层和七层负载均衡。是一个纯软负载均衡器,支持Round-Robin、static-rr、least-conn、source-IP等调度算法。后端健康检查策略完善,包括TCP端口检查、HTTP请求检查、可执行程序检查等带外检查。Layer7可以根据HOST字段复用同一个80端口,解决端口冲突的问题。7层负载会解析HTTP协议,支持多层路由,包括按不同域名路由、按不同路径路由、内部重定向等HTTP协议层功能。缺点:不能作为静态文件服务器使用,不支持Cache缓存功能。在分析了容器服务负载均衡方案的优缺点后,结合相关产品的优势,提出如下解决方案。Docker内置的DNS服务发现只要Docker版本大于1.1就支持DNS服务发现。其特点是:1)每个容器提供独立的DNS解析;2)可以通过容器名称和别名(Aliases)的方式解析到一个容器在整个网络范围内的IP;3)通过链接别名(LinkAliases)的方式设置容器范围内的DNS解析。好处是不同容器的相同别名不会冲突。4)代理外部DNS解析请求。如下图所示:SLB动态绑定的原理:Swarm监控容器的状态。如果容器运行正常,则将容器添加到负载均衡后端。如果容器发现异常,容器将从负载均衡后端移除。.HAProxy实现动态服务发现的原理:除了HAProxy软件外,HAProxy容器中还有一个脚本程序来监控容器的状态,根据容器的健康状态重新生成负载均衡信息,然后重新加载(reload)HAProxy,使新的负载均衡信息生效。实现不间断rolling_update原则:平滑升级的关键是每时每刻至少有一个容器仍能正常提供服务。1)需要部署多个容器,容器分为两批更新,A和B。2)更新容器时,先从SLB或HAProxy中移除A批容器的路由。3)更新A批容器4)A批容器健康检查正常后,重新加入路由5)移除B批容器的路由6)更新B批容器。实现灰度发布的原则:不同版本的服务可以共享相同的路由信息??,灰度发布可以通过调整SLB或者HAProxy的权重来实现。根据场景提供服务形式简单的路由服务:我们在HAProxy的基础上,增加了一层Wrapper,动态发现正在运行的容器,并加入到负载均衡中。我们称之为简单路由服务(Routingservice)。IP通过负载均衡对外暴露。主要解决以下需求:七层服务端点暴露于公网,即接受公网流量访问集群内使用七层协议的服务。七层服务端点暴露于内网,即容器集群中的负载均衡和服务发现:如下图所示,集群中的服务发现使用Docker自带的DNS解析器配合负载均衡和HAProxy的健康检查。图中的LB就是简单路由服务下的HAProxy容器。1)首先通过Docker自带的DNSresolver将域名restserver.local解析为HAProxy容器的IP。这里会选择当前节点的HAProxy容器进行负载均衡;2)RestClient请求域名restserver.local时,首先请求到代理ContainerLB;3)LB代理到容器后端RestServerContaienr,根据从DiscoveryService获得的负载均衡信息提供相应的服务。场景及对应的路由服务总结如图所示,我们将容器集群外部进入容器集群的ingress通信称为南北通信,将集群内容器之间的流量称为东西通信。我们根据不同的通信形式和协议层次提供不同的服务,以满足用户的需求。比如南北通信,如果是使用七层协议的服务,我们建议用户使用集群的SLB进行流量转发,最终的流量会转发到各个主机的HAProxy容器上,然后将其分发到处理请求的相应服务。