Kubernetes网络模型 -flannel +Calico

时间:2022-12-21 11:25:21

切换网络 所有pod 需要重建


Kubernetes 要求所有的网络插件实现必须满足如下要求:

  • 一个Pod一个IP
  • 所有的 Pod 可以与任何其他 Pod 直接通信,无需使用 NAT 映射
  • 所有节点可以与所有 Pod 直接通信,无需使用 NAT 映射
  • Pod 内部获取到的 IP 地址与其他 Pod 或节点与其通信时的 IP 地址是同一个。

Docker容器网络模型

先看下Linux网络名词:

  • 网络的命名空间:Linux在网络栈中引入网络命名空间,将独立的网络协议栈隔离到不同的命令空间中,彼此间无法通信;Docker利用这一特性,实现不同容器间的网络隔离。
  • Veth设备对:Veth设备对的引入是为了实现在不同网络命名空间的通信。
  • Iptables/Netfilter:Docker使用Netfilter实现容器网络转发。
  • 网桥:网桥是一个二层网络设备,通过网桥可以将Linux支持的不同的端口连接起来,并实现类似交换机那样的多对多的通信。
  • 路由:Linux系统包含一个完整的路由功能,当IP层在处理数据发送或转发的时候,会使用路由表来决定发往哪里。

Docker容器网络示意图如下:

Kubernetes网络模型 -flannel +Calico

Pod 网络

问题:Pod是K8S最小调度单元,一个Pod由一个容器或多个容器组成,当多个容器时,怎么都用这一个Pod IP?

实现:k8s会在每个Pod里先启动一个infra container小容器,然后让其他的容器连接进来这个网络命名空间,然后其他容器看到的网络试图就完全一样了。即网络设备、IP地址、Mac地址等。这就是解决网络共享的一种解法。在Pod的IP地址就是infra container的IP地址。

Kubernetes网络模型 -flannel +Calico

在 Kubernetes 中,每一个 Pod 都有一个真实的 IP 地址,并且每一个 Pod 都可以使用此 IP 地址与 其他 Pod 通信。

Pod之间通信会有两种情况:

  • 两个Pod在同一个Node上
  • 两个Pod在不同Node上

先看下第一种情况:两个Pod在同一个Node上

同节点Pod之间通信道理与Docker网络一样的,如下图:

Kubernetes网络模型 -flannel +Calico

  1. 对 Pod1 来说,eth0 通过虚拟以太网设备(veth0)连接到 root namespace;
  2. 网桥 cbr0 中为 veth0 配置了一个网段。一旦数据包到达网桥,网桥使用ARP 协议解析出其正确的目标网段 veth1;
  3. 网桥 cbr0 将数据包发送到 veth1;
  4. 数据包到达 veth1 时,被直接转发到 Pod2 的 network namespace 中的 eth0 网络设备。

再看下第二种情况:两个Pod在不同Node上

K8S网络模型要求Pod IP在整个网络中都可访问,这种需求是由第三方网络组件实现。

Kubernetes网络模型 -flannel +Calico

CNI(容器网络接口)

CNI(Container Network Interface,容器网络接口):是一个容器网络规范,Kubernetes网络采用的就是这个CNI规范,CNI实现依赖两种插件,一种CNI Plugin是负责容器连接到主机,另一种是IPAM负责配置容器网络命名空间的网络。

CNI插件默认路径:

# ls /opt/cni/bin/

地址:​​https://github.com/containernetworking/cni​

当你在宿主机上部署Flanneld后,flanneld 启动后会在每台宿主机上生成它对应的CNI 配置文件(它其实是一个 ConfigMap),从而告诉Kubernetes,这个集群要使用 Flannel 作为容器网络方案。

CNI配置文件路径:

/etc/cni/net.d/10-flannel.conflist

当 kubelet 组件需要创建 Pod 的时候,先调用dockershim它先创建一个 Infra 容器。然后调用 CNI 插件为 Infra 容器配置网络。

