20

处理一次k8s、calico无法分配podIP的心路历程

 3 years ago
source link: http://college.creditease.cn/detail/389
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

又一次偷偷化解了可能发生的重大事故。不想看过程的可以直接跳到末尾看处理方案。

一个网络错误

某天,上kplcloud构建一个测试应用,构建完成之后发现新pod一直启动失败,并且抛出了以下错误信息:

Failed create pod sandbox: rpc error: code = Unknown desc = NetworkPlugin cni failed to set up pod "xxxxxx-fc4cb949f-gpkm2_xxxxxxx" network: netplugin failed but error parsing its diagnostic message "": unexpected end of JSON input

yqEVzei.jpg!mobile

会k8s的运维同学早已不在,突然出问题了怎么办?

试着开始解决问题。

一、有没有可能是镜像拉取失败,开始找问题:

  1. 登录集群所有服务器查看空间是否占满(然而并没有占满)

  2. 查询集群所有服务器网络情况(也没有问题)

  3. 再启一个pod试试?(起不来)

这就尴尬了......,有没有可能是calico的问题?

二、查看服务器报错信息

尝试以下命令看服务器的报错信息:

$ journalctl -exf

确实有一些错误信息:

qQ7vUzF.jpg!mobile

这个错误太广泛了,继续尝试从其他地方找找问题。

此时已经开始在思考如何跑路的问题了...

要不尝试从重启能否解决?

风险太大,不能冒险。虽然很多时候重启能解决大部分问题,但重起docker、k8s在这种情况下不是最佳选择。

ABNnmqY.jpg!mobile

继续搜刮日志,猜测是无法分配IP的问题,那目标转向calico

从calico-node上面找问题

查询ip池是否用完。

使用calicoamd命令查询calico是否正常正常运行

$ calicoctl get ippools -o wide
CIDR            NAT    IPIP
172.20.0.0/16   true   false
$ calicoctl node status

U7J3Ibj.jpg!mobile

似乎是没啥问题。

开始场外求助......

无果

FBrQnyF.jpg!mobile

既然calico-node都运行正常,应该不会是calico-etcd的问题吧。

试试calico-etcd

本着有疑问就查证试试的态度,下面开始对calico-etcd进行一顿骚操作。

为了减少代码量方便阅读,以下etcdctl所需要加的证书及endpoints,就不一一添加了,大家参考一下就好:

ETCDCTL_API=3 etcdctl --cacert=/etc/etcd/ssl/ca.pem \
--cert=/etc/etcd/ssl/etcd.pem \ 
--key=/etc/etcd/ssl/etcd-key.pem \  
--endpoints=http://10.xx.xx.1:2379,http://10.xx.xx.2:2379,http://10.xx.xx.3:2379

calico并没有问题,试试calico 所使用的 ETCD是否正常,进入calico-etcd集群:

$ ETCDCTL_API=3 etcdctl member list
bde98346d77cfa1: name=node-1 peerURLs=http://10.xx.xx.1:2380 clientURLs=http://10.xx.xx.1:2379 isLeader=true
299fcfbf514069ed: name=node-2 peerURLs=http://10.xx.xx.2:2380 clientURLs=http://10.xx.xx.2:2379 isLeader=false
954e5cdb2d25c491: name=node-3 peerURLs=http://10.xx.xx.3:2380 clientURLs=http://10.xx.xx.3:2379 isLeader=false

似乎集群也运行正常,get数据也正常。

一切看起来都感觉是多么的正常,似乎没有什么毛病。

算了,算了,还是先写会简历吧,换换脑子。

aM3mau.jpg!mobile

那尝试向ETCD写入一条数据试试?

$ ETCDCTL_API=3 etcdctl put /hello world
Error:  etcdserver: mvcc: database space exceeded

报了一个错 Error: etcdserver: mvcc: database space exceeded ???

fqUnmiR.jpg!mobile

似乎是找到原因了,既然定位到问题所在,那接下来就好办了。 (不用跑路了(⁎⁍̴̛ᴗ⁍̴̛⁎)) 把简历先放一放。

感谢伟大的google,我从etcd官网找到了一些线索及解决方案,后面我贴上官网介绍,先解决问题:

使用 etcdctl endpoint status 查询etcd各个节点的使用状态:

$ ETCDCTL_API=3 etcdctl endpoint status
http://10.xx.xx.1:2379, 299fcfbf514069ed, 3.2.18, 2.1 GB, false, 7, 8701663
http://10.xx.xx.2:2379, bde98346d77cfa1, 3.2.18, 2.1 GB, true, 7, 8701683
http://10.xx.xx.3:2379, 954e5cdb2d25c491, 3.2.18, 2.1 GB, false, 7, 8701687

上面可以看到集群空间已经使用了 2.1GB 了,这个值需要留意一下。

查询etcd是否有告警信息使用命令 etcdctl alarm list :

$ ETCDCTL_API=3 etcdctl alarm list
memberID:2999344297460918765 alarm:NOSPACE

显示了一个 alerm:NOSPACE ,这个表示没空间了,那是没什么空间呢?磁盘还是内存?先查询一下。

riQF7fn.jpg!mobile

似乎磁盘、内存空间都足够的。从官网的信息了解到应该是etcd配额的问题,Etcd v3 的默认的 backend quota 2GB,也就是说etcd默认最大的配额是2GB,如果超过了则无法再写入数据,要么把旧数据删除,要么把数据压缩了。

参考官方的解决方案

ETCD官网参考: https://etcd.io/docs/v3.2.17/op-guide/maintenance/

  1. 获取etcd的旧版本号

    $ ETCDCTL_API=3 etcdctl endpoint status --write-out="json" | egrep -o '"revision":[0-9]*' | egrep -o '[0-9].*'
    	5395771
    	5395771
    	5395771
  2. 压缩旧版本

    $ ETCDCTL_API=3 etcdctl compact 5395771
    	compacted revision 5395771
  3. 整理碎片

    $ ETCDCTL_API=3 etcdctl defrag
    	Finished defragmenting etcd member[http://10.xx.xx.1:2379]
    	Finished defragmenting etcd member[http://10.xx.xx.2:2379]
    	Finished defragmenting etcd member[http://10.xx.xx.3:2379]
  4. 关闭告警

    $ ETCDCTL_API=3 etcdctl alarm disarm
    	memberID:2999344297460918765 alarm:NOSPACE
    	
    	$ ETCDCTL_API=3 etcdctl alarm list
  5. 测试数据是否可写入

    $ ETCDCTL_API=3 etcdctl put /hello world
    	OK
    	
    	$ ETCDCTL_API=3 etcdctl get /hello
    	OK

回到k8s这边,删除那个失败的pod,并查看是否可正常分配ip。

一切正确,完美。

FVZ7ze6.jpg!mobile

为了避免后续再出现类似问题,需要设置自动压缩,启动自动压缩功能需要在etcd启动参考上加上 xxxxx=1

https://skyao.gitbooks.io/learning-etcd3/content/documentation/op-guide/maintenance.html

eaeyAby.jpg!mobile

etcd 默认不会自动 compact,需要设置启动参数,或者通过命令进行compact,如果变更频繁建议设置,否则会导致空间和内存的浪费以及错误。Etcd v3 的默认的 backend quota 2GB,如果不 compact,boltdb 文件大小超过这个限制后,就会报错: ”Error: etcdserver: mvcc: database space exceeded” ,导致数据无法写入。

产生这么多垃圾数据的原因就是因为频繁的调度,我们集群有大量CronJob在执行,并且执行的非常活跃,每次产生新的Pod都会被分配到ip。有可能是因为pod时间太短或没有及时注销而导致calico-etcd产生了大量垃圾数据。

尾巴

mMZVjyf.jpg!mobile

因calico-etcd集群的的使用配额满了,在创建pod时calico所分配的IP无法写入到etcd里,从而倒致pod创建失败也就无法注册到CoreDNS了。

为了不采坑,监控是非常重要的,我们有etcd集群的监控,却忽略了etcd配额的监控,幸运的是当时并没有应用重启动或升级,没有造成损失。

最后的建议就是,没事上去点点,说不定会有您意想不到的惊喜(惊吓)。

VRnyMbV.jpg!mobile

3ErmAvF.jpg!mobile

作者:宜信技术学院 王聪


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK