k8s flannel网络插件

flannel 介绍

Flannel是用于解决容器跨节点通信问题的解决方案,兼容CNI插件API,支持Kubernetes、OpenShift、Cloud Foundry、Mesos、Amazon ECS、Singularity和OpenSVC等平台。它使用“虚拟网桥和veth设备”的方式为Pod创建虚拟网络接口,通过可配置的“后端”定义Pod间的通信网络,支持基于VXLAN和UDP的Overlay网络,以及基于三层路由的Underlay网络。在IP地址分配方面,它将预留的一个专用网络(默认为10.244.0.0/16)切分成多个子网后作为每个节点的PodCIDR,而后由节点以IPAM插件的host-local形式进行地址分配,并将子网分配信息保存于etcd之中。

flannel 运行机制

Flannel 运行一个在每个主机上调用的小型单个二进制代理flanneld,并负责从更大的预配置地址空间中为每个主机分配子网租约。Flannel 直接使用 Kubernetes API 或etcd来存储网络配置、分配的子网和任何辅助数据(例如主机的公共 IP)。使用多种后端机制之一转发数据包,包括 VXLAN 和各种云集成。

flannel 缺点

Flannel自身并不具备为Pod网络实施网络策略以实现其网络通信控制的能力,它只能借助Calico这类支持网络策略的插件实现该功能。

flannel 后端

Flannel 可以与几种不同的后端配对。一旦设置,后端不应在运行时更改。

VXLAN 是推荐选择。建议更有经验的用户使用 host-gw,host-gw有着较好的转发性能,且易于设定,推荐对报文转发性能要求较高的场景使用。(通常它不能在云环境中使用)。建议仅将 UDP 用于调试或不支持 VXLAN 的非常旧的内核。

flannel 组件

cni0: 网桥设备,没创建一个pod都会创建一对veth pair,其中一端是pod中的eth0,另一端是cni0网桥中的端口(网卡),pod中从网卡eth0发出的流量都会发送到cni0网桥设备的端口(网卡)上,cni0设备获得的ip地址是该节点分配到网段的第一个地址。
Flannel.1: overlay网络的设备,用来进行vxlan报文的处理(封包和解包),不同node之间的pod数据流量都从overlay设备以隧道的形式发送到对端。
flanneld: flannel进程。

VXLAN

使用Linux内核中的vxlan模块封装隧道报文,以Overlay网络模型支持跨节点的Pod间互联互通;同时,该后端类型支持直接路由模式,在该模式下,位于同一二层网络内节点之上的Pod间通信可通过路由模式直接发送,而跨网络的节点之上的Pod间通信仍要使用VXLAN隧道协议转发;因而,VXLAN隶属于Overlay网络模型,或混合网络模型;vxlan后端模式中,flanneld监听UDP的8472端口发送的封装数据包。
类型和选项:

Type(string):vxlan
VNI(number):要使用的 VXLAN 标识符 (VNI)。在 Linux 上,默认值为 1。在 Windows 上,应大于或等于 4096。
Port(number):用于发送封装数据包的 UDP 端口。在 Linux 上,默认为内核默认值,当前为 8472,但在 Windows 上,必须为 4789。
GBP(Boolean):启用基于 VXLAN 组的策略。默认为false. Windows 不支持GBP。
DirectRouting(Boolean):当主机位于同一子网时启用直接路由(如 host-gw)。VXLAN 仅用于将数据包封装到不同子网中的主机。默认为false. Windows 不支持 DirectRouting。
MTU(number):传出数据包所需的 MTU,如果未定义,则使用外部接口的 MTU。
MacPrefix(string):仅在 Windows 上使用,设置为 MAC 前缀。默认为0E-2A.
从 Ubuntu 21.10 开始,Raspberry Pi 上的 vxlan 支持已移至单独的内核模块中。

sudo apt install linux-modules-extra-raspi

flannel Vxlan工作模型示意图

Flannel 会在集群中每个运行 flanneld 的节点之上创建一个名为 flannel.1 的虚拟网桥作为本节点隧道出入口的 VTEP 设备,其中的 1 表示 VNI,因而所有节点上的 VTEP 均属于同一 VXLAN,或者属于同一个大二层域(BD),它们依赖于二层网关进行通信。Flannel 采用了分布式的网关模型,它把每个节点都视为到达该节点 Pod 子网的二层网关,相应的路由信息由 flanneld 自动生成。

1. pod中产生的数据,根据pod的路由信息,将数据发生到cni0。
2. cni0根据节点的路由表,将数据发送到隧道设备flannel.1。
3. flannel.1查看数据包的目的IP,从flanneld获得对端隧道设备的必要信息,封装数据包。
4. flannel.1将数据包发送到对端设备,对端节点的网卡接收到数据包

