thefutureIwant 2019-06-28
如果您的应用程序是面向大量用户、会吸引大量流量,那么一个不变的目标一定是在高效满足用户需求的同时、不让用户感知到任何类似于“服务器繁忙!”的情况。这一诉求的典型解决方案是横向扩展部署,以便有多个应用程序容器可以为用户请求提供服务。但是,这种技术需要可靠的路由功能,需要可以有效地在多个服务器之间分配流量。本文分享的内容就是要解决负载均衡解决方案的问题。
Rancher 1.6是Docker和Kubernetes的容器编排平台,为负载均衡提供了功能丰富的支持。在Rancher 1.6中,用户可以通过使用开箱即用的HAProxy负载均衡器,来提供基于HTTP / HTTPS / TCP主机名/路径的路由。
而在本文中,我们将探讨如何在原生使用Kubernetes进行编排的Rancher 2.0平台上实现这些流行的负载均衡技术。
Rancher 2.0 负载均衡功能
通过Rancher 2.0,用户可以开箱即用地使用由NGINX Ingress Controller支持的原生Kubernetes Ingress功能进行7层负载均衡。因为Kubernetes Ingress仅支持HTTP和HTTPS协议,所以目前如果您使用的是Ingress支持,那么负载均衡仅限于上述这两种协议。
对于TCP协议,Rancher 2.0支持在部署Kubernetes集群的云上配置第4层TCP负载均衡器。后文中我们还将介绍如何通过ConfigMaps为TCP均衡配置NGINX Ingress Controller。
HTTP/HTTPS 负载均衡功能
在Rancher 1.6中,您添加了端口/服务规则以配置HAProxy负载均衡器,以均衡目标服务。您还可以配置基于主机名/路径的路由规则。
例如,下面让我们来看看一个在Rancher 1.6上启动了两个容器的服务。启动的容器正在监听私有80端口。
为了均衡两个容器之间的外部流量,我们可以为应用程序创建一个负载均衡器,如下所示。在这里,我们会配置负载均衡器,将进入端口80的所有流量转发到目标服务的容器端口,然后Rancher 1.6在负载均衡器服务上放置了一个方便的链接到公共端点。
Rancher 2.0提供了一种使用非常相似的、由NGINX Ingress Controller支持的、使用Kubernetes Ingress的负载均衡器功能。下文中我们一起来看看我们该如何做。
Rancher 2.0 Ingress Controller部署
Ingress只是一种规则,控制器组件会将这一规则应用于实际负载均衡器中。实际负载均衡器可以在集群外部运行,也可以在集群中部署。
通过RKE(Rancher Kubernetes安装程序),Rancher 2.0让用户可以开箱即用地在配置的集群上部署NGINX Ingress Controller和负载均衡器,以处理Kubernetes Ingress规则。请注意,NGINX Ingress Controller默认安装在RKE配置的集群上。通过云提供商(如GKE)配置的集群具有自己的Ingress Controller来配置负载均衡器。本文的范围仅适用于使用RKE安装的NGINX Ingress Controller。
RKE将NGINX Ingress Controller部署为Kubernetes DaemonSet——因此NGINX实例会部署在集群中的每个节点上。NGINX就像一个Ingress Controller,在整个集群中监听Ingress创建,它还会将自身配置为满足Ingress规则的负载均衡器。DaemonSet配置有hostNetwork以暴露两个端口——端口80和端口443。有关如何部署NGINX Ingress Controller DaemonSet和部署配置选项的详细信息,请参阅此处:
https://rancher.com/docs/rke/...
如果您是Rancher 1.6用户,那么将Rancher 2.0 Ingress Controller以DaemonSet的形式部署,会带来一些你需要知悉的重要的改变。
在Rancher 1.6中,您可以在堆栈中部署可扩展的负载均衡器服务。因此,如果您在Cattle环境中有四台主机,则可以部署一台规模为2的负载均衡器服务,并通过端口80在这两个主机IP地址上指向您的应用程序。然后,您还可以在剩余的两台主机上启动另一台负载均衡器,以通过端口80再次均衡不同的服务(因为负载均衡器使用不同的主机IP地址)。
Rancher 2.0 Ingress Controller是一个DaemonSet——因此它全局部署在所有可调度节点上,以便为整个Kubernetes集群提供服务。因此,在对Ingress规则进行编程时,你需要使用唯一的主机名和路径指向工作负载,因为负载均衡器节点IP地址和端口80/443是所有工作负载的公共访问点。
现在让我们看看如何使用Ingress将上述1.6示例部署到Rancher 2.0上。在Rancher UI上,我们可以导航到Kubernetes Cluster和Project,并选择【部署工作负载/Deploy Workloads】功能,在命名空间下部署所需镜像的工作负载。让我们将工作负载的规模设置为两个副本,如下所示:
以下是工作负载选项卡上部署和列出工作负载的方式:
要达到这两个pod之间的均衡,您必须创建Kubernetes Ingress规则。要创建此规则,请导航到您的集群和项目,然后选择“ 负载均衡”选项卡。
与Rancher 1.6中的服务/端口规则类似,您可以在此处指定针对工作负载的容器端口的规则。
基于主机和路径的路由
Rancher 2.0允许您添加基于主机名或URL路径的Ingress规则。根据您的规则,NGINX Ingress Controller将流量路由到多个目标工作负载。下面让我们看看如何使用相同的Ingress规范将流量路由到命名空间中的多个服务。比如如下两个在命名空间中部署的工作负载:
我们可以使用相同的主机名但不同的路径添加Ingress来均衡这两个工作负载的流量。
Rancher 2.0还为Ingress记录中的工作负载提供了方便的链接。如果配置外部DNS以对DNS记录进行编程,则可以将此主机名映射到Kubernetes Ingress地址。
Ingress地址是您的集群中Ingress Controller为您的工作负载分配的IP地址。您可以通过浏览此IP地址来达到工作负载。使用kubectl查看控制器分配入口地址。
您可以使用Curl来测试基于主机名/路径的路由规则是否正常工作,如下所示:
以下是使用基于主机名/路径的规则的Rancher 1.6配置规范,与2.0 Kubernetes Ingress YAML规范进行比较:
HTTPS /证书选项
Rancher 2.0 Ingress功能还支持HTTPS协议。您可以在配置Ingress规则时上载证书并使用它们,如下所示:
添加Ingress规则时选择证书:
Ingress限制
尽管Rancher 2.0支持HTTP- / HTTPS-基于主机名/路径的负载均衡,但要突出的一个重要区别是在为工作负载配置Ingress时需要使用唯一的主机名/路径。原因是Ingress功能仅允许将端口80/443用于路由,负载均衡器和Ingress Controller则可作为DaemonSet全局启动。
从最新的Rancher 2.x版本开始,Kubernetes Ingress不支持TCP协议,但我们将在下一节中讨论使用NGINX Ingress Controller的解决方法。
TCP负载均衡选项
对于TCP协议,Rancher 2.0支持在部署Kubernetes集群的云提供程序中配置四层负载均衡器。为集群配置此负载均衡器设备后,Layer-4 Load Balancer在工作负载部署期间选择for port-mapping 选项时,Rancher会创建Load Balancer服务。此服务会让Kubernetes的相应云提供商配置负载均衡器设备。然后,此设备将外部流量路由到您的应用程序pod。请注意,上述功能需要该Kubernetes云提供商满足负载均衡器服务的要求,按此文档配置:
https://rancher.com/docs/ranc...
一旦负载均衡器配置成功,Rancher将在Rancher UI中为您的工作负载的公共端点提供一个链接。
如上所述,Kubernetes Ingress本身不支持TCP协议。因此,即使TCP不是NGINX的限制,也无法通过Ingress创建来配置NGINX Ingress Controller以进行TCP负载均衡。
但是,您可以通过创建一个Kubernetes ConfigMap,来使用NGINX的TCP负载均衡功能,具体可参阅这里:https://github.com/kubernetes...。您可以创建Kuberenetes ConfigMap对象,来将pod配置参数存储为键值对,与pod镜像分开,更多细节可以参考这里:
https://kubernetes.io/docs/ta...
要配置NGINX以通过TCP暴露服务,您可以添加或更新命名空间tcp-services中的ConfigMap ingress-nginx。此命名空间还包含NGINX Ingress Controller pod。
ConfigMap条目中的密钥应该是您要公开访问的TCP端口,其值应为格式<namespace/service name>:<service port>。如上所示,我暴露了Default命名空间中存在的两个工作负载。例如,上面ConfigMap中的第一个条目告诉NGINX我想在外部端口上暴露运行在default命名空间上的myapp工作负载,并监听在外部端口6790上的私有端口80。
将这些条目添加到Configmap,将自动更新NGINX pod,以配置这些工作负载来进行TCP负载均衡。您可以执行部署在ingress-nginx命名空间中的这些pod,并查看如何在/etc/nginx/nginx.conf文件中配置这些TCP端口。<NodeIP>:<TCP Port>在NGINX配置/etc/nginx/nginx.conf更新后,应该可以使用公开的工作负载。如果它们不可访问,则可能必须使用NodePort服务来暴露TCP端口。
Rancher 2.0负载均衡的限制
Cattle提供了功能丰富的负载均衡器支持(详细介绍在此:https://rancher.com/docs/ranc...)。其中一些功能在Rancher 2.0中暂时没有等效功能:
当前NGINX Ingress Controller不支持SNI。
TCP负载均衡需要集群中的云提供程序启用的负载均衡器设备。Kubernetes上没有对TCP的Ingress支持。
只能通过Ingress为端口80/443配置HTTP / HTTPS路由。此外,Ingress Controller作为Daemonset进行全局部署,而不是作为可扩展服务启动。此外,用户无法随机分配外部端口来进行负载均衡。因此,用户需要确保它们配置的主机名/路径组合是唯一的,以避免使用相同的两个端口发生路由冲突。
无法指定端口规则优先级和排序。
Rancher 1.6增加了对draining后端连接和drain超时的支持。Rancher 2.0暂不支持此功能。
目前在Rancher 2.0中,不支持指定自定义粘性策略和自定义负载均衡器配置以附加到默认配置。原生Kubernetes对此有一定的支持,不过也只限于定制NGINX配置:
https://kubernetes.github.io/...。
将负载均衡器配置从Docker Compose迁移到Kubernetes YAML?
Rancher 1.6通过启动自己的微服务提供负载均衡器支持,该微服务启动并配置了HAProxy。用户添加的负载均衡器配置在rancher-compose.yml文件中指定,而不是标准的docker-compose.yml。Kompose工具适用于标准的docker-compose参数,但在本文的情况下,是无法解析Rancher负载均衡器配置结构的。截至目前,我们暂时无法使用Kompose工具将负载均衡器配置从Docker Compose转换为Kubernetes YAML。
结 论
由于Rancher 2.0基于Kubernetes并使用NGINX Ingress Controller(与Cattle使用HAProxy相比),因此原先Rancher 1.6中Cattle支持的一些负载均衡器的功能目前暂时没有直接等效功能。但是,Rancher 2.0支持流行的HTTP / HTTPS基于主机名/路径的路由,这种路由最常用于实际部署。还通过Kubernetes Load Balancer服务使用云提供商提供四层(TCP)支持。2.0中的负载均衡功能也具有类似的直观UI体验。
Kubernetes生态系统在不断发展,我相信我们能找到更多适合所有负载均衡细微差别的解决方案!