这两个路径在kubelet启动参数中定义:

--network-plugin=cni \
--cni-conf-dir=/etc/cni/net.d \
--cni-bin-dir=/opt/cni/bin

Kubernetes网络组件之 Flannel

Flannel是CoreOS维护的一个网络组件,Flannel为每个Pod提供全局唯一的IP,Flannel使用ETCD来存储Pod子网与Node IP之间的关系。flanneld守护进程在每台主机上运行,并负责维护ETCD信息和路由数据包。

Flannel 部署

​https://github.com/coreos/flannel​

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

查看当前pod网段

[root@zcsmaster1 20221220-kube-system]# cat kube-flannel.yml | grep Networ
"Network": "10.244.0.0/16",
hostNetwork: true
[root@zcsmaster1 20221220-kube-system]# kubectl get cm kubeadm-config -n kube-system -o yaml | grep -i podsub
podSubnet: 10.244.0.0/16
[root@zcsmaster1 20221220-kube-system]#

部署前删除集群中的calico

Kubernetes网络模型 -flannel +Calico

Kubernetes网络模型 -flannel +Calico

部署

kubectl  apply -f kube-flannel.yml

Kubernetes网络模型 -flannel +Calico

查看pod 状态

Kubernetes网络模型 -flannel +Calico

Kubernetes网络模型 -flannel +Calico

journalctl -u kubelet.service -f

报错如下

12月 20 11:23:36 zcsmaster1 kubelet[6271]: W1220 11:23:36.054839    6271 cni.go:239] Unable to update cni config: no networks found in /etc/cni/net.d
12月 20 11:23:37 zcsmaster1 kubelet[6271]: E1220 11:23:37.082238 6271 kubelet.go:2188] Container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

Kubernetes网络模型 -flannel +Calico

解决方法