5. 对端节点发现数据包为overlay数据包,解开外层封装,并发送到本机flannel.1设备。
6. flannel.1设备查看数据包,根据路由表匹配,将数据发送给cni0设备。
7. cni0匹配路由表,发送数据给网桥上对应的端口(pod)。

直接路由

为了提升性能,Flannel的VXLAN后端还支持DirectRouting模式,即在集群中的各节点上添加必要的路由信息,让Pod间的IP报文通过节点的二层网络直接传送。仅在通信双方的Pod对象所在的节点跨IP网络时,才启用传统的VXLAN隧道方式转发通信流量。若Kubernetes集群节点全部位于单个二层网络中,则DirectRouting模式下的Pod间通信流量基本接近于直接使用二层网络。即便节点分布在有限的几个可互相通信的网络中的Kubernetes集群来说,合理的应用部署拓扑也能省去相当一部分的隧道开销。

启用DirectRouting

修改configmaps/kube-flannel-cfg资源或者修改etcd键值/coreos.com/network/config,为VXLAN后端添加DirectRouting子键,并设置其值为true即可,如下面的配置示例。
net-conf.json: |
  {
     "Network": "10.244.0.0/16",
     "Backend": {
       "Type": "VxLAN",
       "Directrouting": true
      }
  }

DirectRouting 工作模型示意图

VXLAN 协议报文

VXLAN协议使用UDP报文封装隧道内层数据帧,Pod发出的报文经隧道入口flannel.1封装成数据帧,再由flanneld进程(客户端)封装成UDP报文,之后发往目标Pod对象所在节点的flanneld进程(服务端)。该UDP报文就是所谓的VXLAN隧道,它会在已经生成的帧报文之外再封装一组协议头部

host-gw  

即Host GateWay,它类似于VXLAN中的直接路由模式,但不支持跨网络的节点,因此这种方式强制要求各节点本身必须在同一个二层网络中,不太适用于较大的网络规模;host-gw有着较好的转发性能,且易于设定,推荐对报文转发性能要求较高的场景使用。
类型:

Type(string):host-gw

host-gw模型工作示意图

Flannel的host-gw后端通过添加必要的路由信息,并使用节点的二层网络直接发送Pod间的通信报文,其工作方式类似于VXLAN后端中的直接路由功能,但不包括该后端支持的隧道转发能力,这意味着host-gw后端要求各节点必须位于同一个二层网络中。因完全不会用到VXLAN隧道,所以使用了host-gw后端的Flannel网络也就无须用到VTEP设备flannel.1。

WireGuard

使用内核中的WireGuard对数据包进行封装和加密。
类型:

Type(string):wireguard
PSK(string):可选。要使用的预共享密钥。用于wg genpsk生成密钥。
ListenPort(int):可选。要侦听的 udp 端口。默认为51820.
ListenPortV6(int):可选。用于侦听 ipv6 的 udp 端口。默认为51821.
MTU(number):传出数据包所需的 MTU,如果未定义,则使用外部接口的 MTU。
Mode(string):可选。
  separate  - 对 ipv4 和 ipv6 使用单独的wireguard隧道(默认)
  auto - 用于两个地址族的单线防护隧道;自动确定首选对等地址
  ipv4 - 适用于两个地址系列的单线防护隧道;使用 ipv4 作为对等地址
  ipv6 - 适用于两个地址系列的单线防护隧道;使用 ipv6 作为对等地址
PersistentKeepaliveInterval(int):可选。默认值为 0(禁用)。
如果私钥写入之前没有生成私钥/run/flannel/wgkey。您可以使用环境WIREGUARD_KEY_FILE来更改此路径。

接口的静态名称是flannel-wg和flannel-wg-v6。WireGuard 等工具wg show可用于调试接口和对等点。

内核 < 5.6 的用户需要安装额外的 Wireguard 软件包。

udp

使用常规UDP报文封装完成隧道转发,性能较前两种方式低很多,它仅在不支持前两种后端的环境中使用;UDP后端模式中,flanneld监听UDP的8285端口发送的封装报文。
类型和选项:

Type(string):udp
Port(number):用于发送封装数据包的 UDP 端口。默认为 8285。

flannel 配置

如果 --kube-subnet-mgr 参数为 true,flannel 会从/etc/kube-flannel/net-conf.jso 读取其配置n。

如果 --kube-subnet-mgr 参数为 false,flannel 从 etcd 读取其配置。默认情况下,它将从/coreos.com/network/config读取配置(可以使用 覆盖--etcd-prefix)。

