cni网络插件之flannel

https://www.cni.dev/
https://github.com/containernetworking/plugins
https://www.rfc-editor.org/rfc/rfc7348
静态分配pod ip https://github.com/k8snetworkplumbingwg/whereabouts

flannel 涉及到的目录

/var/lib/cni/networks/cbr0 保存了pod 地址分配信息
/run/flannel/subnet.env  保存了节点子网分配信息
/opt/cni/bin/  保存了可执行命令
/etc/cni/net.d/10-flannel.conflist  保存了cni配置的信息

flannel是什么

  1. flannel 是一个为k8s设计的简单易用的三层网络解决方案
  2. falnnel 不控制container 如何与host 进行通讯,只控制host与host之间如何通讯
  3. flannel 聚焦于网络通讯,网络策略有calico 负责
  4. flannel 以服务的形式运行在每一台主机上,负责从大的网络中租赁子网给每一台主机
  5. flannel 可以使用k8s api 或直接使用etcd来存储网络配置、子网分配及辅助数据。通过监听etcd的变化来调整路由,github 建议使用k8s api 来连接etcd
  6. 容器间数据包被转发通过vxlan、host-gw 及多种云网络
  7. flannel 一旦获得租赁的子网会在/run/flannel/subnet.env 生成环境变量文件。每次flannel 重启都会试图访问/run/flannel/subnet.env 中FLANNEL_SUBNET的值,从而防止在租约到期前更新了网络信息
  8. 可以运行多个flanneld 通过flanneld -subnet-file /vxlan.env -etcd-prefix=/vxlan/network

flannel配置文件

[info]

如果 --kube-subnet-mgr true则flannel 从 /etc/kube-flannel/net-conf.json读取启动配置
如果 --kube-subnet-mgr false则flannel 从 etcd读取启动配置。其中key 为/coreos.com/network/config,可以使用--etcd-prefix 来修改该key

-ip-masq
setup IP masquerade rule for traffic destined outside of overlay network

配置文件事例

# cat /etc/kube-flannel/net-conf.json
{
    "Network": "10.244.0.0/16", # 必须的key
    "SubnetLen": "/24",
    "SubnetMin": "10.244.21.0/24",
    "SubnetMax": "10.244.22.0/24",
    "Backend": {
        "Type": "udp",
        "Port": 7890
	}
}

Backends

flannel 支持多种类型的配置,这个设置一旦设定,在集群运行状态不应该做修改

  • VXLAN

  • host-gw 通常不能使用在云环境,要求host 运行在相同的二层网络

  • UDP suggested for debugging

  • AWS, GCE, and AliVPC 处于试验阶段,存在风险

  • ipip

  • ipsec

vxlan 使用linxu内核的vxlan 技术进行封包

"Backend":{
    "Type": "vxlan",
    # vxlan的标识符 linux 使用 1, windows 使用大于或等于4096的值
    "VNI": 1,
    # 当通讯的主机在同一子网中时基于host-gw 的方式通讯,vxlan 仅用于不同网段的主机通讯
    "DirectRouting": false
}

host-gw

"Backend":{
    "Type": "host-gw"
}

upd

"Backend":{
    "Type": "udp",
     # udp 的端口 Linux 使用 8472 windows 使用4789
    "Port": 8472
}

ali-vpc

"Backend":{
    "Type": "ali-vpc",
    # 可以使用环境变量 ACCESS_KEY_ID
    "AccessKeyID": "",
    # 可以使用环境变量 ACCESS_KEY_SECRET
    "AccessKeySecret": ""
}

tencent-vpc

"Backend":{
    "Type": "tencent-vpc",
    # 可以使用环境变量 ACCESS_KEY_ID
    "AccessKeyID": "",
    # 可以使用环境变量 ACCESS_KEY_SECRET
    "AccessKeySecret": ""
}

ipip
使用内核的ipip 来封装包
ipip 是一种最简单的隧道
他的开销最低,单只能封装基于IPV4的单播数据,因此不支持 OSPF RIP 等基于组播的协议

