基于Kubeadm的Flannel分析

栏目: 编程工具 · 发布时间: 7年前

内容简介:Flannel概述值得探讨的是,flannel的这个overlay网络支持多种后端实现,除上图中的UDP,还有VXLAN和host-gw等。此外,flannel支持通过两种模式来维护隧道端点上FDB的信息,其中一种是通过连接Etcd来实现,另外一种是直接对接K8S,通过K8S添加删除Node来触发更新。

Flannel概述

Flannel是将多个不同子网(基于主机Node)通过被Flannel维护的Overlay网络拼接成为一张大网来实现互联的,通过官方的一张网络拓扑图我们可以对其基本原理一目了然:

基于Kubeadm的Flannel分析

值得探讨的是,flannel的这个overlay网络支持多种后端实现,除上图中的UDP,还有VXLAN和host-gw等。此外,flannel支持通过两种模式来维护隧道端点上FDB的信息,其中一种是通过连接Etcd来实现,另外一种是直接对接K8S,通过K8S添加删除Node来触发更新。

Flannel部署常见问题

1. Node状态显示为“NotReady”

我的K8S环境使用kubeadm来容器化运行K8S的各个组件(除kubelet直接运行在裸机上外),当我使用kubeadm join命令加入新的Minion Node到K8S集群中后,通过kubectl get node会发现所有的node都还是not ready状态,这是因为还没有配置好flannel网络。

2. 使用kube-flannel.yml无法创建DaemonSet

我使用的是K8S的1.6.4的版本,然后按照官方的说明,使用kube-flannel.yml来创建flannel deamon set,结果始终报错。正确的姿势是先使用kube-flannel-rbac.yml来创建flannel的ClusterRole并授权。该yml的主要作用是创建名叫flannel的ClusterRole,然后将该ClusterRole与ServiceAccount(flannel)绑定。接下来,当我们使用kube-flannel.yml来创建flannel daemon set的时候,该daemon set明确指定其Pod的ServiceAccount为flannel,于是通过它启动起来的Pod就具有了flannel ClusterRole中指定的权限。

3.flannel Pod状态为Running,网络不通

我之前在我的Mac Pro上跑了三个VM,为了能够访问公网拉取镜像,我为每个VM分配了一张网卡使用NAT模式,其分配到的IP地址可能重启后发生变化。另外,为了我本机方便管理,我为每台VM又分配了一张网卡使用Host-Only网络模式,每个网卡都有一个固定的IP地址方便SSH。然后,奇怪的事情就这样发生了….

原因在与在kube-flannel.yml中,kube-flannel容器的command被指定为:

command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr"]

可见,其并没有指定使用哪一张网卡作为flanneld对外通信的物理网卡,于是,可能由于机器上面路由配置的差异,导致三台机器并没有一致通过Host-Only网络模式的网卡来打通Overlay网络。遇到这种情况,如果几台机器的配置一致,可以手动修改kube-flannel.yml文件中kube-flannel的command的值,添加参数–iface=ethX,这里的ethX就为我们希望flanneld通信使用的网卡名称。

4.flannel启动异常,显示install-cni错误

这个现象比较坑,遇到这种情况的第一反应就是去查看install-cni容器到底做了什么。我们打开kube-flannel.yml可以看到,该容器的command字段只有简单的一行Shell:

command: [ "/bin/sh", "-c", "set -e -x; cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/10-flannel.conf; while true; do sleep 3600; done" ]

也就是将镜像中做好的cni-conf.json拷贝到cni的netconf目录下。由于容器的/etc/cni/net.d是挂载主机的对应的目录,所以该操作主要目的是为CNI准备flannel环境,便于启动容器的时候正确从netconf目录中加载到flannel,从而使用flannel网络。

我发现进入主机的netconf目录中能够看到10-flannel.conf:

