k8s(十六): VXLAN和Flannel

本文深入探讨了 Flannel 的 VXLAN 工作模式,详细解释了 VXLAN 解决方案如何克服传统二层网络的限制,以及 Flannel 在容器网络环境中如何利用 VXLAN 实现高效的数据通信。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

目前k8s中比较常用的cni有calico、flannel、kube-router等,个人比较熟悉的是kube-router/calico的bgp纯直通方案,flannel则是另一款使用较多的比较简单易用的方案,这里着重了解一下flannel的vxlan这一常用模式

VXLAN

在了解flannel之前,有必要掌握vxlan的基础知识。首先来看看vxlan协议的报文封装格式:
在这里插入图片描述

说明:

vxlan,给数据中心大二层网络使用,何为大二层,又为何需要vxlan?

1.vlan数量有限

vlan的tag位一个4个字节,其中12bit是给vlan id使用,也即是一共有4096个vlan id支持,在大型数据中心中不够用,但这个问题其实QinQ(IEEE 802.1 ad)标准可以解决,重点原因是因为第二点

2.mac地址表限制

虚拟化/容器化场景下,一台物理机内部有众多虚拟网卡,而外部的二层设备(交换机)是将mac地址都缓存入内存中的,且交换机内存空间一般较小,在虚拟化的数据中心中,如果mac表满了,会出现大量的广播泛洪,造成
极大的网络资源和计算资源的浪费

3.灵活部署限制

如果虚机和物理机之间使用桥接网络,那么虚拟机则同样受物理机网络的限制,只能使用那一个vlan的地址,不同vlan下的虚机受制于vlan无法顺畅的进行互相迁移,容易主机的资源利用率的不均衡。虽然可以通过物理机与交换设备全部通过trunk的方式连接来解决vlan切换这个问题,但是这样无疑会形成一个巨大的传统二层网络空间,相应的BUM(Broadcast,Unknown Unicast,Multicast)风暴和交换机MAC地址表的问题也会随之产生,这是无法接受的。

那么vxlan是怎么解决上面几个问题的呢?

从上面的报文封装图可以看出,vxlan外层(二层头部、三层头部)继续沿用现有标准,只是在传输层,使用了udp封装,udp封装之内,就是vxlan的协议封装。VXLAN Tunnel EndPoint(简称VTE, 是指支持vxlan封装、拆包的交换设备,一般可理解为承载着虚拟机的物理机),通过vxlan header内部封装的信息,拆包后直接将original layer 2 frame数据,转发给相应的虚拟网卡。

如此,在外部的网络设备层面,vxlan保持着传统的通信方式,即各个VTE之间以UDP的方式互相通信;而在VTE层面,则通过报文封装,实现了内部众多的虚拟网卡mac地址之间的数据交换:
其一,24bit的VNID标识,实现了1600多万个不同二层子网的区分;
其二,通过报文封装的格式,
其三,通过VXLAN的封装,实现了虚拟网卡之间越过传统三层网络,以特殊的二层数据帧交换的方式通信,走的是一套独立于物理网络(underlay network)的overlay network,在物理网络上可以保持不变,但是同时,虚拟机的部署和迁移,又不用受物理网络的限制,有利于物理资源利用率维持均衡

以上也就是为什么vxlan又称为虚拟大二层网络,有了以上基础铺垫,下面来简述一下flannel 的vxlan实现的工作具体流程。

Flannel

按照惯例,先上流程图:

在这里插入图片描述

步骤详解:
源端:

1)源容器veth0向目标容器发送数据,根据容器内的默认路由,数据首先发送给宿主机的docker0网桥
2)宿主机docker0网桥接受到数据后,宿主机查询路由表,pod相关的路由都是交由flannel.1网卡,因此,将其转发给flannel.1虚拟网卡处理
3)flannel.1接受到数据后,查询etcd数据库,获取目标pod网段对应的目标宿主机地址、目标宿主机的flannel网卡的mac地址、vxlan vnid等信息。然后对数据进行udp封装如下:
udp头封装:
source port 8285,target port 8285
udp内部封装:
1.vxlan封装:vxlan vnid等信息
2. original layer 2 frame封装:source {源 flannel.1网卡mac地址} target{目标flannel.1网卡的mac地址}
完成以上udp封装后,将数据转发给物理机的eth0网卡

