k8s 容器网络接口

  |  

全部的 K8S学习笔记总目录,请点击查看。

k8s中的网络也是一个比较复杂的部分,这里我们看一下k8s中的网络,以及网络插件。

Kubernetes集群的网络实现

容器网络回顾

docker-bridge

Docker 创建一个容器的时候,会执行如下操作:

  • 创建一对虚拟接口/网卡,也就是veth pair;
  • veth pair的一端桥接 到默认的 docker0 或指定网桥上,并具有一个唯一的名字,如 vethxxxxxx;
  • veth pair的另一端放到新启动的容器内部,并修改名字作为 eth0,这个网卡/接口只在容器的命名空间可见;
  • 从网桥可用地址段中(也就是与该bridge对应的network)获取一个空闲地址分配给容器的 eth0
  • 配置容器的默认路由

Pod IP唯一性保障

Kubernetes网络模型的核心要求之一是每个Pod应该获得自己的IP地址,如何实现?

1
2
3
4
5
6
7
8
9
10
11
$ cat /etc/kubernetes/manifests/kube-controller-manager.yaml
...
- --cluster-cidr=10.244.0.0/16
...

# 为每个节点从cidr中分配一个网段,供该节点分配pod ip
$ kubectl describe nodes k8s-node1
...
PodCIDR: 10.244.1.0/24
PodCIDRs: 10.244.1.0/24
...

Pod配置网络流程

CNI:容器网络接口(Container Network Interface), 主要能力是对接 Kubelet 完成容器网卡的创建,申请和设置 ip 地址,路由设置,网关设置,实现kubernetes集群的Pod网络通信及管理。

CNI的具体实现有很多种:

  • 通用类型:flannel、calico、Cilium 等,部署使用简单
  • 其他:根据具体的网络环境及网络需求选择,比如
    • 公有云机器,可以选择厂商与网络插件的定制Backend,如AWS、阿里、腾讯针对flannel均有自己的插件,也有AWS ECS CNI
    • 私有云厂商,比如Vmware NSX-T等
    • 网络性能等,MacVlan

k8s本身不提供cni的实现,因此安装完k8s集群后,需要单独安装网络组件

kubelet-cni-process

  1. pod调度到k8s的节点k8s-node1中
  2. k8s-node1的kubelet调用containerd创建pod
  3. containerd创建pod沙箱和pod所用的网络空间
  4. containerd查找配置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $ cat /etc/containerd/config.toml

    ......
    [plugins."io.containerd.grpc.v1.cri".cni]
    bin_dir = "/opt/cni/bin"
    conf_dir = "/etc/cni/net.d"
    conf_template = ""
    ip_pref = ""
    max_conf_num = 1
    ......
  5. 查看目录/etc/cni/net.d/,发现10-flannel.conflist,使用flannel作为网络插件
    1
    2
    $ sudo ls /etc/cni/net.d/
    10-flannel.conflist
  6. CNI开始为pod配置网络
    • flannel启动时候,写入了本机配置文件/run/flannel/subnet.env
      1
      2
      3
      4
      5
      $ cat /run/flannel/subnet.env
      FLANNEL_NETWORK=10.244.0.0/16
      FLANNEL_SUBNET=10.244.0.1/24
      FLANNEL_MTU=1450
      FLANNEL_IPMASQ=true
    • flannel将本机网段等信息传递给bridge插件
      • bridge插件创建cni0网桥
      • 创建veth pair,分别接入到pod网络空间和cni0网桥
      • 调用 本地IPAM CNI 插件,设置pod ip地址并记录已分配地址
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        $ ip a s cni0
        15: cni0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default qlen 1000
        link/ether 6a:93:41:87:41:22 brd ff:ff:ff:ff:ff:ff
        inet 10.244.0.1/24 brd 10.244.0.255 scope global cni0
        valid_lft forever preferred_lft forever
        inet6 fe80::6893:41ff:fe87:4122/64 scope link
        valid_lft forever preferred_lft forever
        $ yum install bridge-utils -y
        ......
        $ brctl show
        bridge name bridge id STP enabled interfaces
        cni0 8000.6a9341874122 no veth8a587a83
        docker0 8000.024289168674 no

    • IPAM CNI 插件从子网返回容器的IP地址,并将分配的IP本地存储在主机上 /var/lib/cni/networks/cbr0/
  7. containerd创建pause容器,并配置到新建的网络空间
  8. kubelet调用containerd开始拉取业务镜像
  9. 启动业务容器并设置namespace和cgroup

