我对 Kubernetes 中 Ingress 和 Load Balancer 的角色感到很困惑。
据我了解,Ingress 用于将来自互联网的传入流量映射到集群中运行的服务。
负载均衡器的作用是将流量转发到主机。在这方面,入口与负载均衡器有何不同?与 Amazon ELB 和 ALB 相比,kubernetes 内部的负载均衡器的概念是什么?
我对 Kubernetes 中 Ingress 和 Load Balancer 的角色感到很困惑。
据我了解,Ingress 用于将来自互联网的传入流量映射到集群中运行的服务。
负载均衡器的作用是将流量转发到主机。在这方面,入口与负载均衡器有何不同?与 Amazon ELB 和 ALB 相比,kubernetes 内部的负载均衡器的概念是什么?
负载均衡器: kubernetes LoadBalancer 服务是指向外部负载均衡器的服务,这些负载均衡器不在您的 kubernetes 集群中,但存在于其他地方。假设您的 pod 可在外部路由,它们可以与您的 pod 一起工作。Google 和 AWS 本身就提供了这种能力。就亚马逊而言,这直接与 ELB 和 kubernetes 进行映射,在 AWS 中运行时可以为部署的每个 LoadBalancer 服务自动预置和配置一个 ELB 实例。
入口:入口实际上只是传递给正在侦听它们的控制器的一组规则。你可以部署一堆入口规则,但除非你有一个可以处理它们的控制器,否则什么都不会发生。LoadBalancer 服务可以侦听入口规则,如果它被配置为这样做的话。
您还可以创建一个NodePort服务,该服务在集群外部具有可外部路由的 IP,但指向集群中存在的 pod。这可能是一个入口控制器。
入口控制器只是一个配置为解释入口规则的 pod。Kubernetes 支持的最流行的入口控制器之一是 nginx。在亚马逊方面,ALB可以用作入口控制器。
例如,这个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
集群中的服务。
这是一个如何使用 nginx 入口控制器实现 Kubernetes 集群的示例。希望这可以帮助!
我发现这篇非常有趣的文章解释了 NodePort、LoadBalancer 和 Ingress 之间的区别。
从文章中的内容来看:
负载均衡器:
LoadBalancer 服务是向 Internet 公开服务的标准方式。在 GKE 上,这将启动一个网络负载均衡器,它会为您提供一个 IP 地址,该地址会将所有流量转发到您的服务。
如果你想直接暴露一个服务,这是默认的方法。您指定的端口上的所有流量都将转发到该服务。没有过滤,没有路由等。这意味着您可以向它发送几乎任何类型的流量,例如 HTTP、TCP、UDP、Websockets、gRPC 或其他任何类型的流量。
最大的缺点是,您使用 LoadBalancer 公开的每个服务都将获得自己的 IP 地址,并且您必须为每个公开的服务支付 LoadBalancer,这可能会变得昂贵!
入口:
Ingress 实际上不是一种服务。相反,它位于多个服务的前面,充当“智能路由器”或集群的入口点。
您可以使用 Ingress 做很多不同的事情,并且有许多类型的 Ingress 控制器具有不同的功能。
默认的 GKE 入口控制器将为您启动一个 HTTP(S) 负载均衡器。这将允许您对后端服务进行基于路径和基于子域的路由。例如,您可以将 foo.yourdomain.com 上的所有内容发送到 foo 服务,并将 yourdomain.com/bar/ 路径下的所有内容发送到 bar 服务。
Ingress 可能是最强大的暴露服务的方式,但也可能是最复杂的。有多种类型的 Ingress 控制器,包括 Google Cloud Load Balancer、Nginx、Contour、Istio 等。还有一些用于 Ingress 控制器的插件,例如 cert-manager,可以自动为您的服务提供 SSL 证书。
如果您想在同一个 IP 地址下暴露多个服务,并且这些服务都使用相同的 L7 协议(通常是 HTTP),则 Ingress 是最有用的。如果您使用原生 GCP 集成,您只需为一个负载均衡器付费,并且由于 Ingress 是“智能”的,您可以立即获得许多功能(如 SSL、Auth、路由等)
有 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 服务,您将生成 10 个 HA 云负载均衡器(每个都需要花钱)
*如果您使用类型 Ingress Controller,您将生成 1 个 HA 云负载均衡器(省钱),它会指向一个 Ingress在集群中运行的控制器。
入口控制器是:
集群内的 L7 LB/Ingress Controller 负载平衡/反向代理流量到集群内的集群 IP 服务,如果你有 TLS 证书类型的 Kubernetes Secret 和引用它的 Ingress 对象,它也可以终止 HTTPS。)
TL:博士
让我们从实际用例开始:您有多个由服务实现包支持的 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 和我们向外界公开的所有 KServices 之间。Ingress 能够提供负载平衡、SSL 终止和基于名称的虚拟主机。后一种能力能够通过分析其 URL 将传入请求路由到正确的服务。当然,Ingress 必须配置和应用...“ingress.yaml”文件,该文件将指定向正确的 KServ 发送请求所需的重写和路由。
互联网 -> 入口 -> K8s 服务 -> 副本
因此,通过正确的入口、KServices 和 ASIPs 配置,我们可以使用相同的域名安全地公开许多 API。
精简版:
在 Kubernetes 中,对象定义定义了所需的状态,而控制器监视对象定义以实现该状态。
入口:
负载均衡器:
入口对象:
一个 kubernetes 对象,它自己不做任何事情,因为默认情况下不包含 Ingress Controller。Ingress Object 只是描述了一种通过指定请求路径、请求域和目标 kubernetes 服务等内容将第 7 层流量路由到集群的方法,而添加服务对象实际上可能会创建服务,因为服务控制器默认包含在 Kubernetes 中.
入口控制器:
一个 Kubernetes 部署/DaemonSet + 服务,它:
1. listens on specific ports (usually 80 and 443) for web traffic
2. Watches for the creation, modification, or deletion of Ingress Resources
3. Creates internal L7 routing rules based on desired state indicated by Ingress Objects
例如,Nginx 入口控制器可能:
负载均衡器控制器:
负载均衡器控制器可以在 AWS 和 GKE 等平台中进行配置,并提供一种通过创建外部负载均衡器来分配外部 IP 的方法。此功能可用于:
服务类型:
当服务类型设置为 LoadBalancer 并且存在云提供的负载均衡器控制器时,该服务将使用云提供商的负载均衡器对外公开。外部负载均衡器路由到的 NodePort 和 ClusterIP 服务会自动创建,从而分配服务外部 IP 和/或 DNS。
Ingress Controller Services 通常被配置为 LoadBalancer 类型,以便 http 和 https 请求可以通过外部 ip 代理/路由到特定的内部服务。
但是,对此并不严格需要 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/concepts/services-networking/ingress/ https://kubernetes.io/docs/concepts/architecture/cloud-controller/ https://kubernetes-sigs.github.io/aws-负载平衡器控制器/v2.3/
简而言之,负载均衡器在多个后端服务(相同类型)之间分配请求,而入口更像是一个 API 网关(反向代理),它根据例如 URL 将请求路由到特定的后端服务。
Feature |
Ingress |
Load Balancer |
---|---|---|
协议 | HTTP 级别(网络第 7 层) | 网络层 4 |
附加的功能 | 基于 cookie 的会话亲和性、入口规则、资源后端、路径类型 | 只平衡负载 |
依赖 | 入口控制器需要运行。不同的 Kubernetes 环境使用不同的控制器实现,但有几个根本不提供默认控制器。 | 无依赖,内置支持 K8 |
YAML 清单 | 它有单独的 API。apiVersion: networking.k8s.io/v1 |
type: LoadBalancer |
它是如何工作的 | 客户端通过 Ingress 控制器连接到其中一个 pod。客户端首先对 example.com 进行 DNS 查找,DNS 服务器(或本地操作系统)返回 Ingress 控制器的 IP。然后客户端向 Ingress 控制器发送 HTTP 请求,并在 Host 标头中指定 example.com。从该标头中,控制器确定客户端尝试访问的服务,通过与服务关联的Endpoints 对象查找 pod IP ,并将客户端的请求转发到其中一个 pod。 | 负载均衡器将流量重定向到所有节点的节点端口。客户端通过负载均衡器的 IP 连接到服务。 |
负载均衡器服务:是第 4 层代理(TCP、UDP、..)。它在 Kubernetes 集群网络之外运行。它没有第 7 层的功能:CircuitBreaker,测量请求数量,请求延迟,失败,路由,......
ingress:是第 7 层代理(http、https、gRPC、..)。它是 Kubernetes 集群网络内 pod 中的一个应用程序。如果 ingress pod 死亡,Kubernetes 将重新启动它或将其移动到集群中的其他节点。
Pod 有自己的IP:PORT
,但本质上是动态的,如果删除或重新部署,它会发生变化。
分配服务ClusterIP
或NodePort
(创建服务资源的 VM 中的端口)可以映射到一组 pod 或其他后端 [参见:无头服务]
访问正确的 Pod 使用ClusterIP
(从集群内)
NodePort
可用于从集群外部访问 pod
LoadBalancer[External/Internal]:由云提供商提供,指向ClusterIP
或NodePort
。您可以使用LB的IP访问该服务
LB ~> SERVICE(ClusterIP
或NodePort
) ~> POD
Ingress 资源是集群的入口点。一个 LB 可以监听 ingress 规则并可以路由到特定的服务。[见这个例子]
LB(入口管理)~> SERVICE(ClusterIP
或NodePort
)~> POD