處理一次k8s、calico無法分配podIP的心路歷程

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

一個網絡錯誤

某天,上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

會k8s的運維同學早已不在,突然出問題了怎麼辦?

試着開始解決問題。

一、有沒有可能是鏡像拉取失敗,開始找問題:

  1. 登錄集羣所有服務器查看空間是否佔滿(然而並沒有佔滿)
  2. 查詢集羣所有服務器網絡情況(也沒有問題)
  3. 再啓一個pod試試?(起不來)

這就尷尬了......,有沒有可能是calico的問題?

二、查看服務器報錯信息

嘗試以下命令看服務器的報錯信息:

$ journalctl -exf 

確實有一些錯誤信息:

這個錯誤太廣泛了,繼續嘗試從其他地方找找問題。

此時已經開始在思考如何跑路的問題了...

要不嘗試從重啓能否解決?

風險太大,不能冒險。雖然很多時候重啓能解決大部分問題,但重啓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

本着有疑問就查證試試的態度,下面開始對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/

  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。

一切正確,完美。

爲了避免後續再出現類似問題,需要設置自動壓縮,啓動自動壓縮功能需要在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配額的監控,幸運的是當時並沒有應用重啓動或升級,沒有造成損失。

最後的建議就是,沒事上去點點,說不定會有您意想不到的驚喜(驚嚇)。

作者:宜信技術學院 王聰

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章