入口与负载均衡器
Posted
技术标签:
【中文标题】入口与负载均衡器【英文标题】:Ingress vs Load Balancer 【发布时间】:2017-12-18 04:45:47 【问题描述】:我对 Kubernetes 中 Ingress 和 Load Balancer 的角色感到很困惑。
据我了解,Ingress 用于将来自互联网的传入流量映射到集群中运行的服务。
负载均衡器的作用是将流量转发到主机。在这方面,有何不同?另外,与 Amazon ELB 和 ALB 相比,kubernetes 内部的负载均衡器是什么概念?
【问题讨论】:
【参考方案1】:负载平衡器:kubernetes LoadBalancer 服务是一种指向外部负载平衡器的服务,这些负载平衡器不在您的 kubernetes 集群中,但存在于其他地方。假设您的 pod 可在外部路由,它们可以与您的 pod 一起工作。 Google 和 AWS 本身就提供了这种能力。就亚马逊而言,这直接与 ELB 和 kubernetes 进行映射,在 AWS 中运行时可以为部署的每个 LoadBalancer 服务自动预置和配置一个 ELB 实例。
入口:入口实际上只是一组规则,可传递给正在侦听它们的控制器。你可以部署一堆入口规则,但除非你有一个可以处理它们的控制器,否则什么都不会发生。 LoadBalancer 服务可以监听入口规则,如果它被配置为这样做的话。
您还可以创建一个 NodePort 服务,该服务在集群外部具有可外部路由的 IP,但指向集群中存在的 pod。这可能是一个 Ingress Controller。
入口控制器只是一个配置为解释入口规则的 pod。 Kubernetes 支持的最流行的入口控制器之一是 nginx。在 Amazon 方面,ALB can be used 作为入口控制器。
例如,this nginx 控制器能够摄取您定义的入口规则并将它们转换为它在其 pod 中加载和启动的 nginx.conf 文件。
例如,假设您定义了一个入口,如下所示:
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
ingress.kubernetes.io/rewrite-target: /
name: web-ingress
spec:
rules:
- host: kubernetes.foo.bar
http:
paths:
- backend:
serviceName: appsvc
servicePort: 80
path: /app
如果您随后检查您的 nginx 控制器 pod,您将看到在 /etc/nginx.conf
中定义的以下规则:
server
server_name kubernetes.foo.bar;
listen 80;
listen [::]:80;
set $proxy_upstream_name "-";
location ~* ^/web2\/?(?<baseuri>.*)
set $proxy_upstream_name "apps-web2svc-8080";
port_in_redirect off;
client_max_body_size "1m";
proxy_set_header Host $best_http_host;
# Pass the extracted client certificate to the backend
# Allow websocket connections
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Real-IP $the_real_ip;
proxy_set_header X-Forwarded-For $the_x_forwarded_for;
proxy_set_header X-Forwarded-Host $best_http_host;
proxy_set_header X-Forwarded-Port $pass_port;
proxy_set_header X-Forwarded-Proto $pass_access_scheme;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Scheme $pass_access_scheme;
# mitigate HTTPoxy Vulnerability
# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
proxy_set_header Proxy "";
# Custom headers
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
proxy_redirect off;
proxy_buffering off;
proxy_buffer_size "4k";
proxy_buffers 4 "4k";
proxy_http_version 1.1;
proxy_cookie_domain off;
proxy_cookie_path off;
rewrite /app/(.*) /$1 break;
rewrite /app / break;
proxy_pass http://apps-appsvc-8080;
Nginx 刚刚创建了一条规则,将 http://kubernetes.foo.bar/app
路由到集群中的服务 appsvc
。
这里是an example 如何使用 nginx 入口控制器实现 kubernetes 集群。希望这会有所帮助!
【讨论】:
我认为最后一行 proxy_pass apps-appsvc-8080;应该改为在端口 80 上。此外,通常将像 ELB 这样的 LB 放在 Ingress Controller 前面,为什么?【参考方案2】:我找到了this very interesting article,它解释了 NodePort、LoadBalancer 和 Ingress 之间的区别。
来自文章中的内容:
负载平衡器:
LoadBalancer 服务是将服务公开给 互联网。在 GKE 上,这将启动一个网络负载均衡器,它将 为您提供一个 IP 地址,该地址会将所有流量转发到您的 服务。
如果你想直接暴露一个服务,这是默认的方法。 您指定的端口上的所有流量都将转发到该服务。 没有过滤,没有路由等。这意味着你几乎可以发送 任何类型的流量,如 HTTP、TCP、UDP、Websockets、gRPC 或 随便。
最大的缺点是您使用 LoadBalancer 公开的每个服务 将获得自己的 IP 地址,并且您必须为 LoadBalancer 付费 每个暴露的服务,这可能会变得昂贵!
入口:
Ingress 实际上不是一种服务。相反,它坐在前面 多个服务并充当“智能路由器”或入口点 你的集群。
您可以使用 Ingress 做很多不同的事情,并且有 许多类型的 Ingress 控制器具有不同的功能。
默认的 GKE 入口控制器将启动 HTTP(S) 负载 平衡器为您服务。这将让您同时执行基于路径和子域 基于路由到后端服务。例如,您可以发送 foo.yourdomain.com 上的所有内容到 foo 服务,以及所有内容 在 bar 服务的 yourdomain.com/bar/ 路径下。
Ingress 可能是公开服务的最有效方式,但是 也可能是最复杂的。 Ingress 有多种类型 控制器,来自 Google Cloud Load Balancer、Nginx、Contour、 Istio 等等。还有用于 Ingress 控制器的插件,例如 证书管理器,可以自动提供 SSL 证书 为您服务。
如果您想公开多个服务,Ingress 是最有用的 在同一个IP地址下,这些服务都使用同一个L7 协议(通常是 HTTP)。如果您只为一个负载均衡器付费 正在使用原生 GCP 集成,并且因为 Ingress 是“智能的” 您可以获得很多开箱即用的功能(如 SSL、Auth、路由、 等)
【讨论】:
【参考方案3】:有 4 种方法可以让集群中的 pod 接收外部流量: 1.) 使用 HostNetworking 的 Pod:true 和(允许每个节点 1 个 pod 直接监听主机节点上的端口。Minikube、裸机和 rasberry pi 有时会走这条路线,这可以让主机节点监听端口80/443 允许不使用负载均衡器或高级云负载均衡器配置,它还绕过 Kubernetes 服务,这对于避免 SNAT/实现类似的 externalTrafficPolicy 效果很有用:在 AWS 不支持的场景中是本地的。) 2.) NodePort 服务 3.) LoadBalancer 服务(基于 NodePort 服务构建) 4.) 入口控制器 + 入口对象(基于上述)
假设您在集群中托管了 10 个网站,并且您希望将它们全部公开给外部流量。 *如果您使用 LoadBalancer Service 类型,您将生成 10 个 HA 云负载均衡器(每个都需要花钱) *如果您使用类型 Ingress Controller,您将生成 1 个 HA 云负载均衡器(节省资金),它将指向在您的集群中运行的 Ingress Controller。 入口控制器是:
负载均衡器类型的服务,由集群中运行的 pod 部署提供支持。 每个 pod 做 2 件事:-
充当在集群内运行的第 7 层负载均衡器。 (有多种口味 Nginx 很受欢迎)
根据集群中的入口对象动态配置自身
(可以将入口对象视为第 7 层负载均衡器的声明性配置片段。)
集群内的 L7 LB/Ingress Controller 负载平衡/反向代理流量到集群内的集群 IP 服务,如果您有 TLS 证书类型的 Kubernetes Secret 和引用它的 Ingress 对象,它也可以终止 HTTPS。)
【讨论】:
在图片中,HA LB 负载平衡到节点(例如循环),然后将这些请求发送到 IC pod?如果 IC 在单 pod 上运行,负载均衡有什么意义? 外部 LB 将流量传播到 NodePorts 正是 Kubernetes 设计用于接收外部流量的方式。 kube-proxy 将 LAN 上的 NodePorts 映射到集群中的服务。 (注意:通常是 kube-proxy,Cilium CNI 有替代方案)。然后 Kubernetes 服务充当内部集群 LB,因此一旦 kube-proxy 将 LB 服务的流量带到内部集群网络,内部集群服务就会开始 LB'ing 到使用标签标识的入口 pod。 Ingress Controller pod 通常由部署管理,因此您可以从 1 个 Ingress Controller pod 开始,但可以根据需要进行扩展。 还有一点是,这是可扩展的 LB 架构。 L7 LB 的扩展性不如 L4 LB。因此,使 L7 LB 规模化的常见 LB 架构模式是在 L7 LB 之前放置一个 L4 LB。将 HA CLB 想象为 L4 LB。 Ingress Controller pods 作为 L7 LB(由部署 + 水平 pod 自动扩缩器支持),这是一个在规模上运行良好的架构。 好的,谢谢。然后跟进问题。如果 IC 可以扩展并在许多 pod 上运行,如果它前面有一个 L4 LB(不理解 TCP 以上的协议),我们如何实现粘性会话(对于 L7 LB 是正常的)? 一般来说,不建议使用粘性会话,因为它们会限制扩展能力/在我看来,它们是解决糟糕架构设计的一个技巧,但如果你不得不使用它们。您需要在 Google 上搜索与您的 LB 类型的 Kubernetes 服务相关的文档,具体实现如何。大多数 L4 LB 都有一些 L7 意识。 AWS NLB(网络 = OSI L4),HA 代理最初是一个 L4 LB,但已经慢慢成长为具有一些 L7 功能。两者都支持粘性会话。也可以选择使用 L7 CSP LB 转发到 L7 Ingress LB,L7 CSP LB 往往带有流量 SLA。【参考方案4】:TL:DR
-
Ingress 位于公共网络 (Internet) 和 Kubernetes 服务之间,公开公开我们的 Api 实现。
Ingress 能够提供负载平衡、SSL 终止和基于名称的虚拟主机。
入口功能允许从单个域名安全地公开多个 API 或应用程序。
让我们从实际用例开始:您有多个由服务实现包支持的 API(ASIP 表示简洁明了)部署在一个域名下。由于您是一名尖端开发人员,因此您实现了一个微服务架构,该架构需要为每个 ASIP 单独部署,以便它们可以单独升级或扩展。当然,这些 ASIP 封装在单独的 docker 容器中,并且可以从容器存储库中提供给 Kubernetes (K8s)。
现在假设您想在 Google 的 GKE K8s 上部署它。为了实现持续可用性,每个 ASIP 实例(副本)都部署在不同的节点 (VM) 上,每个 VM 都有自己的云内部 IP 地址。每个 ASIP 部署都在一个恰当名称的“deployment.yaml”文件中进行配置,您可以在其中以声明方式指定给定 ASIP K8 应部署的副本数量等。
下一步是将 API 公开给外部世界,并将请求集中到已部署的 ASIP 实例之一。由于我们有许多相同 ASIP 的副本运行在不同的节点上,我们需要一些东西来在这些副本之间分配请求。为了解决这个问题,我们可以创建并应用一个“service.yaml”文件,该文件将配置一个 K8s 服务 (KServ),该服务将对外公开并通过 IP 地址访问。该 KServ 将负责 API 在其配置的 ASIP 之间的请求分发。请注意,当 ASIP 的节点发生故障并重新启动时,K8s master 将自动重新配置 KServ。在这种情况下,永远不会重复使用内部 IP 地址,并且必须告知 KServ 新 ASIP 的部署位置。
但是我们有其他的 API 服务包应该暴露在同一个域名上。旋转一个新的 KServ 将创建一个新的外部 IP 地址,我们将无法在同一个域名上公开它。嗯,这就是 Ingress 的用武之地。
Ingress 位于 Internet 和我们向外界公开的所有 KService 之间。 Ingress 能够提供负载平衡、SSL 终止和基于名称的虚拟主机。后一种能力能够通过分析其 URL 将传入请求路由到正确的服务。当然,Ingress 必须配置和应用...“ingress.yaml”文件,该文件将指定向正确 KServ 发送请求所需的重写和路由。
互联网 -> 入口 -> K8s 服务 -> 副本
因此,通过正确的入口、KServices 和 ASIPs 配置,我们可以使用相同的域名安全地公开许多 API。
【讨论】:
【参考方案5】:简单来说,负载均衡器在多个后端服务(相同类型)之间分配请求,而 Ingress 更像是一个 API 网关(反向代理),它根据例如 URL 将请求路由到特定后端服务.
【讨论】:
AWS 中的 ALB 将使用类似于带代理的 API 网关的路径进行路由。【参考方案6】:入口:入口对象 + 入口控制器
入口资源:
就像服务资源一样,除了它自己不做任何事情,因为默认情况下不包含入口控制器。 Ingress Resource 只是描述了一种将第 7 层流量路由到集群的方法,通过指定请求路径、请求域和目标 kubernetes 服务等内容,而添加服务对象实际上可能会创建服务,因为服务控制器包含在 Kubernetes 中默认。
入口控制器:
一项服务:
1. listens on specific ports (usually 80 and 443) for web traffic
2. Listens for the creation, modification, or deletion of Ingress Resources
3. Creates internal L7 routing rules based on these Ingress Resources
例如,Nginx Ingress Controller 可以使用服务来侦听端口 80 和 443,然后读取新的 Ingress 资源并将它们解析到新的服务器部分中, 部分会动态放置到它的 nginx.conf 中
LoadBalancer:外部负载均衡器提供者+服务类型
外部负载均衡器提供者:
外部负载均衡器提供商通常配置在 AWS 和 GKE 等云中,并提供一种通过创建外部负载均衡器来分配外部 IP 的方法。可以通过将服务指定为“LoadBalancer”类型来使用此功能。
服务类型:
当服务类型设置为 LoadBalancer 时,Kubernetes 会尝试创建并配置一个外部负载均衡器,其中包含 Kubernetes pod 的条目,从而为它们分配外部 IP。
Kubernetes 服务控制器自动创建外部负载均衡器、健康检查(如果需要)、防火墙规则(如果需要)并检索由云提供商分配并填充的新创建或配置的 LoadBalancer 的外部 IP它在服务对象中。
可以在集群上安装一个额外的云控制器,并分配读取服务资源及其注释,以便自动部署和配置云负载均衡器,接收 kubernetes 服务的流量。
关系:
Ingress Controller 服务通常配置为 LoadBalancer 类型,因此可以通过外部 ip 代理/路由 http 和 https 请求到特定的内部服务。
然而,LoadBalancer 并不是绝对必要的。因为,通过使用 hostNetwork 或 hostPort,您可以在技术上将主机上的端口绑定到服务(允许您通过主机外部 ip:port 访问它)。虽然官方不建议这样做,因为它会占用实际节点上的端口。
参考资料:
https://kubernetes.io/docs/concepts/configuration/overview/#services
https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/
https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#external-load-balancer-providers
https://kubernetes.io/docs/concepts/services-networking/ingress/
【讨论】:
【参考方案7】:Feature |
Ingress |
Load Balancer |
---|---|---|
Protocal | HTTP level (Network layer 7) | Network layer 4 |
Additional Features | cookie-based session affinity, Ingress rules, Resource backends, Path types | Only balance the load |
Dependency | Ingress controller need to be running. Different Kubernetes environments use different implementations of the controller, but several don’t provide a default controller at all. | No dependency, Built-in support with K8 |
YAML manifest | There is separate API for it. apiVersion: networking.k8s.io/v1
|
type: LoadBalancer |
How it work | Client connected to one of the pods through Ingress controller. The client first performed a DNS lookup of example.com, and the DNS server (or the local operating system) returned the IP of the Ingress controller. The client then sent an HTTP request to the Ingress controller and specified example.com in the Host header. From that header, the controller determined which service the client is trying to access, looked up the pod IPs through the Endpoints object associated with the service, and forwarded the client’s request to one of the pods. | The load balancer redirects traffic to the node port across all the nodes. Clients connect to the service through the load balancer’s IP. |
【讨论】:
【参考方案8】:LoadBalancer :这是向互联网公开服务的标准方式。
我们端口上的任何流量(HTTP / TCP / UDP / Websockets/ gRPC 等) 指定,将被转发到服务没有任何 过滤/路由。
入口:它位于多个服务的前面,充当我们集群的路由器/入口点。
让我们配置一组规则以传递给控制器 (基于 NGINX 的入口控制器 / Envoy 入口控制器 / GCP 正在监听它们的 Ingress Controller / Trefik / Istio) 如果我们想在同一个下暴露多个服务,这真的很有用 IP 地址。
【讨论】:
【参考方案9】:负载平衡器服务:是第 4 层代理(TCP、UDP、..)。它在 Kubernetes 集群网络之外运行。它没有第 7 层的功能:CircuitBreaker、测量请求数量、请求延迟、失败、路由……
ingress: 是第 7 层代理(http、https、gRPC、..)。它是 Kubernetes 集群网络内 pod 中的一个应用程序。如果 ingress pod 死亡,Kubernetes 将重新启动它或将其移动到集群中的其他节点。
【讨论】:
【参考方案10】:Pod 有自己的 IP:PORT
,但它本质上是动态的,并且会在删除或重新部署时发生变化。
服务被分配ClusterIP
或NodePort
(VM中创建服务资源的端口),可以映射到一组pod或其他后端[参见:headless services]
要访问正确的 Pod,请使用 ClusterIP
(从集群内)
NodePort
可用于从集群外部访问 pod
LoadBalancer[External/Internal]:由云提供商提供指向ClusterIP
或NodePort
。您可以使用LB的IP访问服务
LB ~> SERVICE(ClusterIP
or NodePort
) ~> POD
Ingress 资源是集群的入口点。LB 可以监听 Ingress 规则并可以路由到特定服务。[请参阅此example]
LB(入口管理)~> SERVICE(ClusterIP
或NodePort
)~> POD
【讨论】:
以上是关于入口与负载均衡器的主要内容,如果未能解决你的问题,请参考以下文章