上图可以清晰的看到如下重点:

  • kubelet、containerd、cni的工作边界和职责
  • cni是被containerd进行调用,cni的实现是可以根据不同的网络环境配置的
  • 配置Pod网络的过程,实际上是一个网络工具的链式调用

更细致的CNI调用过程如下图:

cni-network

  • Flannel CNI
    • 使用Flannel作为网络提供程序时,Containered CRI插件使用CNI配置文件/etc/cni/net.d/10-flannel.conflist调用Flannel CNI插件
    • Flannel CNI插件与Flanneld结合使用。当Flanneld启动时,它会从apiserver中获取podCIDR和其他与网络相关的详细信息,并将它们存储在文件/run/flannel/subnet.env
    • Flannel CNI插件使用/run/flannel/subnet.env中的信息来配置和调用网桥CNI插件。
  • Bridge CNI
    • 首次调用Bridge CNI插件时,它将使用配置文件中指定的"name": "cni0"创建一个Linux网桥。然后,它为每个Pod创建veth对,该对的一端在容器的网络名称空间中,另一端连接到主机网络上的linux桥。使用Bridge CNI插件,主机上的所有容器都连接到主机网络上的linux网桥。
    • 配置完veth对后,Bridge插件将调用主机本地IPAM CNI插件
  • host-local IPAM CNI
    • Host-local IPAM(IP地址管理)插件从子网返回容器的IP地址,并将分配的IP本地存储在主机上

经过Pod网络配置后,本机的Pod应该是这样的:

pod-local

kube-flannel的作用

从Pod的启动进程,看flannel的Pod:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
$ kubectl -n kube-flannel get po -owide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kube-flannel-ds-6tx4f 1/1 Running 0 87d 192.168.100.1 k8s-master <none> <none>
kube-flannel-ds-7p2rb 1/1 Running 0 87d 192.168.100.2 k8s-node1 <none> <none>
kube-flannel-ds-rx54g 1/1 Running 0 87d 192.168.100.3 k8s-node2 <none> <none>

$ kubectl -n kube-flannel get pod kube-flannel-ds-gdvpx -oyaml

......
containers:
- args:
- --ip-masq
- --kube-subnet-mgr
- --iface=ens192
command:
- /opt/bin/flanneld
......
initContainers:
- args:
- -f
- /flannel
- /opt/cni/bin/flannel
command:
- cp
image: docker.io/flannel/flannel-cni-plugin:v1.2.0
imagePullPolicy: IfNotPresent
name: install-cni-plugin
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /opt/cni/bin
name: cni-plugin
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-db2cl
readOnly: true
- args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
command:
- cp
image: docker.io/flannel/flannel:v0.22.2
imagePullPolicy: IfNotPresent
name: install-cni
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /etc/cni/net.d
name: cni
- mountPath: /etc/kube-flannel/
name: flannel-cfg
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-db2cl
readOnly: true
......
volumes:
- hostPath:
path: /run/flannel
type: ""
name: run
- hostPath:
path: /opt/cni/bin
type: ""
name: cni-plugin
- hostPath:
path: /etc/cni/net.d
type: ""
name: cni
......

# 从配置文中可以知道,flannel的Pod做了如下事情:
# 1. 执行命令 /opt/bin/flanneld --ip-masq --kube-subnet-mgr --iface=eth0
# 2. 第一个 initContainer 执行命令 cp -f /flannel /opt/cni/bin/flannel
# 3. 第二个 initContainer 执行命令 cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/10-flannel.conflist

从进程可以得知:

  1. 启动flanneld进程,功能未知
  2. 拷贝flannel的网络插件到宿主机中,为containerd调用
  3. 考虑flannel的配置文件,当成宿主机的CNI配置,告知containerd使用flannel

