Kubernetes中的网络原理解析该怎么理解

77次阅读
没有评论

共计 3938 个字符,预计需要花费 10 分钟才能阅读完成。

这篇文章给大家介绍 Kubernetes 中的网络原理解析该怎么理解,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

01 覆盖网络

覆盖⽹络 (overlay network) 是将 TCP 数据包装在另⼀种⽹络包⾥⾯进⾏路由转发和通信的技术。Overlay ⽹络不是默认必须的,但是它们在特定场景下⾮常有⽤。⽐如当我们没有⾜够的 IP 空间,或者⽹络⽆法处理额外路由,抑或当我们需要 Overlay 提供的某些额外管理特性。⼀个常⻅的场景是当云提供商的路由表能处理的路由数是有限制时,例如 AWS 路由表最多⽀持 50 条路由才不⾄于影响⽹络性能。因此如果我们有超过 50 个 Kubernetes 节点,AWS 路由表将不够。这种情况下,使⽤ Overlay ⽹络将帮到我们。

本质上来说,Overlay 就是在跨节点的本地⽹络上的包中再封装⼀层包。你可能不想使⽤ Overlay ⽹络,因为它会带来由封装和解封所有报⽂引起的时延和复杂度开销。通常这是不必要的,因此我们应当在知道为什么我们需要它时才使⽤它。

为了理解 Overlay ⽹络中流量的流向,我们拿 Flannel 做例⼦,它是 CoreOS 的⼀个开源项⽬。Flannel 通过给每台宿主机分配⼀个⼦⽹的⽅式为容器提供虚拟⽹络,它基于 Linux TUN/TAP,使⽤ UDP 封装 IP 包来创建 overlay ⽹络,并借助 etcd 维护⽹络的分配情况。

Kubernetes 中的网络原理解析该怎么理解

Kubernetes Node with route table (通过 Flannel Overlay 网络进行跨节点的 Pod-to-Pod 通信)

这⾥我们注意到它和之前我们看到的设施是⼀样的,只是在 root netns 中新增了⼀个虚拟的以太⽹设备,称为 flannel0。它是虚拟扩展⽹络 Virtual Extensible LAN(VXLAN)的⼀种实现,但是在 Linux 上,它只是另⼀个⽹络接⼝。

从 pod1 到 pod4(在不同节点)的数据包的流向类似如下:

1)它由 pod1 中 netns 的 eth0 ⽹⼝离开,通过 vethxxx 进⼊ root netns。
2)然后被传到 cbr0,cbr0 通过发送 ARP 请求来找到⽬标地址。
3)数据封装

3a. 由于本节点上没有 Pod 拥有 pod4 的 IP 地址,因此⽹桥把数据包发送给了 flannel0,因为节点的路由表上 flannel0 被配成了 Pod ⽹段的⽬标地址。

3b. flanneld daemon 和 Kubernetes apiserver 或者底层的 etcd 通信,它知道所有的 Pod IP,并且知道它们在哪个节点上。因此 Flannel 创建了 Pod IP 和 Node IP 之间的映射(在⽤户空间)。flannel0 取到这个包,并在其上再⽤⼀个 UDP 包封装起来,该 UDP 包头部的源和⽬的 IP 分别被改成了对应节点的 IP,然后发送这个新包到特定的 VXLAN 端⼝(通常是 8472)。

Kubernetes 中的网络原理解析该怎么理解

Packet-in-packet encapsulation(notice the packet is encapsulated from 3c to 6b in previous diagram)

尽管这个映射发⽣在⽤户空间,真实的封装以及数据的流动发⽣在内核空间,因此仍然是很快的。

3c. 封装后的包通过 eth0 发送出去,因为它涉及了节点间的路由流量。

4. 包带着节点 IP 信息作为源和⽬的地址离开本节点。
5. 云提供商的路由表已经知道了如何在节点间发送报⽂,因此该报⽂被发送到⽬标地址 node2。
6. 数据解包

6a. 包到达 node2 的 eth0 ⽹卡,由于⽬标端⼝是特定的 VXLAN 端⼝,内核将报⽂发送给了
flannel0。
6b. flannel0 解封报⽂,并将其发送到 root 命名空间下。从这⾥开始,报⽂的路径和我们之前在 Part1 中看到的⾮ Overlay ⽹络就是⼀致的了。
6c. 由于 IP forwarding 开启着,内核按照路由表将报⽂转发给了 cbr0。

7. ⽹桥获取到了包,发送 ARP 请求,发现⽬标 IP 属于 vethyyy。
8. 包跨过管道对到达 pod4

这就是 Kubernetes 中 Overlay ⽹络的⼯作⽅式,虽然不同的实现还是会有细微的差别。有个常⻅的误区是,当我们使⽤ Kubernetes,我们就不得不使⽤ Overlay ⽹络。事实是,这完全依赖于特定场景。因此请确保在确实需要的场景下才使⽤。

02 动态集群

由于 Kubernetes(更通⽤的说法是分布式系统)天⽣具有不断变化的特性,因此它的 Pod(以及 Pod 的 IP)总是在改变。变化的原因可以是针对不可预测的 Pod 或节点崩溃⽽进⾏的滚动升级和扩展。这使得 Pod IP 不能直接⽤于通信。我们看⼀下 Kubernetes Service,它是⼀个虚拟 IP,并伴随着⼀组 Pod IP 作为 Endpoint(通过标签选择器识别)。它们充当虚拟负载均衡器,其 IP 保持不变,⽽后端 Pod IP 可能会不断变化。

