K8S网络模型
K8S网络通信细节
一、网络必要基础知识
IP地址标准计算法
计算IP
192.168.20.125/27
IP/子网掩码长度
192.168.20.125
第一步 拆解IP地址
11000000 10101000 00010100 01111101
第二步 根据子网掩码长度 将拆解的ip分段
11000000 10101000 00010100 011/11101
网络位 /主机位
第三步 直接计算IP地址
网段地址:网络位不变 主机位全为0 11000000 10101000 00010100 011/00000 192.168.20.96
广播地址:网络位不变 主机位全为1 11000000 10101000 00010100 011/11111 192.168.20.127
有效地址范围:192.168.20.97~192.168.20.126
子网掩码:网络位全为1 主机位全为0
11111111 11111111 11111111 111/00000 ---> 255.255.255.224
表示方法有两种
1) 192.168.20.125/27
2) 192.168.20.125 255.255.255.224
二、K8S网络通信分类
集群内
- Pod中container和container之间通信(Container<->Container)
在同一个pod内部的不同容器所处在同一个Network Namespace,所以pod内部的container间的通信通过localhost即可完成。
- Pod和Pod之间通信(Pod<->Pod)
pod和pod之间的通信,一般来说所有的pod在K8S系统网络规划的时候让其处在同一个CIDR下,跨主机的pod通信需要依赖CNI来实现,CNI一般有两大类基于隧道和基于路由,
基于隧道的代表Flannel,基于路由的代表Calico。
- Pod和Service之间通信(Pod<->Service)
Pod的Ip通过veth生成的虚拟网络设备来作为网络接口,而ServiceIp是Ipvs或者Iptables规则虚拟出来的Ip,没有网络接口。
集群外
- 外部应用和服务之间通信
- 同一个Pod之间的通信
- 不同Pod中容器间的通信
三、分层网络模型Overlay和Underlay
为什么K8S要设计Underlay和Overlay两层网络结构?
1. 可分配ip数目依赖于underlay网络的网络规划,有可能可用ip数目很少;
2. 跨网段通讯需要nat或其它映射技术的支持;
3. underlay网络ip的变化有可能会导致pod ip的变化;
基于Flannel作为K8S插件解释
Calico和Flannel对比
| 模式 | Overlay | 主要基于隧道 | 主要基于路由 | 性能损失 | 方式 |
|---|---|---|---|---|---|
| Calico | No | No | Yes | 小 | IPIP(隧道)、BGP、RR |
| Flannel | Yes | Yes | No | 大 | UDP、VXLAN、Host-GW |
Flannel的模式(基于隧道的网络实现):UDP、VXLAN、Host-GW三种模式,VXLAN是比较推荐的模式。
| 模式 | 应用场景 | 实现网络层 |
|---|---|---|
| UDP | 一般用于不支持VXLAN的内核服务器 | 二层网络支持(同广播域) |
| VXLAN | 推荐一般性场景 | 三层网络支持 |
| Host-GW | 网络性能要求高 | 二层网络支持(同广播域) |