"Backend": {
    "Type": "ipip",
    # 当通讯的主机在同一子网中时基于host-gw 的方式通讯,ipip 仅用于不同网段的主机通讯
    "DirectRouting": false 
}

ipsec
使用内核的ipsec 进行封包
使用IKEv2进程,通过预共享秘钥的来实现秘钥的交换,保证秘钥在周期性改变

"Backend": {
    "Type": "ipsec",
    # 预共享秘钥,最少96个字符,可以使用这个命令生成 dd if=/dev/urandom count=48 bs=1 status=none | xxd -p -c 48  xxd通过yum install vim-common 安装
    "PSK": ""
    # 当通讯的主机在同一子网中时基于host-gw 的方式通讯,ipip 仅用于不同网段的主机通讯
    "DirectRouting": false,
    # 使用udp 封包,默认false
    "UDPEncap": false,
    # 秘钥交换的算法
    "ESPProposal": "aes128gcm16-sha256-prfsha256-ecp256"
}

启动命令

flannel

--publish-ip="10.4.7.21" 用于通讯的ip
--etcd-endpoints=https://10.4.7.12:2379,https://10.4.7.21:2379 指定etcd,使用都好隔开
--etcd-prefix=/coreos.com/network 指定 etdctl 中key
--etcd-keyfile="" 与etcd 通讯的key
--etcd-certfile="" 与etcd 通讯的crt
--etcd-cafile="" 与etcd 通讯的ca
--kube-subnet-mgr 指定使用k8sapi 而不是独立的etcd
--iface="" 指定通讯的网卡名字 eth0
--subnet-file=/run/flannel/subnet.env 指定变量文件包括subnet 和 MTU。MTU 有flannel 自动设定不能修改
--net-config-path=/etc/kube-flannel/net-conf.json 指定启动配置文件
--ip-masq=false 发往pod 集群外的网络进行nat,这里假设iptables POSTROUTING 的默认策略为ACCEPT
--healthz-port=0 指定健康检查的端口,0 表示禁用

任何指令都可以通过环境变量的形式传递规则如下:
使用FLANNELD_代替指令开头的--
其他- 转换成_
所有小写字母转大写
举例:--etcd-endpoints=http://10.0.0.2:2379 is equivalent to FLANNELD_ETCD_ENDPOINTS=http://10.0.0.2:2379

安装部署

[info]

  1. 在启动kube-apiserver是需要添加 --allow-privileged=true 。否则在pod 中无法使用sercurityContext.privileged: true
  2. 在启动kubelet 是需要指定 --allocate-node-cidrs=true --cluster-cidr="172.7.0.0/16" 。否则会提示crashLoopBackOff,容器日志提示Error registering network: faild to acquire less: node "node-01" pod cidr not assigned

部署
https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/k8s-manifests/kube-flannel-legacy.yml
https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml

网络策略canl
wget https://docs.projectcalico.org/manifests/canal.yaml --no-check-certificate

vxlan 下数据包的抓取

[root@master ~]# ip r
default via 10.4.7.254 dev eth0 proto static metric 100 
10.4.7.0/24 dev eth0 proto kernel scope link src 10.4.7.12 metric 100 
172.7.0.0/24 dev cni0 proto kernel scope link src 172.7.0.1 
172.7.0.7 dev calic5dfa14a2a1 scope link 
172.7.0.8 dev cali67af1dd0d0b scope link 
172.7.0.21 dev cali725cb08e809 scope link 
172.7.1.0/24 via 172.7.1.0 dev flannel.1 onlink 
[root@master ~]# tcpdump -i flannel.1 icmp -nn
22:21:46.943557 IP 172.7.0.22 > 172.7.1.88: ICMP echo request, id 17, seq 0, length 64
22:21:46.944043 IP 172.7.1.88 > 172.7.0.22: ICMP echo reply, id 17, seq 0, length 64
[root@master ~]# tcpdump -i eth0 -nnn  |sed -n '/overlay/{N;p}'
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:41:16.081998 IP 10.4.7.12.48367 > 10.4.7.11.8472: OTV, flags [I] (0x08), overlay 0, instance 1
IP 172.7.0.22 > 172.7.1.88: ICMP echo request, id 15, seq 0, length 64
22:41:16.082615 IP 10.4.7.11.53477 > 10.4.7.12.8472: OTV, flags [I] (0x08), overlay 0, instance 1
IP 172.7.1.88 > 172.7.0.22: ICMP echo reply, id 15, seq 0, length 64
22:41:18.217711 IP 10.4.7.12.47091 > 10.4.7.11.8472: OTV, flags [I] (0x08), overlay 0, instance 1