跨主机Pod通信

跨主机间的通信流程:

pods-network

flannel的网络有多种后端实现:

1.udp
2. vxlan
3. host-gw
4. …

不特殊指定的话,默认会使用vxlan技术作为Backend,可以通过如下命令查看:

1
2
3
4
5
6
7
8
$ kubectl -n kube-flannel exec -it kube-flannel-ds-6tx4f -- cat /etc/kube-flannel/net-conf.json
Defaulted container "kube-flannel" out of: kube-flannel, install-cni-plugin (init), install-cni (init)
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}

使用vxlan作为后端实现时,flanneld进程的作用:

  • 启动flannel.1作为VTEP设备,用来封包、解包,实现跨主机通信
  • 监听宿主机的Pod CIDR,维护本机路由表

vxlan介绍及点对点通信的实现

VXLAN 全称是虚拟可扩展的局域网( Virtual eXtensible Local Area Network),它是一种 overlay 技术,通过三层的网络来搭建虚拟的二层网络。

vxlan

它创建在原来的 IP 网络(三层)上,只要是三层可达(能够通过 IP 互相通信)的网络就能部署 vxlan。在每个端点上都有一个 vtep 负责 vxlan 协议报文的封包和解包,也就是在虚拟报文上封装 vtep 通信的报文头部。物理网络上可以创建多个 vxlan 网络,这些 vxlan 网络可以认为是一个隧道,不同节点的虚拟机能够通过隧道直连。每个 vxlan 网络由唯一的 VNI 标识,不同的 vxlan 可以不相互影响。

  • VTEP(VXLAN Tunnel Endpoints):vxlan 网络的边缘设备,用来进行 vxlan 报文的处理(封包和解包)。vtep 可以是网络设备(比如交换机),也可以是一台机器(比如虚拟化集群中的宿主机)
  • VNI(VXLAN Network Identifier):VNI 是每个 vxlan 的标识,一共有 2^24 = 16,777,216,一般每个 VNI 对应一个租户,也就是说使用 vxlan 搭建的公有云可以理论上可以支撑千万级别的租户

vxlan点对点通信的实现

在k8s选择两台机器,利用vxlan的点对点能力,实现虚拟二层网络的通信

vxlan-p2p

配置vxlan网络

192.168.100.1节点:

1
2
3
4
5
6
7
8
# 创建vTEP设备,对端指向192.168.100.2节点,指定VNI及underlay网络使用的网卡
$ sudo ip link add vxlan20 type vxlan id 20 remote 192.168.100.2 dstport 4789 dev ens224
# 查看设备信息
$ sudo ip -d link show vxlan20
# 启动设备
$ sudo ip link set vxlan20 up
# 设置ip地址
$ sudo ip addr add 172.16.1.1/24 dev vxlan20

192.168.100.2节点:

1
2
3
4
5
6
# 创建VTEP设备,对端指向192.168.100.1节点,指定VNI及underlay网络使用的网卡
$ sudo ip link add vxlan20 type vxlan id 20 remote 192.168.100.1 dstport 4789 dev ens224
# 启动设备
$ sudo ip link set vxlan20 up
# 设置ip地址
$ sudo ip addr add 172.16.2.2/24 dev vxlan20

测试点对点通信

192.168.100.1节点:

1
2
3
4
5
$ ping -c 6 172.16.2.2
PING 172.16.2.2 (172.16.2.2) 56(84) 比特的数据。
^C
--- 172.16.2.2 ping 统计 ---
已发送 6 个包, 已接收 0 个包, 100% packet loss, time 5105ms

配置路由

192.168.100.1节点:

1
2
# 走vtep封包解包
$ ip route add 172.16.2.0/24 dev vxlan20

192.168.100.2机器上:

1
$ ip route add 172.16.1.0/24 dev vxlan20

再次测试点对点通信

192.168.100.1节点,再次ping:

1
$ ping 172.16.2.2

等似模型

vxlan-p2p-overlay

这里的隧道是一个逻辑上的概念,在 vxlan 模型中并没有具体的物理实体相对应。隧道可以看做是一种虚拟通道,vxlan 通信双方认为自己是在直接通信,并不知道底层网络的存在。从整体来说,每个 vxlan 网络像是为通信的虚拟机搭建了一个单独的通信通道,也就是隧道。

