Kubernetes — 网络流量模型

Posted 范桂飓

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Kubernetes — 网络流量模型相关的知识,希望对你有一定的参考价值。

目录

Kubernetes Network 中的 IP 地址类型

Kubernetes 网络中涉及以下几种类型的 IP 地址:

  1. Node IP:宿主机 IP 地址。

  2. Pod IP:Pod 是 Kubernetes 的最小部署单元,Pod 下可以包含若干个 Containers,但是 Container 没有独立的 IP 地址,它们共享 Pod 的 IP 地址和 Ports 区间。

  3. Cluster IP:这里所述 Cluster 并非 Kubernetes Cluster,而是 Kubernetes Service 的 IP 地址。外部网络是无法访问该地址的,只有 Kubernetes Cluster 内部才能访问。因为 Cluster IP 是一个虚拟的 IP 地址,即:没有网络设备为这个 IP 地址负责。在 Kubernetes 内部使用了 IPtables 规则来重定向到其本地端口,再均衡到后端的 Pods;

  4. Public IP:因为 Cluster IP 能在 Kubernetes Cluster Internal 访问,属于应用程序内部的层级。如果希望将这个 Service 为 Kubernetes Cluster External 的客户端提供访问,就需要为这个 Service 提供一个 Public IP。

Kubernetes 的网络流量模型

同 Pod 内部的 Containers 间的通信(Container 模式)

Pod 内部的 Containers 通过 localhost 进行通信,它们使用了同一个 Network Namespace。对 Container 而言,hostname 就是 Pod 的名称。

Pod 内部的 Containers 共享同一个 IP 地址和端口区间,所以要为每个可以建立连接的 Container 分配不同的 Port 号。也就是说,Pod 中的 “应用” 需要自己协调端口号的分配和使用。

  • 例如:创建一个 Pod ,包含两个 Containers。
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

可以看到同一个 Pod 下属的两个 Containers 共享了 IP 地址。

在这里插入图片描述
在这里插入图片描述

可以看见,同一个 Pod 下属的两个 Containers 不能占有同一个 Port 号,因为 Port 区间也是共享的。

所以,我们可以将 Pod 理解为一个小型的 “操作系统沙盒”,两个进程可以使用同一个操作系统 IP 地址,自然也就不可以使用同一个 Port 号了。

实现原理:同一个 Pod 内的 Containers 处于同一个 Network Namespace,因此使用了相同的 IP 地址和 Port 区间。该 Namespace 是由一个名为 Pause Container 实现的,每当一个 Pod 被创建,首先会创建一个 Pause Container。

在这里插入图片描述

后续所有新的普通 Containers 都通过过共享 Pause Container 的网络栈,实现与外部 Pod 进行通信。因此,对于同 Pod 下属的 Containers 而言,它们看到的网络视图是一样的。上述我们在 Container 中看的 IP 地址,实际就是 Pause Container 的 IP 地址,通过控制 Pause Container 的网络协议栈就可以影响所有同属 Pod 下的 Container 的网络协议栈了。

这种新创建的容器和已经存在的一个容器(Pause)共享一个 Network Namespace(而不是和宿主机共享)的模式,就是常说的 Container 模式。

在这里插入图片描述

同 Node 内部的 Pods 间的通信(Host Virtual Network 模式)

每个 Node 上的每个 Pod 都有自己专属的 Network Namespace,由此实现 Container 模型网络的隔离。而两个 Pod 之间,即:两个 Network Namespace 之间希望进行通信的话,就需要使用到 Linux 操作系统的网络虚拟化技术 —— Veth Pair(虚拟网线)了。

但是,如果有多个 Pod 都需要两两建立 Veth Pair 的话,扩展性就会非常的差,假如:有 N 个 Pod,就需要创建 n(n-1)/2 个 Veth Pair。可见,除了 Veth Pair(虚拟网线)之外,我们还需要一个二层的 “集线” 设备 —— Linux Bridge(虚拟交换机)。

在这里插入图片描述

举个例子:创建位于同一个 Node 下属的 Pod1 和 Pod2,IP 地址分别为:10.244.1.16、10.244.1.18。

在这里插入图片描述

查看 Node 下的 Network Namespace:

在这里插入图片描述
在这里插入图片描述

分别查询两个 Network Namespace 下的 Network Interfaces:

在这里插入图片描述
可见,Pod1、Pod2 内部的 Veth Pair 的一端分别是 3: eth0@if73: eth0@if9;另一端则位于 default Network Namespace,分别为 7: veth3b416eb2@if39: veth88cfc816@if3。注意:interface ID 和 ifID 刚刚好是两端对称的,以此来进行辨识。当然了,Bridge 也同样存在于 default Network Namespace。

