面向邊緣的輕量級K8S發行版k3s於去年2月底發佈後,備受關注,在發佈後的10個月時間裏,Github Star達11,000顆。於去年11月中旬已經GA。但正如你所知,沒有一個產品是十全十美的,k3s在客戶落地實踐的過程當中也暴露過一些不足。在k3s技術團隊的專業技術支持下,許多問題獲得了改善和解決。node
咱們精選了一些在實際生產環境中的問題處理案例,分享給正在使用k3s的你。但願k3s技術團隊的經驗可以爲你帶來參考,也但願你能夠參與進來和咱們一塊兒探索切磋。畢竟,尋找答案的路途永遠沒有終點。web
本文將分享k3s產品中關於node註冊失敗的排查記錄。api
k3s版本:v1.17.2+k3s1安全
k3s agent向server註冊時,日誌出現明顯報錯:websocket
同時,在k3s server上查詢node,也確實沒法獲取註冊的節點信息(只有一個server節點):socket
客戶的虛擬機環境使用某私有云,從反饋看有過VM反覆清理的操做,不過具體操做沒法完整復原。日誌
Agent註冊的過程是十分複雜的,總的來講有兩個目的:code
啓動kubelet等服務,鏈接到server節點上的api-server服務,這是k8s集羣必須的server
創建websocket tunnel,用於k3s的server和agent同步一些信息blog
咱們在註冊agent時只提供了server地址和node-token,agent是如何一步一步完成註冊的?首先看node-token的格式:
這裏的user和password會對應k3s api-server中basic auth的配置,k3s api-server啓動時會設置一個特殊的authentication方式就是basic auth,對應文件在server節點的/var/lib/rancher/k3s/server/cred/passwd中:
1a51f67d17af05b6f48357f46a9c6833,server,server,k3s:server 0050004354d29b565f4a8bf2faba769e,admin,admin,system:masters 1a51f67d17af05b6f48357f46a9c6833,node,node,k3s:agent
由此agent端經過解析node-token,能夠得到一個和k3s api-server通訊的受權,受權方式是basic auth。
瞭解node-token的做用,咱們就能夠解開agent註冊過程的序幕,參考下圖:
以黃色文本框順序爲例,前三步是爲了獲得啓動kubelet服務各類依賴信息,最後一步創建websocket通道。咱們能夠只關心前面三步,最重要的是api-server的地址,還有各類k8s組件通訊的tls證書,因爲那些證書是在server上籤發,因此agent須要經過一些API請求獲取,這些證書大體有:
/v1-k3s/serving-kubelet.crt /v1-k3s/client-kubelet.crt /v1-k3s/client-kube-proxy.crt /v1-k3s/client-k3s-controller.crt /v1-k3s/client-ca.crt /v1-k3s/server-ca.crt ...
這些證書中kubelet兩個證書最爲特殊,因爲kubelet在每一個節點都運行,因此安全須要咱們須要給每一個kubelet node都單獨簽發證書(node-name做爲簽發依據)。涉及到單獨簽發就須要驗證node信息是否合法,這時node-passwd就粉墨登場了。
這個過程大體是這樣的,agent先生成一個隨機passwd(/etc/rancher/node/password),並把node-name和node-passwd信息做爲證書請求的request header發給k3s server,因爲agent會向server申請兩個kubelet證書,因此會收到兩個帶有此header的請求。若是agent首次註冊,server收到第一個請求後,會把這個node-name和node-passwd解析出來存儲到/var/lib/rancher/k3s/server/cred/node-passwd中,收到第二個請求後會讀取node-passwd文件與header信息校驗,信息不一致則會403拒絕請求。若是agent重複註冊時,server會直接比對request header內容和本地信息,信息不一致也會403拒絕請求。
瞭解基本原理後,咱們再回到問題自己,agent在註冊時報出的錯誤日誌以下:
level=error msg="Node password rejected, duplicate hostname or contents of '/etc/rancher/node/password' may not match server nod e-passwd entry, try enabling a unique node name with the --with-node-id flag"
查找代碼出處,確實發現這是在申請kubelet證書時,k3s server返回的403致使的:
對比agent上的node-passwd(/etc/rancher/node/password)和server上的node-paswd:
# agent $ cat /etc/rancher/node/password 47211f28f469622cccf893071dbda698 $ hostname xxxxxxx # server cat /var/lib/rancher/k3s/server/cred/node-passwd 31567be88e5408a31cbd036fc9b37975,ip-172-31-13-54,ip-172-31-13-54, cf3f4f37042c05c631e07b0c0abc528f,xxxxx,xxxxxx,
Agent node對應的passwd和server中存儲的hostname對應的passwd不一致,按照咱們前面說的基本原理,就會出現403的錯誤日誌。
爲何會出現passwd不一致呢?正常來講若是用k3s-agent-uninstall.sh來清理安裝過的agent node,並不會刪除password文件(/etc/rancher/node/password),那麼問題極可能是VM重建或者手動操做刪除的這個文件。由於agent上刪除了password,agent再次註冊時會從新生成password,就致使了新的password和server上原先存儲的不一致。
解決辦法能夠有三種:
手動在agent上建立password,內容和server中存儲保持一致
修改了server中的原始內容,讓password和agent上新生成的保持一致
能夠試試agent註冊時使用--with-node-id,這樣server中認爲這徹底是新node,不會用原始信息比對
原則上不建議用戶去觸碰文中提到的這些文件,儘可能把控制權交給k3s,即便咱們清理agent節點,也儘可能利用k3s內置的腳本。若是碰到此類問題,能夠參考本文的原理介紹去分析,並經過已知的解決方案去修復它。