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是什么
- flannel 是一个为k8s设计的简单易用的三层网络解决方案
- falnnel 不控制container 如何与host 进行通讯,只控制host与host之间如何通讯
- flannel 聚焦于网络通讯,网络策略有calico 负责
- flannel 以服务的形式运行在每一台主机上,负责从大的网络中租赁子网给每一台主机
- flannel 可以使用k8s api 或直接使用etcd来存储网络配置、子网分配及辅助数据。通过监听etcd的变化来调整路由,github 建议使用k8s api 来连接etcd
- 容器间数据包被转发通过vxlan、host-gw 及多种云网络
- flannel 一旦获得租赁的子网会在
/run/flannel/subnet.env
生成环境变量文件。每次flannel 重启都会试图访问/run/flannel/subnet.env
中FLANNEL_SUBNET的值,从而防止在租约到期前更新了网络信息 - 可以运行多个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]
- 在启动kube-apiserver是需要添加
--allow-privileged=true
。否则在pod 中无法使用sercurityContext.privileged: true- 在启动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/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示