#ls /etc/cni/net.d/10-flannel.conf
/etc/cni/net.d/10-flannel.conf
# cat /etc/cni/net.d/10-flannel.conf
cat: /etc/cni/net.d/10-flannel.conf: No such file or directory

无法打出其内容,而且文件显示为红色,说明其内容并没有正确从容器中拷贝过来。

之前我怀疑该异常是因为kubelet所带的文件系统参数为systemd,而 docker 的文件系统参数为cgroupfs所致,结果发现并非如此。当前能够绕开该异常的workaround为手动进入到主机的netconf目录,创建10-flannel.conf目录,并写入以下数据:

{
"name": "cbr0",
 "type": "flannel",
 "delegate": {
 "isDefaultGateway": true
 }
}

5.flannel网络启动正常,能够创建pod,但是网络不通

出现该现象一般会想到debug,而debug的思路当然是基于官方的那张网络拓扑图。比如在我的机器上,通过参看网卡IP地址有如下信息:

6: flannel.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN
link/ether 22:a0:ce:3c:bf:1f brd ff:ff:ff:ff:ff:ff
 inet 10.244.1.0/32 scope global flannel.1
valid_lft forever preferred_lft forever
inet 10.244.2.0/32 scope global flannel.1
valid_lft forever preferred_lft forever
7:cni0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1450 qdisc noqueue state DOWN qlen 1000
 link/ether 0a:58:0a:f4:01:01 brd ff:ff:ff:ff:ff:ff
inet 10.244.1.1/24 scope global cni0
valid_lft forever preferred_lft forever
inet6 fe80::4cb6:7fff:fedb:2106/64 scope link
valid_lft forever preferred_lft forever

很明显,cni0为10.244.1.1/24网段,说明该主机应该位于10.244.1.0/16子网内;但是我们看flannel.1网卡,确有两个IP地址,分别为于两个不同的”/16”子网。所以,可以肯定的是,我们一定是在该太主机上部署了多次kubeadm,而kubeadm reset并不会清理flannel创建的flannel.1和cni0接口,这就导致环境上遗留下了上一次部署分配到的IP地址。这些IP地址会导致IP地址冲突,子网混乱,网络通信异常。

解决的方法就是每次执行kubeadm reset的时候,手动执行以下命令来清楚对应的残余网卡信息:

ip link del cni0
ip link del flannel.1

K8S如何使用Flannel网络

Flannel打通Overlay网络

当使用kubeadm来部署k8s,网络组件(如flannel)是通过Add-ons的方式来部署的。我们使用这个yml文件来部署的flannel网络。

我截除了关键的一段内容(containers spec):

containers:
- name: kube-flannel
image: quay.io/coreos/flannel:v0.7.1-amd64
command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ]
securityContext:
privileged: true
env:
- name: POD_NAME
valueFrom:
fieldRef:
 fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
 fieldPath: metadata.namespace
 volumeMounts:
- name: run
mountPath: /run
- name: flannel-cfg
mountPath: /etc/kube-flannel/
 - name: install-cni
image: quay.io/coreos/flannel:v0.7.1-amd64
 command: [ "/bin/sh", "-c", "set -e -x; cp -f /etc/kube-flannel/cni-conf.json /etc/cni/net.d/10-flannel.conf; while true; do sleep 3600; done" ]
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
 mountPath: /etc/kube-flannel/

通过分析该yaml文件可以知道:该pod内有两个container,分别为install-cni和 kube-flannel。

  • install-cni

主要负责将config-map中适用于该flannel的CNI netconf配置拷贝到主机的CNI netconf 路径下,从而使得K8S在创建pod的时候可以遵照标准的CNI流程挂载网卡。

  • kube-flannel

主要启动flanneld,该command中为flanneld的启动指定了两个参数: –ip-masq, –kube-subnet-mgr。第一个参数–ip-masq代表需要为其配置SNAT;第二个参数–kube-subnet-mgr代表其使用kube类型的subnet-manager。该类型有别于使用etcd的local-subnet-mgr类型,使用kube类型后,flannel上各Node的IP子网分配均基于K8S Node的spec.podCIDR属性。可以参考下图的方式来查看(该示例中,k8s为node-1节点分配的podCIDR为:10.244.8.0/24):

