前 言
面向邊緣的輕量級K8S發行版k3s于去年2月底發布后,備受關注,在發布后的10個月時間里,Github Star達11,000顆,于去年11月中旬已經GA,但正如你所知,沒有一個產品是十全十美的,k3s在客戶落地實踐的程序中也暴露過一些不足,在k3s技術團隊的專業技術支持下,許多問題得到了改善和解決,
我們精選了一些在實際生產環境中的問題處理案例,分享給正在使用k3s的你,希望k3s技術團隊的經驗能夠為你帶來參考,也希望你可以參與進來和我們一起探索切磋,畢竟,尋找答案的路途永遠沒有終點,
本文將分享k3s產品中關于node注冊失敗的排查記錄,
排查記錄
問題描述
k3s版本:v1.17.2+k3s1
k3s agent向server注冊時,日志出現明顯報錯:

同時,在k3s server上查詢node,也確實無法獲取注冊的節點資訊(只有一個server節點):

客戶的虛擬機環境使用某私有云,從反饋看有過VM反復清理的操作,不過具體操作無法完整復原,
基本原理
Agent注冊的程序是十分復雜的,總的來說有兩個目的:
-
啟動kubelet等服務,連接到server節點上的api-server服務,這是k8s集群必須的
-
建立websocket tunnel,用于k3s的server和agent同步一些資訊
我們在注冊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內置的腳本,如果碰到此類問題,可以參考本文的原理介紹去分析,并通過已知的解決方案去修復它,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/38915.html
標籤:其他
