kube-proxy实现原理

介绍

kube-proxy,负责为Service提供集群内部的服务发现负载均衡

本文展示Kube-Proxy的工作原理。我们将解释创建服务时发生的流程。并展示Kube-Proxy创建的一些示例规则。

什么是Kube-Proxy

Kubernetes中的Pods是临时的,可随时被终止或重启。由于这种行为,我们不能依赖于它们的IP地址,因为它们总是在变。

这就是 Service 对象发挥作用的地方。Services为Pods提供一个稳定的IP地址,用于连接Pods。每个Service与一组Pods相关联。当流量到达Service时,根据规则将其重定向到相应的后端Pods。

“Service到Pod”映射在网络层如何实现?

这就是Kube-Proxy的作用。
Kube-Proxy是安装在 每个节点 中的Kubernetes代理。它监视与Service对象及其端点相关的更改。然后将这些更改转换为节点内的实际网络规则。Kube-Proxy通常以 DaemonSet 的形式在集群中运行。但也可直接作为节点上的Linux进程安装。取决于你的集群安装类型:

  • 用 kubeadm,它将以DaemonSet的形式安装Kube-Proxy
  • 用官方Linux tarball二进制文件 手动安装集群组件,它将直接作为节点上的进程运行

工作原理

安装Kube-Proxy后,它将与API服务器进行身份验证。当新的Service或端点被添加或移除时,API服务器会将这些更改传递给Kube-Proxy。

Kube-Proxy然后在节点内将这些更改应用为 NAT 规则。这些NAT规则简单将Service IP映射到Pod IP。

当流量被发送到一个Service时,根据这些规则,它将被重定向到相应的后端Pods。

实例

有一类型为ClusterIP的Service SVC01。创建此Service时,API服务器将检查要与该Service关联的Pods。因此,它将查找具有与Service的 label selector 匹配的 labels 的Pods。称这些为 Pod01 和 Pod02。

现在APIServer将创建一个称为 endpoint 的抽象。每个endpoint代表一个Pod的IP。现在,SVC01与2个端点关联,对应我们的Pods。称这些为 EP01EP02

现在API服务器将 SVC01 的IP地址映射到2个IP地址 EP01EP02

kube-proxy实现原理
kube-proxy实现原理
kube-proxy实现原理

所有这些配置目前只是控制平面的一部分。我们希望这个映射实际上应用在网络上。一旦应用,到 SVC01 IP的流量将被转发到 EP01EP02

这就是Kube-Proxy的作用。API服务器将向每个节点的Kube-Proxy宣传这些更新。然后Kube-Proxy将其应用为节点内部的规则。

kube-proxy实现原理
kube-proxy实现原理

现在,流向SVC01 IP的流量将遵循这个 DNAT 规则,并被转发到Pods。请记住,EP01和EP02基本上是Pods的IP。

kube-proxy实现原理
kube-proxy实现原理

当然,我试图尽量简化情景。这只是为了集中关注Kube-Proxy的重要部分。然而,值得一提的有几点:

  1. Service和endpoint是 IP和端口 映射,而不仅仅是IP。
  2. 在示例中,DNAT翻译发生在 源节点 上。这是因为我们使用了 ClusterIP 类型的Service。这就是为什么ClusterIP永远不会路由到集群外部的原因。它只能从集群内部访问,因为它基本上是一个内部NAT规则。换句话说,集群外部没有人知道这个IP。
  3. 如果使用其他类型Service,则在节点内部安装其他规则。它们可能被分开放置在所谓的 chain 中。虽然这超出了主题的范围,但链是Linux机器中的一组规则。它们有一个特定的类型,并且按照流量路径中的特定顺序应用。
  4. NAT规则随机选择一个Pod。然而,此行为可能取决于Kube-Proxy的“模式”。

Kube-Proxy模式

Kube-Proxy可以不同模式运行。每个模式决定了Kube-Proxy如何实现我们提到的NAT规则。由于每个模式都有其优缺。

kube-proxy实现原理

1、userspace 模式
k8s v1.2 就被淘汰:

kube-proxy 监视 Kubernetes 控制平面对 Service 和 EndpointSlice 对象的增加、修改和删除。 对于每个 Service,kube-proxy 在本地节点用户空间创建一个ClusterIP:Port 的 Socket 套接字(监听端口随机),并增加一个 iptables 规则。任何对这个代理端口的连接都将代理到 Service 的一个后端 Pod。

从客户端到 ClusterIP:Port 的报文都会通过 iptables 规则被重定向到 kube-proxy创建的Proxy Port,Kube-Proxy 收到报文后,然后分发给对应 Pod。

缺点

kube-proxy实现原理

默认用户空间模式下的 kube-proxy 通过round-robin轮巡算法选择后端。

2、IPtables模式

kube-proxy实现原理

默认和目前最广泛使用的模式。该模式下的Kube-Proxy依赖于Linux的一个特性IPtables

Linux 中最常用的一种防火墙工具,还可用作 IP 转发和简单的负载均衡功能。基于 Linux 中的 netfilter 内核模块实现。 Netfilter 在协议中添加了一些钩子,它允许内核模块通过这些钩子注册回调函数,这样经过钩子的所有数据都会被注册在响应钩子上的函数处理,包括修改数据包内容、给数据包打标记或者丢掉数据包等。iptables 是运行在用户态的一个程序,通过 netlink 和内核的 netfilter 框架打交道,具有足够的灵活性来处理各种常见的数据包操作和过滤需求。它允许将灵活的规则序列附加到内核的数据包处理管道中的各种钩子上。

Netfilter 是 Linux 2.4.x 引入的一个子系统,它作为一个通用的、抽象的框架,提供一整套的 hook 函数的管理机制,使得诸如数据包过滤、网络地址转换(NAT)和基于协议类型的连接跟踪成为了可能。

kubernetes v1.2 之后 iptables 成为默认代理模式,这种模式下,kube-proxy 会监视 Kubernetes master 对 Service 对象和 Endpoints 对象的添加和移除。 对每个 Service,它会安装 iptables 规则,从而捕获到达该 Service 的 clusterIP(虚拟 IP)和端口的请求,进而将请求重定向到 Service 的一组 backend 中的某个上面。因为流量转发都是在内核进行的,所以性能更高更加可靠。

IPtables作为一个内部的数据包处理和过滤组件。它检查发往和发自Linux机器的流量。然后,它对匹配特定条件的数据包应用特定的规则。

在运行此模式时,Kube-Proxy将Service到Pod的NAT规则插入IPtables。这样,流量在将目标IP从Service IP转换为Pod IP后被重定向到相应的后端Pods。

现在Kube-Proxy的角色可以更多地被描述为规则的“安装者”。

kube-proxy实现原理
kube-proxy实现原理

该模式下 iptables 做用户态的入口,kube-proxy 不再为每个 Service 创建反向代理(也就是无需创建 Socket 监听),kube-proxy 只是持续监听 Service 以及 Endpoints 对象的变化,捕获访问 Service ClusterIP:Port 的流量,直接重定向到指定的 Endpoints 后端。Iptables 使用 DNAT 来完成转发,其采用了随机数实现负载均衡。

但是将数据转发完全交给 iptables 来做也有个缺点,就是一旦选择的后端没有响应,连接就会直接失败了,而不会像 userspace 模式那样,反向代理可以支持自动重新选择后端重试,算是失去了一定的重试灵活性。不过,官方建议使用 Readiness 探针来解决这个问题,一旦检测到后端故障,就自动将其移出 Endpoint 列表,避免请求被代理到存在问题的后端。

优缺点

优点:1、该模式相比 userspace 模式,克服了请求在用户态-内核态反复传递的问题,性能有所提升,2、而且也避免了大量宿主机端口被占用的问题。