#kubectl edit node node-1

apiVersion: v1
kind: Node
 ...
name: dev-1
resourceVersion: "2452057"
selfLink: /api/v1/nodesdev-1
uid: 31f6e4c3-57b6-11e7-a0a5-00163e122a49
spec:
 externalID: dev-1
podCIDR: 10.244.8.0/24

另外,flannel的subnet-manager通过监测K8S的node变化来维护了一张路由表,这张表里面描述了要到达某个Pod子网需要先到达哪个EndPoint。

CNI挂载容器到隧道端点

如果说flannel为Pod打通了一张跨node的大网,那么CNI就是将各个终端Pod挂载到这张大网上的安装工人。

在刚部署好flannel网络并未在该Node上启动任何Pod时,通过ip link我们只能够看到flannel.1这张网卡,却无法看到cni0。难道是flannel网络运行异常吗?我们接下来就来分析flannel的CNI实现原理,就知道答案了。

通过传统方式来部署flannel都需要通过脚本来修改dockerd的参数,从而使得通过docker创建的容器能够挂载到指定的网桥上。但是flannel的CNI实现并没有采用这种方式。通过分析CNI代码,

我们可以了解flannel CNI的流程:

  • 读取netconf配置文件,并加载/run/flannel/subnet.env环境变量信息。
  • 基于加载的信息,生成适用于其delegate的ipam和CNI bridge的netconf文件;其中指定ipam使用host-local,CNI bridge type为bridge。
  • 调用deletgate(CNI bridge type)对应的二进制文件来挂载容器到网桥上。

这里的环境变量文件/run/flannel/subnet.env是由flanneld生成的,里面包含了该主机所能够使用的IP子网网段,具体内容如下:

# cat /run/flannel/subnet.env
FLANNEL_NETWORK=10.244.0.0/16
FLANNEL_SUBNET=10.244.8.1/24
FLANNEL_MTU=1450
FLANNEL_IPMASQ=true

这些数据生成ipam的配置文件的依据,另外,flannel CNI插件的代码中,默认指定delegate为bridge:

if !hasKey(n.Delegate, "type") {
 n.Delegate["type"] = "bridge"
}

所以,当flannel CNI插件调用delegate,本质上就是调用bridge CNI插件来将容器挂载到网桥上。分析bridge CNI 插件的过程我们可以看到其指定了默认网桥名称为cni0:

const defaultBrName = "cni0"

func loadNetConf(bytes []byte) (*NetConf, error) {
n := &NetConf{
 BrName: defaultBrName,
 }
 ...
 return n, nil
}

因此,现在我们可以将整个流程连起来了:flannel CNI插件首先读取netconf配置和subnet.env信息,生成适用于bridge CNI插件的netconf文件和ipam(host-local)配置,并设置其delegate为bridge CNI插件。然后调用走bridge CNI插件挂载容器到bridge的流程。由于各个Pod的IP地址分配是基于host-local的Ipam,因此整个流程完全是分布式的,不会对API-Server造成太大的负担。

至此,基于kubeadm的flannel分析就大致结束了,希望对您有帮助!

来源: https://www.kubernetes.org.cn/2270.html


以上所述就是小编给大家介绍的《基于Kubeadm的Flannel分析》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Pro HTML5 and CSS3 Design Patterns

Pro HTML5 and CSS3 Design Patterns

Michael Bowers / Apress / 2011-11-15 / GBP 35.50

Pro HTML5 and CSS3 Design Patterns is a reference book and a cookbook on how to style web pages using CSS3 and HTML5. It contains 350 ready--to--use patterns (CSS3 and HTML5 code snippets) that you ca......一起来看看 《Pro HTML5 and CSS3 Design Patterns》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换