rm -rf /etc/cni/net.d/*

rm -rf /var/lib/cni/calico

systemctl restart kubelet
systemctl restart

Kubernetes网络模型 -flannel +Calico

访问pod

Kubernetes网络模型 -flannel +Calico

Flannel工作模式及原理

VXLAN

Flannel支持多种数据转发方式:

  • UDP:最早支持的一种方式,由于性能最差,目前已经弃用。
  • VXLAN:Overlay Network方案,源数据包封装在另一种网络包里面进行路由转发和通信
  • Host-GW:Flannel通过在各个节点上的Agent进程,将容器网络的路由信息刷到主机的路由表上,这样一来所有的主机都有整个容器网络的路由数据了。
  • Directrouting(vxlan+host-gw)

# kubeadm部署指定Pod网段
kubeadm init --pod-network-cidr=10.244.0.0/16

# 二进制部署指定
cat /opt/kubernetes/cfg/kube-controller-manager.conf
--allocate-node-cidrs=true \
--cluster-cidr=10.244.0.0/16 \

#配置文件 kube-flannel.yml
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}

为了能够在二层网络上打通“隧道”,VXLAN 会在宿主机上设置一个特殊的网络设备作为“隧道”的两端。这个设备就叫作 VTEP,即:VXLAN Tunnel End Point(虚拟隧道端点)。

Kubernetes网络模型 -flannel +Calico

kubectl  create deploy busybox-pod1  --image=busybox -o yaml --dry-run=client >busybox1.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
creationTimestamp: null
labels:
app: busybox-pod1
name: busybox-pod1
spec:
replicas: 1
selector:
matchLabels:
app: busybox-pod1
strategy: {}
template:
metadata:
creationTimestamp: null
labels:
app: busybox-pod1
spec:
containers:
- image: busybox
name: busybox
command: ["/bin/sh","-c","sleep 36000"]

Kubernetes网络模型 -flannel +Calico


如果Pod 1访问Pod 2,源地址10.244.2.21,目的地址10.244.2.20 ,数据包传输流程如下:

  • 首先进入容器

1、容器路由:容器根据路由表从eth0发出

kubectl  exec -it busybox-pod1-f4d5dc49b-fkr7c   sh

kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
/ # ip route
default via 10.244.2.1 dev eth0
10.244.0.0/16 via 10.244.2.1 dev eth0
10.244.2.0/24 dev eth0 scope link src 10.244.2.21
/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
link/ether a2:8f:3c:b9:eb:9d brd ff:ff:ff:ff:ff:ff
inet 10.244.2.21/24 brd 10.244.2.255 scope global eth0
valid_lft forever preferred_lft forever

2、主机路由:数据包进入到宿主机虚拟网卡cni0,根据路由表转发到flannel.1虚拟网卡,也就是,来到了隧道的入口。

登录 pod 所在节点 查找 default via 10.244.2.1 dev eth0

Kubernetes网络模型 -flannel +Calico

[root@zcsnode2 ~]# ip route

default via 192.168.40.2 dev ens32 proto static metric 100
10.244.0.0/24 via 10.244.0.0 dev flannel.1 onlink
10.244.1.0/24 via 10.244.1.0 dev flannel.1 onlink

3、VXLAN封装:而这些VTEP设备(二层)之间组成二层网络必须要知道目的MAC地址。这个MAC地址从哪获取到呢?其实在flanneld进程启动后,就会自动添加其他节点ARP记录,可以通过ip命令查看,如下所示:

[root@zcsnode2 ~]# ip neigh show dev flannel.1

10.244.1.0 lladdr 06:af:28:c8:84:47 PERMANENT

10.244.0.0 lladdr ea:07:71:ce:97:8b PERMANENT

4、二次封包:知道了目的MAC地址,封装二层数据帧(容器源IP和目的IP)后,对于宿主机网络来说这个帧并没有什么实际意义。接下来,Linux内核还要把这个数据帧进一步封装成为宿主机网络的一个普通数据帧,好让它载着内部数据帧,通过宿主机的eth0网卡进行传输。

Kubernetes网络模型 -flannel +Calico

5、封装到UDP包发出去:现在能直接发UDP包嘛?到目前为止,我们只知道另一端的flannel.1设备的MAC地址,却不知道对应的宿主机地址是什么。

flanneld进程也维护着一个叫做FDB的转发数据库,可以通过bridge fdb命令查看:


[root@zcsmaster1 20221220-kube-system]# bridge fdb show  dev flannel.1

06:af:28:c8:84:47 dst 192.168.40.181 self permanent

92:bc:79:d0:e7:d3 dst 192.168.40.182 self permanent

可以看到,上面用的对方flannel.1的MAC地址对应宿主机IP,也就是UDP要发往的目的地。使用这个目的IP进行封装。

6、数据包到达目的宿主机:Node2的eth0网卡发出去,发现是VXLAN数据包,把它交给flannel.1设备。flannel.1设备则会进一步拆包,取出原始二层数据帧包,发送ARP请求,经由cni0网桥转发给container

Host-GW

host-gw模式相比vxlan简单了许多, 直接添加路由,将目的主机当做网关,直接路由原始封包。

kubectl edit cm kube-flannel-cfg  -n kube-flannel

net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "host-gw"
}
}

kubectl  delete pod  kube-flannel-ds-2kpf6    -n kube-flannel


当你设置flannel使用host-gw模式,flanneld会在宿主机上创建节点的路由表:

Kubernetes网络模型 -flannel +Calico

Kubernetes网络模型 -flannel +Calico

例如两个pod 在不同节点

Kubernetes网络模型 -flannel +Calico

在master 节点可以看到 10.244.1.0/24  10.244.2.0/24  下一跳地址

Kubernetes网络模型 -flannel +Calico

node2节点路由信息

Kubernetes网络模型 -flannel +Calico

node1 路由信息

Kubernetes网络模型 -flannel +Calico

一旦配置了下一跳地址,那么接下来,当 IP 包从网络层进入链路层封装成帧的时候,eth0 设备就会使用下一跳地址对应的 MAC 地址,作为该数据帧的目的 MAC 地址。


而 Node 2 的内核网络栈从二层数据帧里拿到 IP 包后,会“看到”这个 IP 包的目的 IP 地址是10.244.1.6,即busybox-pod2 的 IP 地址。这时候,根据 Node 2 上的路由表,该目的地址会匹配到第二条路由规则(也就是 10.244.1.0 对应的路由规则),从而进入 cni0 网桥,进而进入到 container-2 当中。

Directrouting

 kubectl edit cm kube-flannel-cfg  -n kube-flannel

net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
"Directrouting": true
}
}

小结:

1、vxlan 不受网络环境限制,只要三层可达就行

2、vxlan 需要二层解封包,降低工作效率

3、hostgw 基于路由表转发,效率更高 新能更好 (前提在同一个网段)

4、hostgw 只适用于二层网络(本身网络架构受限,节点数量也受限)

Kubernetes网络方案之 Calico

Calico是一个纯三层的数据中心网络方案,Calico支持广泛的平台,包括Kubernetes、OpenStack等。

Calico 在每一个计算节点利用 Linux Kernel 实现了一个高效的虚拟路由器( vRouter) 来负责数据转发,而每个 vRouter 通过 BGP 协议负责把自己上运行的 workload 的路由信息向整个 Calico 网络内传播。

此外,Calico 项目还实现了 Kubernetes 网络策略,提供ACL功能。

BGP概述

实际上,Calico项目提供的网络解决方案,与Flannel的host-gw模式几乎一样。也就是说,Calico也是基于路由表实现容器数据包转发,但不同于Flannel使用flanneld进程来维护路由信息的做法,而Calico项目使用BGP协议来自动维护整个集群的路由信息。

BGP英文全称是Border Gateway Protocol,即边界网关协议,它是一种自治系统间的动态路由发现协议,与其他 BGP 系统交换网络可达信息。

为了能让你更清楚理解BGP,举个例子:

Kubernetes网络模型 -flannel +Calico

在这个图中,有两个自治系统(autonomous system,简称为AS):AS 1 和 AS 2。

在互联网中,一个自治系统(AS)是一个有权自主地决定在本系统中应采用何种路由协议的小型单位。这个网络单位可以是一个简单的网络也可以是一个由一个或多个普通的网络管理员来控制的网络群体,它是一个单独的可管理的网络单元(例如一所大学,一个企业或者一个公司个体)。一个自治系统有时也被称为是一个路由选择域(routing domain)。一个自治系统将会分配一个全局的唯一的16位号码,有时我们把这个号码叫做自治系统号(ASN)。

在正常情况下,自治系统之间不会有任何来往。如果两个自治系统里的主机,要通过 IP 地址直接进行通信,我们就必须使用路由器把这两个自治系统连接起来。BGP协议就是让他们互联的一种方式。

Calico BGP实现

Kubernetes网络模型 -flannel +Calico

在了解了 BGP 之后,Calico 项目的架构就非常容易理解了,Calico主要由三个部分组成:

  • Felix:以DaemonSet方式部署,运行在每一个Node节点上,主要负责维护宿主机上路由规则以及ACL规则。
  • BGP Client(BIRD):主要负责把 Felix 写入 Kernel 的路由信息分发到集群 Calico 网络。
  • Etcd:分布式键值存储,保存Calico的策略和网络配置状态。
  • calicoctl:允许您从简单的命令行界面实现高级策略和网络。

Calico 部署

curl curl https://docs.projectcalico.org/v3.20/manifests/calico.yaml-o calico.yaml

下载完后还需要修改里面配置项:

具体步骤如下:

  • 配置连接etcd地址,如果使用https,还需要配置证书。(ConfigMap,Secret)(kubeadm 部署的集群 只关注以下两点)
  • 根据实际网络规划修改Pod CIDR(CALICO_IPV4POOL_CIDR)

kubectl get cm kubeadm-config -n kube-system -o yaml | grep -i podsub


  • 选择工作模式(CALICO_IPV4POOL_IPIP),支持BGP(Never)IPIP(Always)CrossSubnet(开启BGP并支持跨子网)

删除flannel网络

所有节点执行

# kubectl delete -f kube-flannel.yaml
# ip link delete flannel.1
# ip link delete cni0
# ip route del 10.244.1.0/24 via 192.168.40.181 dev ens32
# ip route del 10.244.2.0/24 via 192.168.40.182 dev ens32

修改 calico.yaml

Kubernetes网络模型 -flannel +Calico


Kubernetes网络模型 -flannel +Calico

应用清单:

# kubectl apply -f calico.yaml
# kubectl get pods -n kube-system

Calico 管理工具

注意:工具版本不到大于calico 版本

下载工具:​https://github.com/projectcalico/calicoctl/releases​

wget https://github.com/projectcalico/calico/releases/tag/v3.20.6
cp calicoctl /usr/bin
chmod +x /usr/bin/calicoctl

命令行测试

DATASTORE_TYPE=kubernetes KUBECONFIG=~/.kube/config calicoctl node status

Kubernetes网络模型 -flannel +Calico

配置文件测试

mkdir -p /etc/calico/
vim /etc/calico/calicoctl.cfg

apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
datastoreType: "kubernetes"
kubeconfig: "/root/.kube/config"



calicoctl node status

如下图


Kubernetes网络模型 -flannel +Calico

常用命令如下

# 查看 BGP Peer
[root@zcsmaster1 bin]# calicoctl get bgppeer
NAME PEERIP NODE ASN
......
# 收集诊断
[root@zcsmaster1 bin]# calicoctl node diags
......
# 查看所有的BGP节点,若携带右侧参数则能输出AS号,一个编号就是一个自治系统
[root@zcsmaster1 bin]# calicoctl get nodes --output=wide
NAME ASN IPV4 IPV6
zcsmaster1 (64512) 192.168.40.180/24
zcsnode1 (64512) 192.168.40.181/24
zcsnode2 (64512) 192.168.40.182/24 [root@zcsmaster1 bin]# calicoctl node status
Calico process is running.

IPv4 BGP status
+----------------+-------------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
+----------------+-------------------+-------+----------+-------------+
| 192.168.40.181 | node-to-node mesh | up | 07:41:45 | Established |
| 192.168.40.182 | node-to-node mesh | up | 07:41:45 | Established |
+----------------+-------------------+-------+----------+-------------+

# 查看IP池相关信息 ...

[root@zcsmaster1 bin]# calicoctl get ipPool -o yaml
apiVersion: projectcalico.org/v3
items:
- apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
creationTimestamp: "2022-12-20T07:41:39Z"
name: default-ipv4-ippool
resourceVersion: "213763"
uid: 6f666892-4a12-4793-982f-f5d75f153149
spec:
blockSize: 26
cidr: 10.244.0.0/16
ipipMode: Never
natOutgoing: true
nodeSelector: all()
vxlanMode: Never
kind: IPPoolList
metadata:
resourceVersion: "223175"

[root@zcsmaster1 bin]# calicoctl get ipPool -o wide
NAME CIDR NAT IPIPMODE VXLANMODE DISABLED SELECTOR
default-ipv4-ippool 10.244.0.0/16 true Never Never false all()

Calico BGP 原理

Pod 1 访问 Pod 2大致流程如下:

  1. 数据包从容器1出到达Veth Pair另一端(宿主机上,以cali前缀开头);
  2. 宿主机根据路由规则,将数据包转发给下一跳(网关);
  3. 到达Node2,根据路由规则将数据包转发给cali设备,从而到达容器2

master 节点查看地址

Kubernetes网络模型 -flannel +Calico

node1 路由如下

详细表述了 路由表 ,类似静态路由

default via 192.168.40.2 dev ens33 proto static metric 100 
10.244.178.192 via 192.168.40.180 dev ens33 proto bird
10.244.234.64/26 via 192.168.40.182 dev ens33 proto bird
10.244.236.0 dev calice006542334 scope link
blackhole 10.244.236.0/26 proto bird
10.244.236.1 dev cali0165a3bd95c scope link
10.244.236.2 dev cali41405ac4777 scope link
10.244.236.3 dev cali54e47caa1bc scope link
10.244.236.4 dev cali61779b5908a scope link
10.244.236.5 dev calic0ed5697017 scope link
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
192.168.40.0/24 dev ens33 proto kernel scope link src 192.168.40.181 metric 100

Kubernetes网络模型 -flannel +Calico

node2路由如下

Kubernetes网络模型 -flannel +Calico

其中,这里最核心的“下一跳”路由规则,就是由 Calico 的 Felix 进程负责维护的。这些路由规则信息,则是通过 BGP Client 也就是 BIRD 组件,使用 BGP 协议传输而来的。

不难发现,Calico 项目实际上将集群里的所有节点,都当作是边界路由器来处理,它们一起组成了一个全连通的网络,互相之间通过 BGP 协议交换路由规则。这些节点,我们称为 BGP Peer。



Route Reflector 模式(RR)

​https://docs.projectcalico.org/master/networking/bgp​

Calico 维护的网络在默认是(Node-to-Node Mesh)全互联模式,Calico集群中的节点之间都会相互建立连接,用于路由交换。但是随着集群规模的扩大,mesh模式将形成一个巨大服务网格,连接数成倍增加

节点越多 压力 越大node-to-node

+----------------+-------------------+-------+----------+-------------+
| PEER ADDRESS | PEER TYPE | STATE | SINCE | INFO |
+----------------+-------------------+-------+----------+-------------+
| 192.168.40.181 | node-to-node mesh | up | 07:41:45 | Established |
| 192.168.40.182 | node-to-node mesh | up | 07:41:45 | Established |
+----------------+-------------------+-------+----------+-------------+

Kubernetes网络模型 -flannel +Calico

这时就需要使用 Route Reflector(路由器反射)模式解决这个问题。

确定一个或多个Calico节点充当路由反射器,让其他节点从这个RR节点获取路由信息。

具体步骤如下:

1、关闭 node-to-node BGP网格 

操作立马断网

添加 default BGP配置,调整 nodeToNodeMeshEnabled和asNumber:

ASN号可以通过获取 

calicoctl get nodes --output=wide

Kubernetes网络模型 -flannel +Calico

cat << EOF | calicoctl create -f -
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
name: default
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: false
asNumber: 64512
EOF

查看配置
[root@zcsmaster1 20221220-kube-system]# calicoctl get bgpconfig
NAME LOGSEVERITY MESHENABLED ASNUMBER
default Info false 64512
2、配置指定节点充当路由反射器

为方便让BGPPeer轻松选择节点,通过标签选择器匹配。

给路由器反射器节点打标签:

[root@zcsmaster1 20221220-kube-system]# kubectl  get node
NAME STATUS ROLES AGE VERSION
zcsmaster1 Ready control-plane,master 244d v1.20.6
zcsnode1 Ready <none> 244d v1.20.6
zcsnode2 Ready <none> 244d v1.20.6

kubectl label node zcsnode1 route-reflector=true

然后配置路由器反射器节点routeReflectorClusterID:(RR)

calicoctl get node zcsnode1 -o yaml > rr-node.yaml

Kubernetes网络模型 -flannel +Calico

calicoctl  apply -f rr-node.yaml

现在,很容易使用标签选择器将路由反射器节点与其他非路由反射器节点配置为对等

# vi bgppeer.yaml
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
name: peer-with-route-reflectors
spec:
nodeSelector: all()
peerSelector: route-reflector == 'true'

calicoctl apply -f bgppeer.yaml

查看节点的BGP连接状态:

calicoctl node status

Kubernetes网络模型 -flannel +Calico

3、路由反射器做高可用

kubectl label node zcsnode2 route-reflector=true

Kubernetes网络模型 -flannel +Calico

calicoctl get node zcsnode2 -o yaml > rr-node2.yaml

routeReflectorClusterID: 244.0.0.1


添加以下字段

Kubernetes网络模型 -flannel +Calico

calicoctl apply -f rr-node2.yaml

Successfully applied 1 'Node' resource(s)

查看节点连接状态

calicoctl node status




IPIP模式

(解决node 在不同网段的问题)

在前面提到过,Flannel host-gw 模式最主要的限制,就是要求集群宿主机之间是二层连通的。而这个限制对于 Calico 来说,也同样存在。

修改为IPIP模式:

calicoctl get ipPool -o yaml > ipip.yaml

Kubernetes网络模型 -flannel +Calico

calicoctl apply -f ipip.yaml

查看状态

IPIPMODE  = Always  启用 ipip 模式

# calicoctl get ippool
NAME CIDR SELECTOR
default-ipv4-ippool 10.244.0.0/16 all()

#calicoctl get ippool -o wide
NAME CIDR NAT IPIPMODE VXLANMODE DISABLED SELECTOR
default-ipv4-ippool 10.244.0.0/16 true Always Never false all()

会发现多了网卡tunl0 (隧道的网卡)

Kubernetes网络模型 -flannel +Calico

Kubernetes网络模型 -flannel +Calico

ipip 示意图


Kubernetes网络模型 -flannel +Calico


Pod 1 访问 Pod 2大致流程如下:
  1. 数据包从容器1出到达Veth Pair另一端(宿主机上,以cali前缀开头);
  2. 进入IP隧道设备(tunl0)由Linux内核IPIP驱动封装在宿主机网络的IP包中(新的IP包目的地之是原IP包的下一跳地址),这样就成了Node1 到Node2的数据包;
  3. 数据包经过路由器三层转发到Node2;
  4. Node2收到数据包后,网络协议栈会使用IPIP驱动进行解包,从中拿到原始IP包;
  5. 然后根据路由规则,根据路由规则将数据包转发给cali设备,从而到达容器2。
路由表:

master节点写了 去往两个网段的 ,路由 以及网卡

Kubernetes网络模型 -flannel +Calico

node1 节点描述 其他两个节点的路由

Kubernetes网络模型 -flannel +Calico

node 2节点发现路由有问题

Kubernetes网络模型 -flannel +Calico

so

更改工作模式 需要重启pod

kubectl  get pod  |awk '{print $1}' |grep -v NAME| xargs kubectl delete pod 

所有节点还重启了 docker kubelet
systemctl restart docker

systemctl restart kubelet

Kubernetes网络模型 -flannel +Calico

node1;node2 路由表如下

Kubernetes网络模型 -flannel +Calico

Kubernetes网络模型 -flannel +Calico

不难看到,当 Calico 使用 IPIP 模式的时候,集群的网络性能会因为额外的封包和解包工作而下降。所以建议你将所有宿主机节点放在一个子网里,避免使用 IPIP。

CNI 网络方案优缺点及选择

先考虑几个问题:

  • 需要细粒度网络访问控制?
  • 追求网络性能?
  • 服务器之前是否可以跑BGP协议?
  • 集群规模多大?
  • 是否有维护能力?


思考

1.k8s 网络环境和办公网络互相通信

在办公网络 添加路由

ip route add 10.244.0.0/16 via <k8s-node1> dev A