如果您的应用程序是面向大量用户、会吸引大量流量,那么一个不变的目标一定是在高效满足用户需求的同时、不让用户感知到任何类似于“服务器繁忙!”的情况。这一诉求的典型解决方案是横向扩展部署,以便有多个应用程序容器可以为用户请求提供服务。但是,这种技术需要可靠的路由功能,需要可以有效地在多个服务器之间分配流量。本文分享的内容就是要解决负载均衡解决方案的问题。
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/v0.1.x/en/config-options/add-ons/ingress-controllers/
如果您是 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/rancher/v2.x/en/cluster-provisioning/rke-clusters/options/cloud-providers/
一旦负载均衡器配置成功,Rancher 将在 Rancher UI 中为您的工作负载的公共端点提供一个链接。
通过 ConfigMaps 支持 NGINX Ingress Controller TCP
如上所述,Kubernetes Ingress 本身不支持 TCP 协议。因此,即使 TCP 不是 NGINX 的限制,也无法通过 Ingress 创建来配置 NGINX Ingress Controller 以进行 TCP 负载均衡。
但是,您可以通过创建一个 Kubernetes ConfigMap,来使用 NGINX 的 TCP 负载均衡功能,具体可参阅这里:https://github.com/kubernetes/ingress-nginx/blob/master/docs/user-guide/exposing-tcp-udp-services.md。您可以创建 Kuberenetes ConfigMap 对象,来将 pod 配置参数存储为键值对,与 pod 镜像分开,更多细节可以参考这里:
https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/
要配置 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/rancher/v1.6/en/cattle/adding-load-balancers/#load-balancers)。其中一些功能在 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/ingress-nginx/examples/customization/custom-configuration/README/。
将负载均衡器配置从 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 生态系统在不断发展,我相信我们能找到更多适合所有负载均衡细微差别的解决方案!
评论