Kubernetes内部的网络与物理世界中的网络没有太大区别。有了网络基础知识,你就可以轻松实现容器Pod和服务之间的通信。
从使用交换机、路由器和以太网电缆的物理网络转移到使用软件定义网络(SDN)和虚拟接口的虚拟网络需要一段轻微的学习曲线。当然,原则保持不变,但有不同的规范和最佳实践。Kubernetes有自己的一套规则,如果你处理的是容器和云,这有助于了解Kubernetes网络是如何工作的。
Kubernetes网络模型有一些需要记住的一般规则:
- 每个pod都有自己的IP地址:不需要在Pod之间创建链接,也不需要将容器端口映射到主机端口。
- 不需要NAT:节点上的Pod应该能够与没有NAT的所有节点上的所有Pod通信。
- 代理获得所有访问权限:节点(系统守护进程、Kubelet)上的代理可以与该节点中的所有Pod通信。
- 共享命名空间:Pod中的容器共享网络命名空间(IP和MAC地址),因此它们可以使用环回地址相互通信。
Kubernetes网络解决了什么问题
Kubernetes网络旨在确保Kubernetes中的不同实体类型可以通信。Kubernetes基础设施的布局在设计上有很多分离。命名空间、容器和Pod旨在保持组件彼此不同,因此高度结构化的通信计划非常重要。
容器到容器的网络
容器到容器的网络通过Pod网络命名空间进行。网络命名空间允许你拥有独立的网络接口和路由表,这些接口和路由表与系统的其余部分隔离并独立运行。每个Pod都有自己的网络命名空间,其中的容器共享相同的IP地址和端口。这些容器之间的所有通信都是通过localhost进行的,因为它们都是同一命名空间的一部分。(由图中的绿线表示。)
Pod到Pod的网络
对于Kubernetes,每个节点都有一个指定的用于Pod的CIDR IP范围。这确保每个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到服务的网络
Pod很动态。它们可能需要根据需求扩大或缩小规模。在应用程序崩溃或节点故障的情况下,可以再次创建它们。这些事件会导致Pod的IP地址发生变化,这将给联网带来挑战。
Kubernetes通过使用Service功能来解决此问题,该功能执行以下操作:
- 在前端分配静态虚拟IP地址,以连接与服务关联的任何后端吊舱。
- 负载将寻址到此虚拟IP的所有流量平衡到后端Pod集。
- 跟踪Pod的IP地址,这样即使Pod IP地址更改,客户端也不会有任何问题,因为它们只直接连接到服务本身的静态虚拟IP地址。
集群内负载均衡有两种方式:
- IPTABLES:在这种模式下,kube-proxy监视API服务器中的更改。对于每个新服务,它都会安装iptables规则,这些规则将流量捕获到Service的clusterIP和端口,然后将流量重定向到服务的后端Pod。Pod是随机选择的。此模式可靠,系统开销较低,因为Linux Netfilter处理流量时不需要在用户空间和内核空间之间切换。
- IPV:IPV构建在Netfilter之上,并实现传输层负载均衡。IPVS使用Netfilter钩子函数,使用哈希表作为底层数据结构,并在内核空间中工作。这意味着IPVS模式下的kube代理比iptables模式下的kube代理具有更低的延迟、更高的吞吐量和更好的性能来重定向流量。
上图显示了从Pod 1到Pod 3的包流通过Service到不同节点(以红色标记)。前往虚拟网桥的包必须使用默认路由(eth0),因为网桥上运行的ARP无法理解该服务。之后,包必须通过iptables进行过滤,iptables使用kube代理在节点中定义的规则。因此,该图显示了当前的路径。
Internet到服务的网络
到目前为止,已经讨论了如何在集群内路由流量。然而,Kubernetes网络还有另一面,那就是将应用程序暴露于外部网络。
你可以通过两种不同的方式将应用程序公开给外部网络。
- 出口:当你想要将流量从Kubernetes服务路由到Internet时,请使用此选项。在这种情况下,iptables执行源NAT,因此流量似乎来自节点,而不是Pod。
- 入口:这是从外部世界到服务的传入流量。入口还允许并阻止使用连接规则与服务进行的特定通信。通常,有两种入口解决方案在不同的网络堆栈区域上运行:服务负载均衡器和入口控制器。
发现服务
Kubernetes发现服务有两种方式:
- 环境变量:在Pod运行的节点上运行的kubelet服务负责以{SVCNAME}\u service\u HOST和{SVCNAME}\u service\u PORT的格式为每个活动服务设置环境变量。你必须在客户端Pod出现之前创建服务。否则,这些客户端Pod将不会填充其环境变量。
- DNS:DNS服务实现为Kubernetes服务,映射到一个或多个DNS服务器Pod,这些Pod与任何其他Pod一样进行调度。集群中的Pod配置为使用DNS服务,DNS搜索列表包括Pod自己的命名空间和集群的默认域。集群感知DNS服务器(如CoreDNS)监视Kubernetes API以获取新服务,并为每个服务创建一组DNS记录。如果在整个集群中启用了DNS,则所有Pod都可以根据其DNS名称自动解析服务。Kubernetes DNS服务器是访问ExternalName服务的唯一方式。
发布服务的ServiceTypes
Kubernetes服务提供了一种访问一组Pod的方法,通常通过使用标签选择器来定义。这可能是应用程序试图访问集群中的其他应用程序,也可能允许你将集群中运行的应用程序公开给外部世界。Kubernetes
ServiceTypes允许你指定所需的服务类型。
不同的ServiceTypes包括:
- ClusterIP:这是默认的ServiceType。它使服务只能从集群内访问,并允许集群内的应用程序相互通信。没有外部访问。
- LoadBalancer:此服务类型使用云提供商的负载均衡器对外公开服务。来自外部负载均衡器的流量被定向到后端POD。云提供商决定如何实现负载均衡。
- NodePort:这允许外部通信通过在所有节点上打开特定端口来访问服务。然后,发送到此端口的任何流量都会转发到该服务。
- ExternalName:这种类型的服务使用ExternalName字段的内容,通过返回CNAME记录及其值,将服务映射到DNS名称。未设置任何类型的代理。
网络软件
只要你了解所使用的技术,Kubernetes内部的网络与物理世界中的网络没有太大区别。好好学习,记住网络基础知识,就可以轻松实现容器、Pod和服务之间的通信。