从使用交换机、路由器和以太网电缆的物理网络过渡到使用软件定义网络 (SDN) 和虚拟接口的虚拟网络,需要一个稍微的学习曲线。当然,原理保持不变,但规范和最佳实践有所不同。Kubernetes 有自己的一套规则,如果您正在处理容器和云,那么了解 Kubernetes 网络的工作原理会很有帮助。
Kubernetes 网络模型有一些需要记住的通用规则
- 每个 Pod 都有自己的 IP 地址:应该不需要在 Pod 之间创建链接,也不需要将容器端口映射到主机端口。
- 不需要 NAT:节点上的 Pod 应该能够与所有节点上的所有 Pod 通信,而无需 NAT。
- 代理获得所有访问权限:节点上的代理(系统守护程序、Kubelet)可以与该节点中的所有 Pod 通信。
- 共享命名空间:Pod 内的容器共享一个网络命名空间(IP 和 MAC 地址),因此它们可以使用环回地址相互通信。
Kubernetes 网络解决的问题
Kubernetes 网络旨在确保 Kubernetes 内的不同实体类型可以通信。 Kubernetes 基础设施的布局在设计上具有很大的隔离性。命名空间、容器和 Pod 旨在使组件彼此区分开来,因此高度结构化的通信计划非常重要。

(Nived Velayudhan,CC BY-SA 4.0)
容器到容器的网络
容器到容器的网络通过 Pod 网络命名空间发生。网络命名空间允许您拥有与系统其余部分隔离且独立运行的单独网络接口和路由表。每个 Pod 都有自己的网络命名空间,并且该 Pod 内的容器共享相同的 IP 地址和端口。这些容器之间的所有通信都通过 localhost 发生,因为它们都是同一命名空间的一部分。(在图中用绿线表示。)
Pod 到 Pod 的网络
使用 Kubernetes,每个节点都有一个指定的 Pod IP CIDR 范围。这确保每个 Pod 都收到一个集群中其他 Pod 可以看到的唯一 IP 地址。创建新 Pod 时,IP 地址永远不会重叠。与容器到容器的网络不同,Pod 到 Pod 的通信使用真实的 IP,无论您是将 Pod 部署在同一节点还是集群中的不同节点上。
该图显示,为了使 Pod 相互通信,流量必须在 Pod 网络命名空间和根网络命名空间之间流动。这是通过使用虚拟以太网设备或 veth 对(veth0 到 Pod 命名空间 1,veth1 到图中的 Pod 命名空间 2)连接 Pod 命名空间和根命名空间来实现的。虚拟网络桥接器连接这些虚拟接口,允许流量使用地址解析协议 (ARP) 在它们之间流动。
当数据从 Pod 1 发送到 Pod 2 时,事件流如下:
- Pod 1 流量通过 eth0 流向根网络命名空间的虚拟接口 veth0。
- 然后流量通过 veth0 到虚拟网桥,虚拟网桥连接到 veth1。
- 流量通过虚拟网桥到达 veth1。
- 最后,流量通过 veth1 到达 Pod 2 的 eth0 接口。
Pod 到 Service 的网络
Pod 非常动态。它们可能需要根据需求进行扩容或缩容。它们可能会在应用程序崩溃或节点故障时重新创建。这些事件会导致 Pod 的 IP 地址发生变化,这将使网络成为一项挑战。