flannel配置基础

配置的值是一个包含以下键的 JSON 字典:

Network(string):用于整个 flannel 网络的 CIDR 格式的 IPv4 网络。(如果 EnableIPv4 为 true,则为强制项)

IPv6Network(string):用于整个 flannel 网络的 CIDR 格式的 IPv6 网络。(如果 EnableIPv6 为 true,则为强制项)

EnableIPv4(bool): 启用 ipv4 支持 默认为true

EnableIPv6(bool): 启用 ipv6 支持 默认为false

SubnetLen(integer):分配给每个主机的子网大小。默认为 24​​(即 /24),除非Network配置为小于 /22,在这种情况下它比网络小 2。

SubnetMin(string):子网分配应开始的 IP 范围的开头。默认为 的第二个子网Network。

SubnetMax(string):子网分配应结束的 IP 范围的末尾。默认为 的最后一个子网Network。

IPv6SubnetLen(integer):分配给每个主机的 ipv6 子网的大小。默认为 64(即 /64),除非Ipv6Network配置为小于 /62,在这种情况下它比网络小 2。

IPv6SubnetMin(string):子网分配应开始的 IPv6 范围的开头。默认为 的第二个子网Ipv6Network。

IPv6SubnetMax(string):子网分配应结束的 IPv6 范围的末尾。默认为 的最后一个子网Ipv6Network。

Backend(dictionary):要使用的后端类型以及该后端的特定配置。Backends中列出了可用后端的列表以及可以放入此字典中的键。默认为vxlan后端。
子网租用的持续时间为 24 小时。租约会在到期后 1 小时内续订,除非使用该选项--subnet-lease-renew-margin设置了不同的续订保证金。

配置upd后端示例

以下配置说明了大多数选项与udp后端的使用。
{
	"Network": "10.0.0.0/8",
	"SubnetLen": 20,
	"SubnetMin": "10.10.0.0",
	"SubnetMax": "10.99.0.0",
	"Backend": {
		"Type": "udp",
		"Port": 7890
	}
}

配置vxlan后端示例

Flannel项目官方给出的在线配置清单中默认使用的VXLAN后端,相关的配置定义ConfigMap资源kube-flannel-cfg中,配置内容如下所示。
net-conf.json: |
  {
    "Network": "10.244.0.0/16",
    "Backend": {
      "Type": "VxLAN"
      "Directrouting": true
     }
  }

配置hosts-gw后端示例

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

关键命令行选项

--public-ip="": IP accessible by other nodes for inter-host communication. Defaults to the IP of the interface being used for communication.
--etcd-endpoints=http://127.0.0.1:4001: a comma-delimited list of etcd endpoints.
--etcd-prefix=/coreos.com/network: etcd prefix.
--etcd-keyfile="": SSL key file used to secure etcd communication.
--etcd-certfile="": SSL certification file used to secure etcd communication.
--etcd-cafile="": SSL Certificate Authority file used to secure etcd communication.
--kube-subnet-mgr: Contact the Kubernetes API for subnet assignment instead of etcd.
--iface="": interface to use (IP or name) for inter-host communication. Defaults to the interface for the default route on the machine. This can be specified multiple times to check each option in order. Returns the first match found.
--iface-regex="": regex expression to match the first interface to use (IP or name) for inter-host communication. If unspecified, will default to the interface for the default route on the machine. This can be specified multiple times to check each regex in order. Returns the first match found. This option is superseded by the iface option and will only be used if nothing matches any option specified in the iface options.
--iface-can-reach="": detect interface to use (IP or name) for inter-host communication based on which will be used for provided IP. This is exactly the interface to use of command "ip route get <ip-address>" (example: --iface-can-reach=192.168.1.1 results the interface can be reached to 192.168.1.1 will be selected)
--iptables-resync=5: resync period for iptables rules, in seconds. Defaults to 5 seconds, if you see a large amount of contention for the iptables lock increasing this will probably help.
--subnet-file=/run/flannel/subnet.env: filename where env variables (subnet and MTU values) will be written to.
--net-config-path=/etc/kube-flannel/net-conf.json: path to the network configuration file to use
--subnet-lease-renew-margin=60: subnet lease renewal margin, in minutes.
--ip-masq=false: setup IP masquerade for traffic destined for outside the flannel network. Flannel assumes that the default policy is ACCEPT in the NAT POSTROUTING chain.
-v=0: log level for V logs. Set to 1 to see messages related to data path.
--healthz-ip="0.0.0.0": The IP address for healthz server to listen (default "0.0.0.0")
--healthz-port=0: The port for healthz server to listen(0 to disable)
--version: print version and exit