缺点:1、但使用 iptables NAT 来完成转发,最主要问题是在 service 数量大的时候会产生太多的 iptables 规则,使用非增量式更新会引入一定时延,大规模情况下有明显性能问题。IPtables使用顺序遍历其表。因为它最初是设计为一个数据包过滤组件。这种顺序算法在规则增加时不适用。在我们的场景中,这将是Service和端点的数量。将这一点低级别地看,该算法将按O(n)性能进行。这意味着查询次数的增加是线性增加。2、此外,IPtables不支持特定的负载平衡算法。它使用一个随机等成本的分发方式。

3、IPVS模式

kube-proxy实现原理

专门设计用于负载平衡的Linux功能,成为Kube-Proxy使用的理想选择。在这种模式下,Kube-Proxy将规则插入到IPVS而非IPtables。

IPVS具有优化的查找算法(哈希),复杂度为O(1)。这意味着无论插入多少规则,它几乎都提供一致的性能。

在我们的情况下,这意味着对于Services和端点的更有效的连接处理。

IPVS还支持不同LB算法,如轮询,最小连接和哈希方法。

轮转(rr) round-robin:轮转调度算法将每个传入请求发送到其列表中的下一个服务器。因此,在三服务器集群(服务器A,B和C)中,请求1将转到服务器A,请求2将转到服务器B,请求3将转到服务器C,请求4将转到服务器A,这样就完成了服务器的循环或“轮转”。
最少连接(lc) least connection:最少连接调度算法将网络连接定向到具有最少数量的已建立连接的服务器。
目标地址哈希(dh) destination hashing:目标地址哈希调度算法根据请求的目标IP地址查找静态分配的哈希表来为服务器分配网络连接。
源地址哈希(sh) source hashing :源地址哈希调度算法根据请求的源IP地址查找静态分配的哈希表来为服务器分配网络连接。
最短预期延迟(sed) shortest expected delay :最短预期延迟调度算法以最短的预期延迟将网络连接分配给服务器。如果发送到第i个服务器,作业将经历的预期延迟为 (Ci + 1)/ Ui,其中Ci是第i个服务器上的连接数,Ui是第i个服务器的固定服务速率(权重)
永不排队(nq) never queue:永不排队调度算法采用双速模型。当有空闲服务器可用时,作业将被发送到空闲服务器,而不是等待快速服务器。当没有空闲服务器时,作业将被发送到最短预期延迟的服务器(最短预期延迟调度算法)。

尽管它有优势,但是IPVS可能不在所有Linux系统中都存在。与几乎每个Linux操作系统都有的IPtables相比,IPVS可能不是所有Linux系统的核心功能。如果你的Services数量不太多,IPtables应该完美工作。

kube-proxy实现原理

4、KernelSpace模式

此模式特定于Windows节点。在此模式中,Kube-proxy使用Windows的 Virtual Filtering Platform (VFP) 来插入数据包过滤规则。Windows上的 VFP 与Linux上的IPtables的工作方式相同,这意味着这些规则也将负责重写数据包封装并将目标IP地址替换为后端Pod的IP。

可将 VFP 想象成最初用于虚拟机网络的Hyper-V交换机的扩展。

如何检查Kube-Proxy模式

默认,Kube-Proxy在端口10249上运行,并暴露一组端点,你可以使用这些端点查询Kube-Proxy的信息。

你可以使用 /proxyMode 端点检查kube-proxy的模式。

首先通过SSH连接到集群中的一个节点。然后使用命令 curl -v localhost:10249/proxyMode

kube-proxy实现原理

可看到Kube-Proxy正在使用iptables模式。

检查ClusterIP服务的IPtables规则

创建一个ClusterIP服务并检查创建的规则。

先决条件:

  • 一个工作的Kubernetes集群(单节点或多节点)
  • 安装了Kubectl以连接到集群并创建所需的资源
  • 在我们将检查规则的节点上启用了SSH

步骤

先创建一个具有2个副本的redis部署。

kubectl create deployment redis --image=redis
kubectl scale deployment redis --replicas=2
kube-proxy实现原理

你可以看到我们有2个正在运行的Pods以及它们的IP地址。

创建一个与这些Pods关联的Service。为此,我们使用具有匹配Pods标签的选择器创建Service。这里默认类型是 ClusterIP。