Kubernetes 中的网络原理解析该怎么理解

Kubernetes service 对象中的 label 选择器

整个虚拟 IP 的实现实际上是⼀组 iptables(最新版本可以选择使⽤ IPVS,但这是另⼀个讨论)规则,由 Kubernetes 组件 kube-proxy 管理。这个名字现在实际上是误导性的。它在 v 1.0 之前确实是⼀个代理,并且由于其实现是内核空间和⽤户空间之间的不断复制,它变得⾮常耗费资源并且速度较慢。现在,它只是⼀个控制器,就像 Kubernetes 中的许多其它控制器⼀样,它 watch api serverendpoint 的更改并相应地更新 iptables 规则。

Kubernetes 中的网络原理解析该怎么理解

Iptables DNAT

有了这些 iptables 规则,每当数据包发往 Service IP 时,它就进⾏ DNAT(DNAT= ⽬标⽹络地址转换)操作,这意味着⽬标 IP 从 Service IP 更改为其中⼀个 Endpoint – Pod IP – 由 iptables 随机选择。这可确保负载均匀分布在后端 Pod 中。

Kubernetes 中的网络原理解析该怎么理解

conntrack 表中的 5 元组条⽬

当这个 DNAT 发⽣时,这个信息存储在 conntrack 中——Linux 连接跟踪表(iptables 规则 5 元组转译并完成存储:protocol,srcIP,srcPort,dstIP,dstPort)。这样当请求回来时,它可以 un-DNAT,这意味着将源 IP 从 Pod IP 更改为 Service IP。这样,客户端就不⽤关⼼后台如何处理数据包流。

因此通过使⽤ Kubernetes Service,我们可以使⽤相同的端⼝⽽不会发⽣任何冲突(因为我们可以将端⼝重新映射到 Endpoint)。这使服务发现变得⾮常容易。我们可以使⽤内部 DNS 并对服务主机名进⾏硬编码。

我们甚⾄可以使⽤ Kubernetes 提供的 service 主机和端⼝的环境变量来完成服务发现。

专家建议:采取第⼆种⽅法,你可节省不必要的 DNS 调⽤,但是由于环境变量存在创建顺序的局限性(环境变量中不包含后来创建的服务),推荐使⽤ DNS 来进⾏服务名解析。

2.1 出站流量

到⽬前为⽌我们讨论的 Kubernetes Service 是在⼀个集群内⼯作。但是,在⼤多数实际情况中,应⽤程序需要访问⼀些外部 api/website。通常,节点可以同时具有私有 IP 和公共 IP。对于互联⽹访问,这些公共和私有 IP 存在某种 1:1 的 NAT,特别是在云环境中。对于从节点到某些外部 IP 的普通通信,源 IP 从节点的专⽤ IP 更改为其出站数据包的公共 IP,⼊站的响应数据包则刚好相反。但是,当 Pod 发出与外部 IP 的连接时,源 IP 是 Pod IP,云提供商的 NAT 机制不知道该 IP。因此它将丢弃具有除节点 IP 之外的源 IP 的数据包。

因此你可能也猜对了,我们将使⽤更多的 iptables!这些规则也由 kube-proxy 添加,执⾏ SNAT(源⽹络地址转换),即 IP MASQUERADE(IP 伪装)。它告诉内核使⽤此数据包发出的⽹络接⼝的 IP,代替源 Pod IP 同时保留 conntrack 条⽬以进⾏反 SNAT 操作。

2.2 入站流量

到⽬前为⽌⼀切都很好。Pod 可以互相交谈,也可以访问互联⽹。但我们仍然缺少关键部分 – 为⽤户请求流量提供服务。截⾄⽬前,有两种主要⽅法可以做到这⼀点:

NodePort / 云负载均衡器(L4 – IP 和端⼝)

将服务类型设置为 NodePort 默认会为服务分配范围为 30000-33000d 的 nodePort。即使在特定节点上没有运⾏ Pod,此 nodePort 也会在每个节点上打开。此 NodePort 上的⼊站流量将再次使⽤ iptables 发送到其中⼀个 Pod(该 Pod 甚⾄可能在其它节点上!)。

云环境中的 LoadBalancer 服务类型将在所有节点之前创建云负载均衡器(例如 ELB),命中相同的 nodePort。

Ingress(L7 – HTTP / TCP)

许多不同的⼯具,如 Nginx,Traefik,HAProxy 等,保留了 http 主机名 / 路径和各⾃后端的映射。通常这是基于负载均衡器和 nodePort 的流量⼊⼝点,其优点是我们可以有⼀个⼊⼝处理所有服务的⼊站流量,⽽不需要多个 nodePort 和负载均衡器。

2.3 网站策略

可以把它想象为 Pod 的安全组 / ACL。NetworkPolicy 规则允许 / 拒绝跨 Pod 的流量。确切的实现取决于⽹络层 /CNI,但⼤多数只使⽤ iptables。

⽬前为⽌就这样了。在前⾯的部分中,我们研究了 Kubernetes ⽹络的基础以及 overlay ⽹络的⼯作原理。现在我们知道 Service 抽象是如何在⼀个动态集群内起作⽤并使服务发现变得⾮常容易。我们还介绍了出站和⼊站流量的⼯作原理以及⽹络策略如何对集群内的安全性起作⽤。

关于 Kubernetes 中的网络原理解析该怎么理解就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-08-25发表,共计3938字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)