环境变量

上面概述的命令行选项也可以通过环境变量指定。例如--etcd-endpoints=http://10.0.0.2:2379相当于FLANNELD_ETCD_ENDPOINTS=http://10.0.0.2:2379环境变量。任何命令行选项都可以转换为环境变量,方法是在其前面加上 前缀FLANNELD_、去掉前导破折号、转换为大写并将所有其他破折号替换为下划线。

EVENT_QUEUE_DEPTH是另一个指示 kubernetes 规模的环境变量。设置EVENT_QUEUE_DEPTH以适应您的集群节点号。如果未设置,则默认值为 5000。

健康检查

Flannel 提供了健康检查 http 端点healthz。目前,当 flannel 运行时,此端点将返回 http 状态 ok(即 200)。该功能默认禁用。设置healthz-port为非零值将为 flannel 启用 healthz 服务器。

双栈

Flannel 支持双栈模式。这意味着 Pod 和服务可以同时使用 ipv4 和 ipv6。目前,仅 vxlan、wireguard 或 host-gw(linux) 后端支持双堆栈。
要求:

来自containernetworking/plugins的 flannel 二进制文件 v1.0.1
节点在主界面中必须有 ipv4 和 ipv6 地址
节点必须有 ipv4 和 ipv6 地址默认路由
vxlan 支持 ipv6 隧道需要内核版本 >= 3.12
配置:

/coreos.com/network/config在 kube-flannel-cfg ConfigMap 的 net-conf.json 或for中设置 "EnableIPv6": true 和 "IPv6Network",例如 "IPv6Network": * "2001:cafe:42:0::/56"等
如果一切按预期工作,flanneld 应该生成一个/run/flannel/subnet.env包含 IPV6 子网和网络的文件。例如:
FLANNEL_NETWORK=10.42.0.0/16
FLANNEL_SUBNET=10.42.0.1/24
FLANNEL_IPV6_NETWORK=2001:cafe:42::/56
FLANNEL_IPV6_SUBNET=2001:cafe:42::1/64
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

flannel 部署

注意事项

如果配置了防火墙,请确保启用所配置的后端使用的正确端口。
Flannel默认使用portmap作为CNI网络插件;在部署Flannel时,请确保CNI网络插件安装在/opt/CNI/bin中,可以使用以下命令下载最新的二进制文件:
mkdir -p /opt/cni/bin
curl -O -L https://github.com/containernetworking/plugins/releases/download/v1.2.0/cni-plugins-linux-amd64-v1.2.0.tgz
tar -C /opt/cni/bin -xzf cni-plugins-linux-amd64-v1.2.0.tgz

使用 kubectl 部署 Flannel

# kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
如果您使用自定义podCIDR(不是10.244.0.0/16),您首先需要下载上述清单并修改网络以匹配您的网络。

使用 helm 部署 Flannel

# Needs manual creation of namespace to avoid helm error
kubectl create ns kube-flannel
kubectl label --overwrite ns kube-flannel pod-security.kubernetes.io/enforce=privileged

helm repo add flannel https://flannel-io.github.io/flannel/
helm install flannel --set podCidr="10.244.0.0/16" --namespace kube-flannel flannel/flannel

flannel 版本升级

方法一:删除旧的资源定义并安装新的

优缺点

优点:管理 flannel 部署资源的最简洁方法,只要管理员/操作员没有创建其他资源,就不需要手动验证
缺点:版本更改期间集群内出现大规模网络中断

升级流程

1. 使用kubectl删除所有flannel资源

kubectl -n kube-flannel delete daemonset kube-flannel-ds
kubectl -n kube-flannel delete configmap kube-flannel-cfg
kubectl -n kube-flannel delete serviceaccount flannel
kubectl delete clusterrolebinding.rbac.authorization.k8s.io flannel
kubectl delete clusterrole.rbac.authorization.k8s.io flannel
kubectl delete namespace kube-flannel

2.安装较新版本的flannel并重启节点

方法二: On the fly version

优缺点

优点:改变flannel版本的破坏性较小,更容易做到

缺点:有些版本可能有无法替换的更改,可能需要清理和/或重命名资源,需要手动比较资源

升级流程

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

方法三: 使用 helm 存储库

从版本 0.21.4 开始,flannel 部署在 helm 存储库上,https://flannel-io.github.io/flannel/可以直接使用 helm 管理更新。
helm upgrade flannel --set podCidr="10.244.0.0/16" --namespace kube-flannel flannel/flannel

参考文档

https://github.com/flannel-io/flannel

posted @ 2023-08-15 11:16  小吉猫  阅读(1886)  评论(0编辑  收藏  举报