【问题标题】:Why do we need a load balancer to expose kubernetes services using ingress?为什么我们需要一个负载均衡器来使用 ingress 暴露 kubernetes 服务?
【发布时间】:2020-08-12 13:56:46
【问题描述】:
对于部署在 Google kubernetes 引擎上的基于微服务的示例架构,我需要帮助来验证我的理解:
- 我们知道服务应该对 pod 副本集的流量进行负载平衡。
- 当我们创建 nginx 入口控制器和入口定义以路由到每个服务时,还会自动设置负载平衡器。
- 在某处读到创建 nginx 入口控制器意味着 nginx 控制器(部署)和负载均衡器类型服务在幕后创建。我不确定这是否属实。
负载平衡似乎是由服务完成的。基于 URL 的路由是
由入口控制器完成。
为什么我们需要负载均衡器?它并不意味着跨多个实例进行负载平衡。它只会
将所有流量转发到创建的 nginx 反向代理,它将
根据 URL 路由请求。
如果我的理解有误,请指正。
【问题讨论】:
标签:
kubernetes
google-cloud-platform
load-balancing
google-kubernetes-engine
kubernetes-ingress
【解决方案1】:
服务类型LoadBalancer 和Ingress 是从外部访问您的应用程序的方式,尽管它们的工作方式不同。
Service:
在 Kubernetes 中,Service 是一种抽象,它定义了一组逻辑 Pod 和访问它们的策略(有时这种模式称为微服务)。 Service 所针对的 Pod 集通常由 selector 确定(请参阅 below 了解为什么您可能希望 Service 没有选择器)。
有一些服务类型,其中LoadBalancer 类型允许您在外部公开您的应用程序,并为您的服务分配一个外部IP。对于每个 LoadBalancer 服务,都会为其分配一个新的外部 IP。
负载均衡将由 kube-proxy 处理。
Ingress:
管理对集群中服务的外部访问的 API 对象,通常是 HTTP。
Ingress 可以提供负载平衡、SSL 终止和基于名称的虚拟主机。
当您设置入口(即:nginx-ingress)时,将为入口控制器 pod 创建一个服务类型 LoadBalancer,并自动在您的云提供商中创建一个负载均衡器,并为nginx 入口服务。
此负载均衡器/公共 ip 将用于所有服务的传入连接,而 nginx-ingress 将负责处理传入连接。
例如:
假设您有 10 个LoadBalancer 类型的服务:这将导致创建 10 个新的公共 ip,您需要使用对应的 ip 来访问您想要访问的服务。
但是,如果您使用入口,则只会创建 1 个 IP,并且入口将负责根据您在入口配置中定义的 PATH/URL 为正确的服务处理传入连接。通过 ingress,您可以:
- 在
path 中使用正则表达式来定义要重定向的服务;
- 使用 SSL/TLS
- 注入自定义标头;
- 如果其中一项服务失败(默认后端),则重定向对默认服务的请求;
- 根据 IP 创建白名单
- 等等……
关于 Ingress 负载均衡的重要note:
GCE/AWS 负载均衡器不为其目标池提供权重。这不是旧的 LB kube-proxy 规则的问题,它可以在所有端点之间正确平衡。
有了新功能,外部流量不是在 Pod 之间均衡负载均衡,而是在节点级别均衡均衡(因为 GCE/AWS 和其他外部 LB 实现没有指定每个节点权重的能力,它们在所有目标节点上平均平衡,不考虑每个节点上的 pod 数量)。
【解决方案2】:
入口控制器(例如 nginx)pod 需要暴露在 Kubernetes 集群之外,作为所有进入 Kubernetes 集群的南北向流量的入口点。一种方法是通过 LoadBalancer。您也可以使用 NodePort,但不建议将其用于生产,或者您可以直接在具有公共 IP 的主机上的主机网络上部署入口控制器。拥有负载平衡器还可以在入口控制器 pod 的多个副本之间对流量进行负载平衡。
当您使用入口控制器时,流量从 loadBalancer 到达入口控制器,然后根据入口资源中定义的规则到达后端 POD IP。这绕过了 kubernetes 服务提供的 kubernetes 服务和负载均衡(通过第 4 层的 kube-proxy)。在内部,入口控制器从 kubernetes 服务的端点发现所有 POD IP,并直接将流量路由到 Pod。
【解决方案3】:
负载平衡似乎是由服务完成的。基于 URL 的路由由入口控制器完成。
服务确实平衡了 pod 之间的流量。但在默认情况下(ClusterIP 类型),它们无法在 Google Kubernetes Engine 中的 kubernetes 之外访问。您可以使用 LoadBalancer 类型创建服务,但每个服务都会获得自己的 IP 地址(网络负载平衡器),因此它可能会变得昂贵。此外,如果您有一个具有不同服务的应用程序,最好使用提供单一入口点的 Ingress 对象。当您创建一个 Ingress 对象时,Ingress 控制器(例如 nginx 控制器)会创建一个 Google Cloud HTTP(S) 负载平衡器。反过来,一个 Ingress 对象可以与一个或多个 Service 对象相关联。
然后你可以从入口对象获取分配的负载均衡器IP:
kubectl get ingress ingress-name --output yaml
因此,您在 pod 中的应用程序可以在 kubernetes 集群之外访问:
LoadBalancerIP/url1 -> service1 -> pods
LoadBalancerIP/url2 -> service2 -> pods