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

又一次偷偷化解了可能發生的重大事故。不想看過程的能夠直接跳到末尾看處理方案。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、calico沒法分配podIP的心路歷程

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

試着開始解決問題。docker

1、有沒有多是鏡像拉取失敗,開始找問題:

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

這就尷尬了......,有沒有多是calico的問題?json

2、查看服務器報錯信息

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

$ journalctl -exf

確實有一些錯誤信息:網絡

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

這個錯誤太普遍了,繼續嘗試從其餘地方找找問題。mvc

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

要不嘗試從重啓可否解決? ide

風險太大,不能冒險。雖然不少時候重啓能解決大部分問題,但重啓docker、k8s在這種狀況下不是最佳選擇。

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

繼續搜刮日誌,猜想是沒法分配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

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

彷佛是沒啥問題。

開始場外求助......

無果

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

既然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數據也正常。

一切看起來都感受是多麼的正常,彷佛沒有什麼毛病。

算了,算了,仍是先寫會簡歷吧,換換腦子。

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

那嘗試向ETCD寫入一條數據試試?

$ ETCDCTL_API=3 etcdctl put /hello world

Error:  etcdserver: mvcc: database space exceeded

報了一個錯Error: etcdserver: mvcc: database space exceeded???

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

彷佛是找到緣由了,既然定位到問題所在,那接下來就好辦了。(不用跑路了(⁎⁍̴̛ᴗ⁍̴̛⁎))把簡歷先放一放。

感謝偉大的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,這個表示沒空間了,那是沒什麼空間呢?磁盤仍是內存?先查詢一下。

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

彷佛磁盤、內存空間都足夠的。從官網的信息瞭解到應該是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。

一切正確,完美。

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

爲了不後續再出現相似問題,須要設置自動壓縮,啓動自動壓縮功能須要在etcd啓動參考上加上xxxxx=1

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

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

etcd 默認不會自動 compact,須要設置啓動參數,或者經過命令進行compact,若是變動頻繁建議設置,不然會致使空間和內存的浪費以及錯誤。Etcd v3 的默認的 backend quota 2GB,若是不 compact,boltdb 文件大小超過這個限制後,就會報錯:」Error: etcdserver: mvcc: database space exceeded」,致使數據沒法寫入。

產生這麼多垃圾數據的緣由就是由於頻繁的調度,咱們集羣有大量CronJob在執行,而且執行的很是活躍,每次產生新的Pod都會被分配到ip。有多是由於pod時間過短或沒有及時註銷而致使calico-etcd產生了大量垃圾數據。

尾巴

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

因calico-etcd集羣的的使用配額滿了,在建立pod時calico所分配的IP沒法寫入到etcd裏,從而致使pod建立失敗也就沒法註冊到CoreDNS了。

爲了避免採坑,監控是很是重要的,咱們有etcd集羣的監控,卻忽略了etcd配額的監控,幸運的是當時並無應用重啓動或升級,沒有形成損失。

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

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

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

 做者:宜信技術學院 王聰

相關文章
相關標籤/搜索