又一次偷偷化解了可能發生的重大事故。不想看過程的能夠直接跳到末尾看處理方案。html
某天,上kplcloud構建一個測試應用,構建完成以後發現新pod一直啓動失敗,而且拋出瞭如下錯誤信息:node
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
會k8s的運維同窗早已不在,忽然出問題了怎麼辦?git
試着開始解決問題。docker
這就尷尬了......,有沒有多是calico的問題?json
嘗試如下命令看服務器的報錯信息:服務器
$ journalctl -exf
確實有一些錯誤信息:網絡
這個錯誤太普遍了,繼續嘗試從其餘地方找找問題。mvc
此時已經開始在思考如何跑路的問題了...運維
要不嘗試從重啓可否解決? ide
風險太大,不能冒險。雖然不少時候重啓能解決大部分問題,但重啓docker、k8s在這種狀況下不是最佳選擇。
繼續搜刮日誌,猜想是沒法分配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
彷佛是沒啥問題。
開始場外求助......
無果
既然calico-node都運行正常,應該不會是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數據也正常。
一切看起來都感受是多麼的正常,彷佛沒有什麼毛病。
算了,算了,仍是先寫會簡歷吧,換換腦子。
那嘗試向ETCD寫入一條數據試試?
$ ETCDCTL_API=3 etcdctl put /hello world Error: etcdserver: mvcc: database space exceeded
報了一個錯Error: etcdserver: mvcc: database space exceeded???
彷佛是找到緣由了,既然定位到問題所在,那接下來就好辦了。(不用跑路了(⁎⁍̴̛ᴗ⁍̴̛⁎))把簡歷先放一放。
感謝偉大的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
,這個表示沒空間了,那是沒什麼空間呢?磁盤仍是內存?先查詢一下。
彷佛磁盤、內存空間都足夠的。從官網的信息瞭解到應該是etcd配額的問題,Etcd v3 的默認的 backend quota 2GB,也就是說etcd默認最大的配額是2GB,若是超過了則沒法再寫入數據,要麼把舊數據刪除,要麼把數據壓縮了。
參考官方的解決方案
ETCD官網參考:https://etcd.io/docs/v3.2.17/op-guide/maintenance/
獲取etcd的舊版本號
$ ETCDCTL_API=3 etcdctl endpoint status --write-out="json" | egrep -o '"revision":[0-9]*' | egrep -o '[0-9].*' 5395771 5395771 5395771
壓縮舊版本
$ ETCDCTL_API=3 etcdctl compact 5395771 compacted revision 5395771
整理碎片
$ 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]
關閉告警
$ ETCDCTL_API=3 etcdctl alarm disarm memberID:2999344297460918765 alarm:NOSPACE $ ETCDCTL_API=3 etcdctl alarm list
測試數據是否可寫入
$ ETCDCTL_API=3 etcdctl put /hello world OK $ ETCDCTL_API=3 etcdctl get /hello OK
回到k8s這邊,刪除那個失敗的pod,並查看是否可正常分配ip。
一切正確,完美。
爲了不後續再出現相似問題,須要設置自動壓縮,啓動自動壓縮功能須要在etcd啓動參考上加上xxxxx=1
https://skyao.gitbooks.io/learning-etcd3/content/documentation/op-guide/maintenance.html
etcd 默認不會自動 compact,須要設置啓動參數,或者經過命令進行compact,若是變動頻繁建議設置,不然會致使空間和內存的浪費以及錯誤。Etcd v3 的默認的 backend quota 2GB,若是不 compact,boltdb 文件大小超過這個限制後,就會報錯:
」Error: etcdserver: mvcc: database space exceeded」
,致使數據沒法寫入。
產生這麼多垃圾數據的緣由就是由於頻繁的調度,咱們集羣有大量CronJob在執行,而且執行的很是活躍,每次產生新的Pod都會被分配到ip。有多是由於pod時間過短或沒有及時註銷而致使calico-etcd產生了大量垃圾數據。
因calico-etcd集羣的的使用配額滿了,在建立pod時calico所分配的IP沒法寫入到etcd裏,從而致使pod建立失敗也就沒法註冊到CoreDNS了。
爲了避免採坑,監控是很是重要的,咱們有etcd集羣的監控,卻忽略了etcd配額的監控,幸運的是當時並無應用重啓動或升級,沒有形成損失。
最後的建議就是,沒事上去點點,說不定會有您意想不到的驚喜(驚嚇)。
做者:宜信技術學院 王聰