kubectl expose deployment redis --name=redis-expose --port=6379
kube-proxy实现原理

现在,如果我们列出端点,我们会发现我们的服务有两个与我们的 Pod 相对应的端点。

kube-proxy实现原理

您会注意到这两个端点代表 Pod 的 IP 地址。

到目前为止,所有这些配置都相当直观。现在让我们深入探讨一下引擎下的魔术。我们将列出其中一个节点上的 IPtables 规则。请注意,您首先需要 SSH 登录到节点才能运行以下命令。

iptables -t nat -L PREROUTING
kube-proxy实现原理

首先让我们解释一下我们的命令选项。“-t nat” 是我们要列出的表的类型。IPtables 包含多个表类型,对于 Kube-Proxy,它使用 NAT 表。这是因为 Kube-Proxy 主要使用 IPtables 来翻译服务 IP。

还记得我们提到的链概念吗?这里的 “-L PREROUTING” 指的是表中链的名称。这是 IPtables 中默认存在的一个链。Kube-Proxy 将其规则挂接到该链中。

简而言之,在这里,我们要列出 PREROUTING 链中的 nat 规则。

现在让我们移动到命令输出。输出中最重要的部分是 KUBE-SERVICES 行。这是由 Kube-Proxy 为服务创建的自定义链。您会注意到该规则将任何源和任何目标的流量转发到此链中。换句话说,通过 PREROUTING 链传递的数据包将被定向到 KUBE-SERVICES 链。

那么让我们查看这个 KUBE-SERVICES 中的内容。

kube-proxy实现原理

现在这里的加密是什么意思呢?嗯,简单地说,这些是另外一些链。

对我们来说,这里重要的是 IP 地址。您会注意到创建了一个特定链,其目标 IP 是服务的 IP(10.109.234.11)。这意味着流向服务的流量将进入该链。

您还可以在 IP 地址右侧看到一些信息。这些表示服务名称、服务类型和端口。

所有这些都确保我们正在查看 IPtables 的正确部分。现在让我们进入这个链。

kube-proxy实现原理

最后,我们到达了我们的 NAT 规则。您会发现创建了两个额外的链。每个都以 KUBE-SEP 开头,然后是一个随机的 ID。这对应于服务端点(SEP)。

在中间看到这一行 statistic mode random probability 吗?这是 IPtables 在 Pod 之间进行的随机负载平衡规则。

进入这些 KUBE-SEP 链中的任何一个,我们可以看到它基本上是一个 DNAT 规则。

这就是服务的 IPtables 规则。由于现在您知道如何深入挖掘,您可以开始在您的环境中探索更多这些规则

kube-proxy实现原理

一些问题解答:

Kubernetes service是代理吗?

是的,Kubernetes service很像代理。

它提供一个稳定的 IP,客户端可以连接到该 IP。接收到该 IP 上的流量会被重定向到后端 Pod 的 IP。这克服了每次重新创建 Pod 时 Pod IP 更改的问题。

Kube-Proxy 能执行LB吗?

这取决于 Kube-Proxy 的哪个部分:

  • Kube-Proxy 代理本身,答案是否定。Kube-Proxy 代理不接收实际流量,也不执行任何负载平衡。此代理仅是创建服务规则的控制平面的一部分
  • Kube-Proxy 创建的规则,肯定的。Kube-Proxy 创建用于在多个 Pod 之间进行流量负载平衡的服务规则。这些 Pod 是彼此的副本,并与特定服务相关联

Kube-Proxy 是一个 Kubernetes 代理,将服务定义转换为网络规则。它在集群中的每个节点上运行,并与 API 服务器通信以接收更新。然后,这些更新由节点内的 Kube-Proxy 填充。通过创建这些规则,Kube-Proxy 允许发送到服务的流量被转发到正确的Pod。这实现了 Pod IP 与连接到它的客户端的解耦。

发布者:LJH,转发请注明出处:https://www.ljh.cool/39906.html

(0)
上一篇 2024年1月11日 下午8:41
下一篇 2024年1月15日 下午9:55

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注