整个vxlan实现的过程就是机器的报文通过 vtep 添加上 vxlan 以及外部的报文层,然后发送出去,对方 vtep 收到之后拆除 vxlan 头部然后根据 VNI 把原始报文发送到目的虚拟机。

清除配置

两台机器上都进行清除配置:

1
$ sudo ip link del vxlan20

跨主机Pod通信

接下来看看k8s中跨主机Pod通信的流量详细过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 查看集群中的Pod,查找两个不同节点的Pod,这里选取了myblog和testpod
$ kubectl -n test get po -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
myblog-84985b5b66-smpwb 1/1 Running 0 76d 10.244.1.5 k8s-node1 <none> <none>
mysql-7f97cb6cc9-vzxpd 1/1 Running 0 76d 192.168.100.2 k8s-node1 <none> <none>
testpod-865855cfc5-m2f99 1/1 Running 0 63d 10.244.2.13 k8s-node2 <none> <none>

$ kubectl -n test exec myblog-84985b5b66-smpwb -- ping 10.244.2.13 -c 6
PING 10.244.2.13 (10.244.2.13) 56(84) bytes of data.
64 bytes from 10.244.2.13: icmp_seq=1 ttl=62 time=1.05 ms
64 bytes from 10.244.2.13: icmp_seq=2 ttl=62 time=1.04 ms
64 bytes from 10.244.2.13: icmp_seq=3 ttl=62 time=0.856 ms
64 bytes from 10.244.2.13: icmp_seq=4 ttl=62 time=1.14 ms
64 bytes from 10.244.2.13: icmp_seq=5 ttl=62 time=1.03 ms
64 bytes from 10.244.2.13: icmp_seq=6 ttl=62 time=0.974 ms

--- 10.244.2.13 ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5005ms
rtt min/avg/max/mdev = 0.856/1.014/1.143/0.086 ms

# 查看路由
$ kubectl -n test exec myblog-84985b5b66-smpwb -- route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.244.1.1 0.0.0.0 UG 0 0 0 eth0
10.244.0.0 10.244.1.1 255.255.0.0 UG 0 0 0 eth0
10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0

# 查看k8s-master 的veth pair 和网桥
$ brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.6a9341874122 no veth8a587a83
vethe7a6a0e0
docker0 8000.024289168674 no

# 流量到了cni0后,查看master节点的route
$ ip r s
default via 10.209.0.200 dev ens192 proto dhcp src 10.209.0.13 metric 100
default via 192.168.100.254 dev ens224 proto static metric 101
10.209.0.0/21 dev ens192 proto kernel scope link src 10.209.0.13 metric 100
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink
10.244.2.0/24 via 10.244.2.0 dev flannel.1 onlink
172.7.21.0/24 dev docker0 proto kernel scope link src 172.7.21.1 linkdown
192.168.100.0/24 dev ens224 proto kernel scope link src 192.168.100.1 metric 101

# 流量转发到了flannel.1网卡,查看该网卡,其实是vtep设备
$ ip -d link show flannel.1
$ ip -d link show flannel.1
6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/ether 0e:af:83:0c:88:29 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 65535
vxlan id 1 local 10.209.0.13 dev ens192 srcport 0 0 dstport 8472 nolearning ttl auto ageing 300 udpcsum noudp6zerocsumtx noudp6zerocsumrx addrgenmode eui64 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 tso_max_size 65536 tso_max_segs 65535 gro_max_size 65536

# 该转发到哪里,通过etcd查询数据,然后本地缓存,流量不用走多播发送
$ bridge fdb show dev flannel.1
f6:62:9f:90:cf:fe dst 10.209.0.15 self permanent
66:1a:39:32:d5:13 dst 10.209.0.11 self permanent

查看k8s-node1的路由