4)宿主机eth0接收到来自flannel.1的udp包,还需要将其封装成正常的通信用的数据包,为它加上通用的ip头、二层头,这项工作在由linux内核来完成。
Ethernet Header的信息:
source:{源宿主机机网卡的MAC地址}
target:{目标宿主机网卡的MAC地址}
IP Header的信息:
source:{源宿主机网卡的IP地址}
target:{目标宿主机网卡的IP地址}
通过此次封装,一个真正可用的数据包就封装完成,可以通过物理网络传输了。

目标端:

5)目标宿主机的eth0接收到数据后,对数据包进行拆封,拆到udp层后,将其转发给8285端口的flannel进程
6)目标宿主机端flannel拆除udp头、vxlan头,获取到内部的原始数据帧,在原始数据帧内部,解析出源容器ip、目标容器ip,重新封装成通用的数据包,查询路由表,转发给docker0网桥;
7)最后,docker0网桥将数据送达目标容器内的veth0网卡,完成容器之间的数据通信。

总结:

通过对vxlan设计思想和flannel的落地方案的互相印证,对这两者会有更为深刻的理解,同时,不难发现,flannel性能表现不佳的原因很可能是因为反复拆封包过程、etcd查询这几个步骤带来的额外开销。

参考:

https://blog.youkuaiyun.com/u010039418/article/details/90451081
https://www.cnblogs.com/cwind/p/10085146.html
https://events.static.linuxfound.org/sites/events/files/slides/2013-linuxcon.pdf

--- kind: Namespace apiVersion: v1 metadata: name: kube-flannel labels: k8s-app: flannel pod-security.kubernetes.io/enforce: privileged --- kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: k8s-app: flannel name: flannel rules: - apiGroups: - "" resources: - pods verbs: - get - apiGroups: - "" resources: - nodes verbs: - get - list - watch - apiGroups: - "" resources: - nodes/status verbs: - patch --- kind: ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: labels: k8s-app: flannel name: flannel roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: flannel subjects: - kind: ServiceAccount name: flannel namespace: kube-flannel --- apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: flannel name: flannel namespace: kube-flannel --- kind: ConfigMap apiVersion: v1 metadata: name: kube-flannel-cfg namespace: kube-flannel labels: tier: node k8s-app: flannel app: flannel data: cni-conf.json: | { "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] } net-conf.json: | { "Network": "10.244.0.0/16", "EnableNFTables": false, "Backend": { "Type": "vxlan" } } --- apiVersion: apps/v1 kind: DaemonSet metadata: name: kube-flannel-ds namespace: kube-flannel labels: tier: node app: flannel k8s-app: flannel spec: selector: matchLabels: app: flannel template: metadata: labels: tier: node app: flannel spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/os operator: In values: - linux hostNetwork: true priorityClassName: system-node-critical tolerations: - operator: Exists effect: NoSchedule serviceAccountName: flannel initContainers: - name: install-cni-plugin image: ghcr.io/flannel-io/flannel-cni-plugin:v1.7.1-flannel1 command: - cp args: - -f - /flannel - /opt/cni/bin/flannel volumeMounts: - name: cni-plugin mountPath: /opt/cni/bin - name: install-cni image: ghcr.io/flannel-io/flannel:v0.27.0 command: - cp args: - -f - /etc/kube-flannel/cni-conf.json - /etc/cni/net.d/10-flannel.conflist volumeMounts: - name: cni mountPath: /etc/cni/net.d - name: flannel-cfg mountPath: /etc/kube-flannel/ containers: - name: kube-flannel image: ghcr.io/flannel-io/flannel:v0.27.0 command: - /opt/bin/flanneld args: - --ip-masq - --kube-subnet-mgr resources: requests: cpu: "100m" memory: "50Mi" securityContext: privileged: false capabilities: add: ["NET_ADMIN", "NET_RAW"] env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: EVENT_QUEUE_DEPTH value: "5000" - name: CONT_WHEN_CACHE_NOT_READY value: "false" volumeMounts: - name: run mountPath: /run/flannel - name: flannel-cfg mountPath: /etc/kube-flannel/ - name: xtables-lock mountPath: /run/xtables.lock volumes: - name: run hostPath: path: /run/flannel - name: cni-plugin hostPath: path: /opt/cni/bin - name: cni hostPath: path: /etc/cni/net.d - name: flannel-cfg configMap: name: kube-flannel-cfg - name: xtables-lock hostPath: path: /run/xtables.lock type: FileOrCreate
最新发布
07-01
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值