在部署kubernetes的时候,遇到了不少奇奇怪怪的calico问题,决定汇总成一篇文章,形成有效的知识点供网友们解决问题。
关于Calico 和Flannel的选择
Calico和Flannel都属于容器网络接口。我个人推荐Calico,因为它有的Flannel未必有,Flannel有的它都有。记不太清Calico是从3.8还是3.9开始不再依赖Etcd,而是改用API读取信息,省了etcd密钥生成。
如果你在体验了Calico或Flannel任意一款后,突然想体验另一款,需要特别注意这个想法的危害性。
我曾经在体验Calico3.8、3.10.1时遇到一个BDIR的bug(提问在segmentfault,几乎无解),折腾1天后无奈转战Flannel了,还是不行。又回来折腾Colica3.9.2。
发现calico-node-都是 0/1 Ready,输出 BIRD is not ready: BGP not established with 172.16.*.*。 IP都是正确的服务器内网IP,卸载了多余的network interface ,改了IP_AUTODETECTION_METHOD
都不行。很迷……
那一天来来去去能调试的就3条命令:
vim calico.yaml
kubectl apply -f calico.yaml
kubectl get pods -o wide -n kube-system
当然还有一些:calicoctl
tcpdump -i
journalctl -u kubelet -n 1000
等等,反复的查看详细情况。
非常头疼。把全Google的搜索结果和各种报文、各种日志看了个遍,依然没有一丝有用的线索。我当时的iptables已经长到令人发指,而grep
出来的信息也几乎没有用处。
重装也许是唯一的出路
最终我只得放弃已经有了gitlab-runner和helm部署好的一些在线应用,master和wokers都执行:
# 重置kubeadm
kubeadm reset -f
# 清空iptables规则
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
# 重启
reboot
如果你是通过SSH连接服务器,你会掉线并且无法完整执行这4个命令,你可以用tmux
执行,重启后20端口默认会重新开放。
在清空了iptables规则,重启后执行kubeadm init
,紧接着就可以装calico了,忐忑的内心等待着结果,5 4 3 2 1,calico-controller和master的calico-node-都没有报错,启动正常!
然后赶紧让wokers 加入。node1加入成功,node2加入后describe pod
看到一个错误Event:
unable to connect to BIRDv4 socket: dial unix /var/run/bird/bird.ctl: connect
进一步查看容器的日志 kubectl -n kube-system log calico-node-
,在容器启动之初有Warning:
calico int_dataplane.go 357: Failed to query VXLAN device error=Link not found
GG了一下,看见一个issue里提到:这是一个没有使用的服务被检测而报出的warning。
我在问题的最后进行了中文补充(嘻嘻),其实这个问题在kubeadm init
时,就已经提示过,只是输出最后是成功,大家就容易忽略最初的关键信息:
[init] Using Kubernetes version: v1.16.3
[preflight] Running pre-flight checks
[WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/
[preflight] Pulling images required for setting up a Kubernetes cluster
这是因为kubeadm init
在集群初始化时会检测到master主机安装的docker驱动程序是cgroupfs
,而kubeadm需要系统化驱动。所以我们要告诉kubele
在使用docker驱动时改为systemd
。这同时也是提醒我们其他主机也存在这样的问题,因为我们准备集群服务器的时候往往是在同一时期。
因此我们需要在所有的服务器上,创建个文件vim /etc/default/kubele
供kubele识别为cgroup驱动。文件内容如下 :
Environment=KUBELET_EXTRA_ARGS=--cgroup-driver=systemd
删除node2 的pod calico-node-
过一会儿看看,应该就好了。
卸载Flannel network interface
Flannel的network interface对于Calico的安装有一定程度的影响,在kubectl delete -f flannel.yaml
后并不会主动清楚,所以需要手动执行以下命令:
ifconfig cni0 down
ip link delete cni0
ifconfig flannel.1 down
ip link delete flannel.1
rm -rf /var/lib/cni/
rm -f /etc/cni/net.d/*
systemctl restart kubelet
推荐安装calicoctl
在master服务器上安装calicoctl
,它会使用KUBECONFIG
这个环境变量调用kubectl
证书,执行 export KUBECONFIG=~/.kube/config
。
calicoctl
可以读取到集群中的网络信息,方便调试与排错。
Calico 1/1 ready bug
Calico v3.8.*都有一个通版本的bug,那就是明明启动失败,get pods
还是显示1/1 ready,建议更换版本到3.9以上。
Calico BIRD is not ready: BGP not established
这个问题几乎每个人都会遇到。因为官方的step by step太傻白甜,没有把IP_AUTODETECTION_METHOD
这个IP检测方法的参数放入calico.yaml
中,calico会使用第一个找到的network interface(往往是错误的interface),导致Calico把master也算进nodes,于是master BGP启动失败,而其他workers则启动成功。
网上有很多调试方式和方法,这里我节省大家的时间,把最佳做法提供给大家。
首先通过内网IP确认你的有效network interface,在这里我是eth0
:
➜ run ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255
ether 02:42:74:9d:e2:02 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.106.121 netmask 255.255.240.0 broadcast 172.17.111.255
inet6 fe80::216:3eff:fe2e:ebaf prefixlen 64 scopeid 0x20<link>
ether 00:16:3e:2e:eb:af txqueuelen 1000 (Ethernet)
RX packets 953994 bytes 917123050 (874.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 366496 bytes 171534061 (163.5 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1 (Local Loopback)
RX packets 87353 bytes 116021075 (110.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 87353 bytes 116021075 (110.6 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tunl0: flags=193<UP,RUNNING,NOARP> mtu 1440
inet 10.100.36.64 netmask 255.255.255.255
tunnel txqueuelen 1 (IPIP Tunnel)
RX packets 2812 bytes 465293 (454.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2812 bytes 243545 (237.8 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
编辑calico.yaml
找到name: IP
,在它上面写入:
- name: CLUSTER_TYPE
value: "k8s,bgp"
# 新增部分
- name: IP_AUTODETECTION_METHOD
value: "interface=eth0"
# value: "interface=eth.*"
# value: "interface=can-reach=www.baidu.com"
# 新增部分结束
- name: IP
value: "autodetect"
- name: CALICO_IPV4POOL_IPIP
value: "Always"
在注释中还有2个写法,
eth.*
这个写法是GoLang的正则,它可以匹配到eth0、eth1等。can-reach
将用第一个可以识别这个地址的network interface。IP和IP_AUTODETECTION_METHOD是互斥关系。
如果是多次执行过kubectl apply -f calico.yaml
的主机,还应该清理cni文件:
rm -rf /var/lib/cni
kubectl apply -f calico.yaml
error looking up service account kube-system/calico-node: serviceaccount “calico-node” not found
这个错误一般是由于yaml配置文件与版本不匹配,里面ClustRole的权限不对。解决办法是去官网下一份正确的yaml文件。
firewall or iptable?
这是一道送分题。
我喜欢Firewall,不喜欢Iptables,它只会伤害我的眼睛……但是calico 、 flannel、 kube-proxy、kubele都推荐使用iptables,so …
#查看防火墙状态
systemctl status firewalld.service
#关闭firewall
systemctl stop firewalld.service
#禁止firewall随系统启动
systemctl disable firewalld.service
发表回复