1
2
3
4
5
6
7
8
9
10
11
# 对端的vtep设备接收到请求后做解包,取出源payload内容
$ route -n
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.21.64.190 0.0.0.0 UG 0 0 0 eth0
10.244.0.0 10.244.0.0 255.255.255.0 UG 0 0 0 flannel.1
10.244.1.0 0.0.0.0 255.255.255.0 U 0 0 0 cni0
10.244.2.0 10.244.2.0 255.255.255.0 UG 0 0 0 flannel.1
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0

#根据路由规则转发到cni0网桥,然后由网桥转到具体的Pod中

实际的请求图:

flannel-actual

kube-flannel中flanneld的作用

现在我们可以说一下前面未知的flanneld进程的作用了。

从上面的分析可以看到,flannel的Pod中的flanneld进程的作用有如下几点,保证Pod网络的通信(vxlan模式):

  • 启动flannel.1作为VTEP设备,用来封包、解包,实现跨主机通信
  • 监听宿主机的Pod CIDR,维护本机路由表
  • 通过etcd查询数据,然后本地缓存,流量不用走多播发送

利用host-gw模式提升集群网络性能

vxlan模式适用于三层可达的网络环境,对集群的网络要求很宽松,但是同时由于会通过VTEP设备进行额外封包和解包,因此给性能带来了额外的开销。

网络插件的目的其实就是将本机的cni0网桥的流量送到目的主机的cni0网桥。实际上有很多集群是部署在同一二层网络环境下的,可以直接利用二层的主机当作流量转发的网关。这样的话,可以不用进行封包解包,直接通过路由表去转发流量。

flannel-host-gw

为什么三层可达的网络不直接利用网关转发流量?

这是因为内核当中的路由规则,网关必须在跟主机当中至少一个 IP 处于同一网段。
由于k8s集群内部各节点均需要实现Pod互通,因此,也就意味着host-gw模式需要整个集群节点都在同一二层网络内。

首先修改flannel的网络后端为host-gw

1
2
3
4
5
6
7
8
9
10
11
$ kubectl edit cm kube-flannel-cfg -n kube-flannel
...
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "host-gw"
}
}
kind: ConfigMap
...

重建Flannel的Pod

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ kubectl -n kube-flannel get pod
NAME READY STATUS RESTARTS AGE
kube-flannel-ds-6tx4f 1/1 Running 0 88d
kube-flannel-ds-7p2rb 1/1 Running 0 88d
kube-flannel-ds-rx54g 1/1 Running 0 88d

$ kubectl -n kube-flannel delete po kube-flannel-ds-6tx4f kube-flannel-ds-7p2rb kube-flannel-ds-rx54g

# 等待Pod新启动后,查看日志,出现Backend type: host-gw字样
$ kubectl -n kube-flannel logs -f kube-flannel-ds-xbbg2
Defaulted container "kube-flannel" out of: kube-flannel, install-cni-plugin (init), install-cni (init)
I1121 17:30:43.302575 1 main.go:212] CLI flags config: {etcdEndpoints:http://127.0.0.1:4001,http://127.0.0.1:2379 etcdPrefix:/coreos.com/network etcdKeyfile: etcdCertfile: etcdCAFile: etcdUsername: etcdPassword: version:false kubeSubnetMgr:true kubeApiUrl: kubeAnnotationPrefix:flannel.alpha.coreos.com kubeConfigFile: iface:[ens224] ifaceRegex:[] ipMasq:true ifaceCanReach: subnetFile:/run/flannel/subnet.env publicIP: publicIPv6: subnetLeaseRenewMargin:60 healthzIP:0.0.0.0 healthzPort:0 iptablesResyncSeconds:5 iptablesForwardRules:true netConfPath:/etc/kube-flannel/net-conf.json setNodeNetworkUnavailable:true useMultiClusterCidr:false}
W1121 17:30:43.302852 1 client_config.go:617] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.
I1121 17:30:43.336114 1 kube.go:145] Waiting 10m0s for node controller to sync
I1121 17:30:43.336353 1 kube.go:489] Starting kube subnet manager
I1121 17:30:43.345998 1 kube.go:510] Creating the node lease for IPv4. This is the n.Spec.PodCIDRs: [10.244.0.0/24]
I1121 17:30:43.346170 1 kube.go:510] Creating the node lease for IPv4. This is the n.Spec.PodCIDRs: [10.244.1.0/24]
I1121 17:30:43.346257 1 kube.go:510] Creating the node lease for IPv4. This is the n.Spec.PodCIDRs: [10.244.2.0/24]
I1121 17:30:44.337195 1 kube.go:152] Node controller sync successful
I1121 17:30:44.337292 1 main.go:232] Created subnet manager: Kubernetes Subnet Manager - k8s-master
I1121 17:30:44.337312 1 main.go:235] Installing signal handlers
I1121 17:30:44.337914 1 main.go:543] Found network config - Backend type: host-gw
I1121 17:30:44.339623 1 match.go:259] Using interface with name ens224 and address 192.168.100.1
I1121 17:30:44.339696 1 match.go:281] Defaulting external address to interface address (192.168.100.1)
I1121 17:30:44.360432 1 main.go:357] Setting up masking rules
I1121 17:30:44.361152 1 kube.go:510] Creating the node lease for IPv4. This is the n.Spec.PodCIDRs: [10.244.0.0/24]
I1121 17:30:44.417318 1 main.go:408] Changing default FORWARD chain policy to ACCEPT
I1121 17:30:44.422345 1 iptables.go:290] generated 7 rules
I1121 17:30:44.428274 1 iptables.go:290] generated 3 rules
I1121 17:30:44.428651 1 main.go:436] Wrote subnet file to /run/flannel/subnet.env
I1121 17:30:44.428713 1 main.go:440] Running backend.
I1121 17:30:44.429253 1 route_network.go:56] Watching for new subnet leases
......

