Kubernetes 网络介绍(三)
Kube-Proxy
kube-proxy 是 Kubernetes 中的另一个每节点守护进程,类似于 Kubelet。 kube-proxy 在集群内提供基本的负载均衡功能。它实现服务并依赖于 Endpoints/EndpointSlices,这两个 API 对象我们将在后续有关网络抽象的内容中详细讨论。参考该部分可能会有所帮助,但以下是相关且快速的解释:
-
服务为一组 Pod 定义负载均衡器。 -
端点(和端点切片)列出一组就绪的 Pod IP。它们是从服务自动创建的,具有与服务相同的 pod 选择器。
大多数类型的服务都有一个服务的 IP 地址,称为集群 IP 地址,该地址在集群外部不可路由。 kube-proxy 负责将对服务集群 IP 地址的请求路由到健康的 Pod。 kube-proxy 是迄今为止 Kubernetes 服务最常见的实现,但是 kube-proxy 有替代方案,例如替代模式 Cilium。
kube-proxy 有四种模式,它们改变了它的运行时模式和确切的功能集:用户空间、iptables、ipvs 和内核空间。您可以使用 --proxy-mode <mode>
指定模式。值得注意的是,所有模式都在某种程度上依赖 iptables。
Userspace Mode
第一个也是最古老的模式是用户空间模式。在用户空间模式下,kube-proxy 运行 Web 服务器并使用 iptables 将所有服务 IP 地址路由到 Web 服务器。
Web 服务器终止连接并将请求代理到服务端点中的 pod。用户空间模式不再常用,我们建议避免使用它,除非您有明确的理由使用它。
Iptables Mode
iptables 模式完全使用 iptables。它是默认模式,也是最常用的(这可能部分是因为 IPVS 模式最近升级到 GA 稳定性,而 iptables 是一种熟悉的 Linux 技术)。
iptables 模式执行连接扇出,而不是真正的负载平衡。换句话说,iptables 模式会将连接路由到后端 pod,并且使用该连接发出的所有请求都将发送到同一个 pod,直到连接终止。这很简单,并且在理想场景中具有可预测的行为(例如,同一连接中的连续请求将能够从后端 Pod 中的任何本地缓存中受益)。在处理长期连接时,例如 HTTP/2 连接(值得注意的是,HTTP/2 是 gRPC 的传输),它也可能是不可预测的。
假设您有两个 pod,X 和 Y,提供服务,并且您在正常滚动更新期间将 X 替换为 Z。较旧的 Pod Y 仍然拥有所有现有连接,加上 Pod X 关闭时需要重新建立的一半连接,导致 Pod Y 提供的流量大幅增加。有很多类似的情况会导致流量不平衡。回想一下第 2 章“实用 iptables”部分中的示例。在其中,我们展示了 iptables 可以配置 IP 地址列表和随机路由概率,以便在所有 IP 地址之间随机建立连接。给定一个具有健康后端 Pod 10.0.0.1、10.0.0.2、10.0.0.3 和 10.0.0.4 的服务,kube-proxy 将创建路由连接的顺序规则,如下所示:
-
25% 的连接转到 10.0.0.1。
-
33.3% 的未路由连接转到 10.0.0.2。
-
50% 的未路由连接转到 10.0.0.3。
-
所有未路由的连接都转到 10.0.0.4。
这可能看起来不直观,并导致一些工程师认为 kube-proxy 正在错误路由流量(特别是因为当服务按预期工作时很少有人查看 kube-proxy)。关键的细节是,每个路由规则都适用于尚未在先前规则中路由的连接。最终规则将所有连接路由到 10.0.0.4(因为连接必须去某个地方),半决赛规则有 50% 的机会路由到 10.0.0.3 作为两个 IP 地址的选择,依此类推。路由随机性分数始终按 1 / ${剩余 IP 地址数} 计算。
以下是集群中 kube-dns 服务的 iptables 转发规则。在我们的示例中,kube-dns 服务的集群 IP 地址是 10.96.0.10。为了清晰起见,此输出已被过滤并重新格式化:
$ sudo iptables -t nat -L KUBE-SERVICES
Chain KUBE-SERVICES (2 references)
target prot opt source destination
/* kube-system/kube-dns:dns cluster IP */
udp dpt:domain KUBE-MARK-MASQ udp
-- !10.217.0.0/16 10.96.0.10
/* kube-system/kube-dns:dns cluster IP */
udp dpt:domain KUBE-SVC-TCOU7JCQXEZGVUNU
udp -- anywhere 10.96.0.10
/* kube-system/kube-dns:dns-tcp cluster IP */
tcp dpt:domain KUBE-MARK-MASQ tcp
-- !10.217.0.0/16 10.96.0.10
/* kube-system/kube-dns:dns-tcp cluster IP */
tcp dpt:domain KUBE-SVC-ERIFXISQEP7F7OF4
tcp -- anywhere 10.96.0.10
ADDRTYPE match dst-type LOCAL
/* kubernetes service nodeports; NOTE: this must be the last rule in this chain */
KUBE-NODEPORTS all -- anywhere anywhere
kube-dns 有一对 UDP 和 TCP 规则。我们将重点关注 UDP。
第一个 UDP 规则标记所有并非源自 Pod IP 地址(10.217.0.0/16 是默认 Pod 网络 CIDR)的服务连接以进行伪装。
下一个 UDP 规则将链 KUBE-SVC-TCOU7JCQXEZGVUNU 作为其目标。让我们仔细看看:
$ sudo iptables -t nat -L KUBE-SVC-TCOU7JCQXEZGVUNU
Chain KUBE-SVC-TCOU7JCQXEZGVUNU (1 references)
target prot opt source destination
/* kube-system/kube-dns:dns */
KUBE-SEP-OCPCMVGPKTDWRD3C all -- anywhere anywhere statistic mode random probability 0.50000000000
/* kube-system/kube-dns:dns */
KUBE-SEP-VFGOVXCRCJYSGAY3 all -- anywhere anywhere
在这里,我们看到一条有 50% 机会执行的链,以及否则将执行的链。如果我们检查第一个链,我们会看到它路由到 10.0.1.141,这是我们的两个 CoreDNS Pod 的 IP 之一:
$ sudo iptables -t nat -L KUBE-SEP-OCPCMVGPKTDWRD3C
Chain KUBE-SEP-OCPCMVGPKTDWRD3C (1 references)
target prot opt source destination
/* kube-system/kube-dns:dns */
KUBE-MARK-MASQ all -- 10.0.1.141 anywhere
/* kube-system/kube-dns:dns */
udp to:10.0.1.141:53
DNAT udp -- anywhere anywhere
Ipvs Mode
ipvs 模式使用第 2 章中介绍的 IPVS,而不是 iptables 来实现连接负载平衡。 ipvs模式支持六种负载均衡模式,通过--ipvsscheduler指定:
-
rr: Round-robin -
lc: 最少连接 -
dh: 目标哈希 -
sh: 源哈希 -
sed: 最短预期延迟 -
nq: 从不排队
循环 (rr) 是默认的负载均衡模式。它是最接近 iptables 模式行为的模拟(无论 pod 状态如何,连接都相当均匀),尽管 iptables 模式实际上并不执行循环路由。
Kernelspace Mode
内核空间是最新的、仅限 Windows 的模式。它为 Windows 上的 Kubernetes 提供了用户空间模式的替代方案,因为 iptables 和 ipvs 是 Linux 特有的。现在我们已经介绍了 Kubernetes 中 Pod 到 Pod 流量的基础知识,接下来让我们看一下 NetworkPolicy 和保护 Pod 到 Pod 流量的安全。
原文始发于微信公众号(Docker中文社区):Kubernetes 网络介绍(三)
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论