如图中所示:
(1)给Node1以100.12.24.1/24作为其podIp的地址池、Node2以100.12.25.1/24、Node3以100.12.26.1/24,每台服务器可以运行pod为254个;
(2)192.168.0.0/24处于同一个二层网络或者三层空间中,属于Underlay网络,该网络的服务器可以通过二层网络直接通信;
(3)Flannel的VXLAN为一种隧道协议帮助跨主机间的Overlay网络通信,比如当Pod 100.12.24.2需要和100.12.26.3通信时,Flannel负责将容器中的网络报文封装成宿主机Node的报文,通过宿主机之间的隧道完成通信。
(4)VXLAN才有L2 over L4的封装模式,将二层报文用三层协议进行封装,可以实现二层网络在三次网络内扩展,形成一个大二层网络。
另外,在分布式pod中,K8S上的所有pod默认会从同一平面网络得到全局一个唯一IP地址和一个虚拟网络接口,无论是否都处于一个namespace,各个pod之间都可使用各自的IP地址直接进行通信。 为了满足分布式pod必须位于同一个平面网络内。对于一个K8S集群来说,容器数量是很多的,为了避免各个容器间网络的冲突,一个常见的解决方案是给每个宿主机分配同一个网络中的不同子网,再让宿主机根据自有子网向其内容器分配ip,如下:
K8S集群分配子网网段给Node --> Node根据划分的网段分配Ip给当前宿主机的Pod
因此整个K8S就会存在三种IP:
(1)node ip: 是物理机IP(或虚拟机ip)。每个service都会在node节点上开通过一个端口,外部可以通过http://nodeip:nodeport即可访问service里的pod提供的服务。
(2)cluster ip:是service的IP地址,此为虚拟ip地址,外部网络无法ping通,只有k8s集群内部访问使用;cluster ip仅仅作用于k8s service这个对象,并由k8s管理和分配IP地址;cluster ip无法被ping,他没有一个“实体网络对象”。单独的cluster ip不具备通信的基础,并且他们属于k8s集群这样一个封闭的空间;在不同service的pod节点在集群间相互访问可以通过cluster ip。
(3)pod ip:是每个pod的IP地址,一般由网络插件提供配置(flannel),通常是一个虚拟的二层网络。同service下的pod可以直接根据podip相互通信;不同service下的pod在集群间pod通信要借助于cluster ip;
四、集群地址分配
查看集群可使用IP范围、端口范围和集群地址池
kubectl cluster-info dump | egrep "service-cluster-ip-range|service-node-port-range|cluster-pool-ipv4-cidr"
得到:
"--service-cluster-ip-range=10.233.0.0/18",
"--service-node-port-range=30000-32767",
"--service-cluster-ip-range=10.233.0.0/18",
"--service-node-port-range=30000-32767",
"--service-cluster-ip-range=10.233.0.0/18",
"--service-node-port-range=30000-32767",
"--cluster-cidr=10.233.64.0/18",
"--service-cluster-ip-range=10.233.0.0/18",
"--cluster-cidr=10.233.64.0/18",
"--service-cluster-ip-range=10.233.0.0/18",
"--cluster-cidr=10.233.64.0/18",
"--service-cluster-ip-range=10.233.0.0/18",
level=info msg=" --cluster-pool-ipv4-cidr='10.0.0.0/8'" subsys=cilium-operator-generic
- service-cluster-ip-range,表示集群Service可用IP地址数量的计算方式:10.233.0.0/18掩码18位【这个段我们理解为完整Overlay网络】,那么掩码就是 255.255.192.0( 11111111 11111111 11000000 00000000),第三段的范围就是 0 ~ 2^6-1,那么范围就是10.233.0.1 ~ 10.233.63.255,总共可用IP地址为2^14-2(16382)个地址。
- service-node-port-range,表示服务端口范围。
- cluster-cidr,表示为Pod分配的地址范围,然后节点从10.233.64.0/24、10.233.65.0/24、10.233.66.0/24 … 依次分配。
查看各个节点的IP地址池范围
通过此命令:kubectl get nodes -o yaml | egrep "io.cilium.network|kubernetes.io/hostname"
得到我们有三个Master和三个Node节点,他们各自的节点上pod可以分配如下所示:
io.cilium.network.ipv4-cilium-host: 10.233.64.15
io.cilium.network.ipv4-health-ip: 10.233.64.230
io.cilium.network.ipv4-pod-cidr: 10.233.64.0/24
kubernetes.io/hostname: cd.ops.k8s-master-01
io.cilium.network.ipv4-cilium-host: 10.233.65.217
io.cilium.network.ipv4-health-ip: 10.233.65.119
io.cilium.network.ipv4-pod-cidr: 10.233.65.0/24
kubernetes.io/hostname: cd.ops.k8s-master-02
io.cilium.network.ipv4-cilium-host: 10.233.66.34
io.cilium.network.ipv4-health-ip: 10.233.66.91
io.cilium.network.ipv4-pod-cidr: 10.233.66.0/24
kubernetes.io/hostname: cd.ops.k8s-master-03
io.cilium.network.ipv4-cilium-host: 10.233.69.246
io.cilium.network.ipv4-health-ip: 10.233.69.171
io.cilium.network.ipv4-pod-cidr: 10.233.69.0/24
kubernetes.io/hostname: cd.ops.server.k8s-node-01
io.cilium.network.ipv4-cilium-host: 10.233.68.214
io.cilium.network.ipv4-health-ip: 10.233.68.91
io.cilium.network.ipv4-pod-cidr: 10.233.68.0/24
kubernetes.io/hostname: cd.ops.server.k8s-node-02
io.cilium.network.ipv4-cilium-host: 10.233.67.133
io.cilium.network.ipv4-health-ip: 10.233.67.235
io.cilium.network.ipv4-pod-cidr: 10.233.67.0/24
kubernetes.io/hostname: cd.ops.server.k8s-node-03
我们用cd.ops.server.k8s-node-01这个节点举例10.233.69.0/24,那么在这个节点上的pod可用地址从10.233.69.2-10.233.69.255,共计 【254 】个可用地址,也就是在此节点运行的pod上限就是254个,其他节点一样。 根据上面的cluster-cidr=10.233.64.0/18,可以知道所有POD的Ip范围是从10.233.64.0-10.233.127.255,也就意味着集群的Node只能从64-127,共计能够容纳64个节点。