查看节点路由表:

1
2
3
4
5
6
7
8
9
$ ip r s
default via 10.209.0.200 dev ens192 proto dhcp src 10.209.0.13 metric 100
default via 192.168.100.254 dev ens224 proto static metric 101
10.209.0.0/21 dev ens192 proto kernel scope link src 10.209.0.13 metric 100
10.244.0.0/24 dev cni0 proto kernel scope link src 10.244.0.1
10.244.1.0/24 via 192.168.100.2 dev ens224
10.244.2.0/24 via 192.168.100.3 dev ens224
172.7.21.0/24 dev docker0 proto kernel scope link src 172.7.21.1 linkdown
192.168.100.0/24 dev ens224 proto kernel scope link src 192.168.100.1 metric 101

总结

flannel pod做的几个事情:

  • 为了配置本机的Pod网络
    • flannel pod启动时,拷贝cni的配置文件/etc/cni/net.d/10-flannel.conflist,告知CRI(containerd) 使用flannel插件进行配置网络
    • 拷贝一份可执行文件到宿主机 /opt/cni/bin/flannel
    • 调用apiserver,得到分配到本机的PodCIDR,写入到/run/flannel/subnet.env
    • 调用本机的bridge插件,创建本地cni0网桥,创建虚拟网卡对,链接cni0和Pod网络空间
    • bridge cni调用local ipam插件(host-local),记录并分配pod ip,写入到/var/lib/cni/networks/cbr0/
  • 为了使得跨主机实现Pod的访问
    • 创建flannel.1 vtep设备,支持vxlan模式下封包解包
    • 维护本机路由表,转发Pod的流量
文章目录
  1. 1. Kubernetes集群的网络实现
    1. 1.1. 容器网络回顾
    2. 1.2. Pod IP唯一性保障
    3. 1.3. Pod配置网络流程
    4. 1.4. kube-flannel的作用
    5. 1.5. 跨主机Pod通信
      1. 1.5.1. vxlan介绍及点对点通信的实现
      2. 1.5.2. vxlan点对点通信的实现
        1. 1.5.2.1. 配置vxlan网络
        2. 1.5.2.2. 测试点对点通信
        3. 1.5.2.3. 配置路由
        4. 1.5.2.4. 再次测试点对点通信
        5. 1.5.2.5. 等似模型
        6. 1.5.2.6. 清除配置
      3. 1.5.3. 跨主机Pod通信
      4. 1.5.4. kube-flannel中flanneld的作用
      5. 1.5.5. 利用host-gw模式提升集群网络性能
    6. 1.6. 总结