在这里插入图片描述

这种借助于 Linux 操作系统原生的网络虚拟化技术实现的两个本地 Pods 之间的网络通信方式,称为 Host Virtual Network 模式。

跨 Nodes 间的 Pods 间的通信(SDN 模式)

总的来说,跨主机通信无非两种方式:

  • Overlay 隧道互通:Nodes 之间通过 Over the Physical 网络互通,e.g. OvS、Flannel 和 Weave。
  • Underlay 直接互通:Nodes 之间通过物理网络互通,e.g. Calico 的 Direct 模式、macvlan。

从网络角度对 Flannel 和 Calico 进行简单对比。可见,对性能敏感、策略需求较高时偏向于 Calico 方案。否则,采用 Flannel 会是更好的选择;

在这里插入图片描述

Calico

Calico 的组件包含:

  • Felix(Calico agent):运行在每个 Node 上,为容器设置网络信息,例如:IP 地址、路由规则,IPtables 规则等。
  • BIRD(BGP Client):运行在每个 Node 上,监听由 Felix 注入的路由信息,然后通过 BGP 协议广播告诉其他 Nodes,从而实现网络互通。
  • BGP Route Reflector:BGP Peer 建立的方式多样,可以在 Node 之间两两建立 BPGP Peer(默认模式),和传统 iBGP Peer 问题类似,这会带来 n*(n-1)/2 的邻居量。因此也可以自建 RR 反射器,Node 和 RR 建立 Peer。当然 Node 也可以和 TOR 建立 Peer。具体选择哪种 Peer 方式没有固定标准,要适配总体网络规划,只要最终保证容器网络可正确发布到物理网络即可;
  • Calicoctl:命令行管理工具。

Calico 支持 3 种路由模式:

  1. Direct 路由转发,报文不做封装;
  2. IP-in-IP(Default)封装;
  3. VXLAN 封装;

这里主要介绍 Direct 模式,使用 BGP 路由协议宣告容器网段,使得全网所有的 Nodes 和网络设备都有到彼此的路由的信息,然后直接通过 Underlay 转发。

数据通信的流程为:数据包先从 Veth Pair 的一端发出,到达 Node 上的以 Cali 为前缀的虚拟网卡上,也就到达了 Host 的内核网络协议栈。然后查询路由表转发;因为本地节点通过 Bird 和 RR 建立 BGP 邻居关系,会将本地的容器地址发送到 RR 从而反射到网络中的其它 Nodes 上,同样,其它 Nodes 的网络地址也会传送到本地,然后由 Felix 进程进行管理并下发到路由表中,报文匹配路由规则后正常进行转发即可(实际还有复杂的 iptables 规则,这里不做展开)。

在这里插入图片描述

Service 的 Cluster IP 和外部网络间的通信

Service 之于集群内部 Pods 之间的通信

Pod 间可以直接通过 IP 地址通信,但前提是 Pod 知道对方的 IP。在 Kubernetes Cluster 中,Pod 可能会频繁地销毁和创建,也就是说 Pod 的 IP 不是固定的。为了解决这个问题,Kubernetes Service 作为访问 Pod 的上层抽象。无论后端的 Pod 如何变化,Service 都作为稳定的前端对外提供服务。同时,Service 还提供了高可用和负载均衡功能,负责将请求转发给正确的 Pod。

Service 之于集群外部与 Pod 的通信

无论是 Pod IP 还是 Service 的 Cluster IP,它们都是只能在 Kubernetes Cluster 内部可见的私有 IP 地址。Kubernetes 提供了两种方式可以让外部网络访问 Service 的 Cluster IP,继而与 Pod 进行通信:

  1. NodePort:Service 通过 Node 的静态端口对外提供服务,外部网络可以通过 NodeIP:NodePort 访问 Service,根据不同的 NodePort 可以访问不同的 Service。

  2. LoadBalancer:Service 利用自建的负载均衡器(反向代理)将流量导向 Service,例如:nginx、OpenStack Octavia、Cloud Provider(GCP、AWS、 Azure)等。

以上是关于Kubernetes — 网络流量模型的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes 系列CNI 与网络流量模型

线上k8s集群利用服务拓扑流量路由策略来设置定向流量?

Istio中的服务和流量的抽象模型

干货分享体验kubernetes网络插件Contiv

精品k8s(kubernetes)的网络策略详networkpolicy实例精讲

代理 kubernetes 通过代理 (CNTLM) 的传出流量