和docker集成

[info]

Docker 1.16及以后,将不再使用docker daemon命令,而直接使用dockerd命令了

需要先启动docker

source /run/flannel/subnet.env
docker daemon --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU} &
EnvironmentFile=/run/flannel/subnet.env   # 文件不存在是会报错
ExecStart=/usr/bin/dockerd \
          -H fd:// --containerd=/run/containerd/containerd.sock \
          --bip ${FLANNEL_SUBNET} \
          --mtu=${FLANNEL_MTU}
source /run/flannel/subnet.env
docker network create --attachable=true --subnet=${FLANNEL_SUBNET} -o "com.docker.network.driver.mtu"=${FLANNEL_MTU} flannel

FQA
启动报错信息

[root@hdss7-11 ~]# FLANNEL_SUBNET="10.24.3.0/24"
[root@hdss7-11 ~]# FLANNEL_MTU=1450
[root@hdss7-11 ~]# dockerd --bip=${FLANNEL_SUBNET} --mtu=${FLANNEL_MTU}
WARN[2021-12-09T10:48:16.618553963+08:00] The "graph" config file option is deprecated. Please use "data-root" instead.
INFO[2021-12-09T10:48:16.618703045+08:00] Starting up
INFO[2021-12-09T10:48:16.623793979+08:00] parsed scheme: "unix"                         module=grpc
INFO[2021-12-09T10:48:16.623832873+08:00] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2021-12-09T10:48:16.623861447+08:00] ccResolverWrapper: sending update to cc: {[{unix:///run/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2021-12-09T10:48:16.623871897+08:00] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2021-12-09T10:48:16.627321514+08:00] parsed scheme: "unix"                         module=grpc
INFO[2021-12-09T10:48:16.627370226+08:00] scheme "unix" not registered, fallback to default scheme  module=grpc
INFO[2021-12-09T10:48:16.627398410+08:00] ccResolverWrapper: sending update to cc: {[{unix:///run/containerd/containerd.sock  <nil> 0 <nil>}] <nil> <nil>}  module=grpc
INFO[2021-12-09T10:48:16.627412396+08:00] ClientConn switching balancer to "pick_first"  module=grpc
INFO[2021-12-09T10:48:16.640777303+08:00] Loading containers: start.
INFO[2021-12-09T10:48:16.746126687+08:00] stopping event stream following graceful shutdown  error="<nil>" module=libcontainerd namespace=moby
failed to start daemon: Error initializing network controller: Error creating default "bridge" network: failed to allocate gateway (10.24.3.0): Address already in use

解决办法

Docker can only start on the default bridge IP range · Issue #22638 · moby/moby · GitHub

修改成FLANNEL_SUBNET="10.24.3.1/24"

您可以使用以下两个命令之一检查节点的 podCidr

  • `kubectl get nodes -o jsonpath='{.items[*].spec.podCIDR}'``
  • ``kubectl get nodes -o template --template={{.spec.podCIDR}}`

如果没有可以手动修改

kubectl patch node <NODE_NAME> -p '{"spec":{"podCIDR":"<SUBNET>"}}

容器报错

cni0 already has an ip address different from 172.24.6.1/24

解决办法

这个节点之前加入过集群,flannel 网路配置不一致导致

ip link cni0 down
ip link flannel.1 down 
ip link delete cni0  
ip link delete flannel.1
rm -rf /var/lib/cni/flannel/*
rm -rf /var/lib/cni/networks/cni0/*
rm -fr /etc/cni/
posted @ 2021-12-18 20:50  mingtian是吧  阅读(669)  评论(0编辑  收藏  举报