(Nived Velayudhan,CC BY-SA 4.0)
Kubernetes 通过使用 Service 功能来解决此问题,该功能执行以下操作:
- 在前端分配一个静态虚拟 IP 地址,以连接与 Service 关联的任何后端 Pod。
- 将寻址到此虚拟 IP 的任何流量负载均衡到后端 Pod 集。
- 跟踪 Pod 的 IP 地址,这样即使 Pod IP 地址发生变化,客户端也不会遇到连接到 Pod 的问题,因为它们仅直接与 Service 本身的静态虚拟 IP 地址连接。
集群内负载均衡以两种方式发生:
- IPTABLES:在这种模式下,kube-proxy 监视 API 服务器中的更改。对于每个新 Service,它都会安装 iptables 规则,这些规则捕获到 Service 的 clusterIP 和端口的流量,然后将流量重定向到 Service 的后端 Pod。Pod 是随机选择的。此模式可靠且系统开销较低,因为 Linux Netfilter 处理流量,而无需在用户空间和内核空间之间切换。
- IPVS:IPVS 构建在 Netfilter 之上,并实现传输层负载均衡。IPVS 使用 Netfilter 挂钩函数,使用哈希表作为底层数据结构,并在内核空间中工作。这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 以更低的延迟、更高的吞吐量和更好的性能重定向流量。
上面的图表显示了从 Pod 1 通过 Service 到不同节点(红色标记)的 Pod 3 的数据包流。传输到虚拟网桥的数据包必须使用默认路由 (eth0),因为在网桥上运行的 ARP 不会理解 Service。稍后,数据包必须由 iptables 过滤,iptables 使用 kube-proxy 在节点中定义的规则。因此,该图显示了路径的实际情况。
互联网到 Service 的网络
到目前为止,我已经讨论了流量如何在集群内路由。但是,Kubernetes 网络还有另一方面,那就是将应用程序暴露给外部网络。

(Nived Velayudhan,CC BY-SA 4.0)
您可以通过两种不同的方式将应用程序暴露给外部网络。
- 出口(Egress):当您要将流量从 Kubernetes Service 路由到互联网时,请使用此方法。在这种情况下,iptables 执行源 NAT,因此流量看起来来自节点而不是 Pod。
- 入口(Ingress):这是来自外部世界到 Service 的传入流量。Ingress 还允许和阻止与 Service 的特定通信,使用连接规则。通常,有两种在不同网络堆栈区域运行的入口解决方案:服务负载均衡器和 Ingress 控制器。
发现 Service
Kubernetes 有两种发现 Service 的方式:
- 环境变量:在 Pod 运行的节点上运行的 kubelet 服务负责为每个活动服务设置环境变量,格式为 {SVCNAME}_SERVICE_HOST 和 {SVCNAME}_SERVICE_PORT。您必须在客户端 Pod 出现之前创建 Service。否则,这些客户端 Pod 将不会填充其环境变量。
- DNS:DNS 服务作为 Kubernetes 服务实现,该服务映射到一个或多个 DNS 服务器 Pod,这些 Pod 与任何其他 Pod 一样被调度。集群中的 Pod 配置为使用 DNS 服务,其 DNS 搜索列表包括 Pod 自己的命名空间和集群的默认域。集群感知 DNS 服务器(例如 CoreDNS)监视 Kubernetes API 以查找新 Service,并为每个 Service 创建一组 DNS 记录。如果在整个集群中启用了 DNS,则所有 Pod 都可以通过其 DNS 名称自动解析 Service。Kubernetes DNS 服务器是访问 ExternalName Service 的唯一方法。
ServiceTypes 用于发布 Service
Kubernetes Service 为您提供了一种访问 Pod 组的方式,通常通过使用标签选择器来定义。这可能是尝试访问集群内其他应用程序的应用程序,也可能是允许您将集群中运行的应用程序暴露给外部世界。Kubernetes ServiceTypes 使您能够指定您想要的 Service 类型。

(Ahmet Alp Balkan,CC BY-SA 4.0)
不同的 ServiceTypes 是:
- ClusterIP:这是默认的 ServiceType。它使 Service 仅可从集群内部访问,并允许集群内的应用程序相互通信。没有外部访问。
- LoadBalancer:此 ServiceType 使用云服务提供商的负载均衡器在外部暴露 Service。来自外部负载均衡器的流量被定向到后端 Pod。云服务提供商决定如何进行负载均衡。
- NodePort:这允许外部流量通过打开所有节点上的特定端口来访问 Service。发送到此端口的任何流量都将转发到 Service。
- ExternalName:此类型的 Service 通过使用 externalName 字段的内容并返回带有其值的 CNAME 记录,将 Service 映射到 DNS 名称。不设置任何类型的代理。
网络软件
Kubernetes 中的网络与物理世界中的网络并没有太大区别,只要您了解所使用的技术即可。努力学习,记住网络基础知识,您就可以轻松地在容器、Pod 和服务之间启用通信。
2 条评论