在 k8s 的 nodes 上面有許多資訊,來看看裡面到底有哪些吧
Nodes 相較於 control plane,是在 k8s 中執行 workload 的單位。Nodes 上面會執行 kubelet, CRI 與 kube-proxy 三個元件
要把機器當作 nodes 加入到 k8s cluster 中,有兩種做法
和其他 k8s object 一樣,nodes 一樣可以透過 json/yaml 來新增,以下是一個 json 的範例:
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
在我們的 cluster 上面直接套用此 json,可以發現 nodes 被新增了,但因為對應 IP 並沒有 kubelet 在發送資訊,因此會停留在 Unknown 狀態:
❯ k create -f node.json
node/10.240.79.157 created
❯ k get no
NAME STATUS ROLES AGE VERSION
10.240.79.157 Unknown <none> 2s
k8s-master1 Ready control-plane 13d v1.31.0
k8s-master2 Ready control-plane 13d v1.31.0
k8s-master3 Ready control-plane 13d v1.31.0
❯ k delete no 10.240.79.157
node "10.240.79.157" deleted
在這個狀態下,任何資源都不會部署上去,包含 daemonset
nodes 的名稱必須要符合 DNS subdomain 的需求,定義於 RFC1123 中,包含以下:
-
或 .
符號與其他 object 一樣,在 metadata.name
中的欄位必須是唯一的。
Nodes 的狀態有以下四項:
Address
:IP 位置,可以是 Hostname (DNS), ExternalIP (對外), InternalIP (對 k8s nodes 內部用)Conditions
(狀態):根據不同的資源表示狀態,若到達一定上限會讓 nodes 無法再部屬 pods,且進行驅逐的動作Capacity and Allocatable
(資源總量與可分配數量):通常指的是 CPU, memory, 以及最多能跑的 podsInfo
:node 上的基本資訊。包含 kernel version, k8s version (指 kubelet 與 kube-proxy 的版本)在所有 running 的 node 上,都可以查看這些資訊,來知道 node 的狀態,conditions 有五項:
True
時代表 node 可接受 pods,False
則代表 node 不健康且不接受 pods。node-monitor-grace-period
參數調整,預設為 40s)可以透過以下指令列出所有 nodes 的 conditions:
❯ kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{range .status.conditions[*]}{.type}={" "}{.status}{"\n"}{end}{"\n"}{end}'
k8s-master1
NetworkUnavailable= False
MemoryPressure= False
DiskPressure= False
PIDPressure= False
Ready= True
k8s-master2
NetworkUnavailable= False
MemoryPressure= False
DiskPressure= True
PIDPressure= False
Ready= True
k8s-master3
NetworkUnavailable= False
MemoryPressure= False
DiskPressure= False
PIDPressure= False
Ready= True
當 nodes 為正常的狀態底下,應該是只有 Ready 為 True,而其餘項目為 False
要特別注意的是,通常僅有 Ready 得狀態最容易被觀察到 (kuubectl get no
會顯示)
但若是其他項目有問題,pods 依然無法排程到該 node 上。
node 有兩種方式通知是否存活:
.status
欄位 (由 kubelet 更新)kube-node-lease
namespace 中的 Lease 欄位 (每一個 node 都會有一個對應的 lease)原本 node status 與 Heartbeats 是綁在一起送的,但因為 node status 傳送的資料比較多,若是頻繁的傳送會造成效能影響。
因此在 k8s 1.12 之後,使用 Lease Heartbeats 的方式將 status 和 heartheat 拆開,若在大規模的叢集可以降地效能影響
括號內為預設值
nodeStatusUpdateFrequency
:(10s) kubelet 計算 node status 的頻率,若是 node lease 功能未開啟的話,此參數也為 kubelet posts node status 到 master 的頻率 (目前預設應該都會開啟)nodeStatusReportFrequency
:(5m) 當 nodes 狀態沒有變動時固定更新狀態的頻率,但若是 nodes 狀態計算後有改變,則 kubelet 會忽略此間隔並立刻回報給 API server node 狀態nodeLeaseDurationSeconds
:(40) kubelet 檢查 lease 的間隔,lease 預設是每 10s 會 renew 一次,目前的版本是無法調整的 (但未來可能會根據 Durations 的時間變動) (參考 KEP-0009)註:在 kubelet 的配置文件中,表示 node lease 每 10 秒 renew 一次,但實際上查找資料後,發現 10 秒是透過 40(Duration 的預設值 ) * 0.25 算出來的,也就是說,調整
nodeLeaseDurationSeconds
是可以增加更新頻率時間的。
參考:https://www.hwchiu.com/docs/2023/node-failure-1#status
在當初使用 kubeadm 安裝 cluster 時,我並沒有給予 kubelet 特別的參數配置,檢查 /var/lib/kubelet/config.yaml
,可看看預設配置:
nodeStatusReportFrequency: 0s
nodeStatusUpdateFrequency: 0s
# 沒有配置 lease durations
此兩個參數被配置為 0s,不過透過下面的方式查看 kubelet 實際讀取到的配置:
# 預設會開啟 8001 port 提供連線
kubectl proxy
# 開啟另一個視窗,將 NODE 變數改為 node name
NODE=k8s-master1
curl -X GET http://127.0.0.1:8001/api/v1/nodes/$NODE/proxy/configz | jq .
### 或者不透過 kubectl proxy,直接使用 kubectl get --raw
kubectl get --raw "/api/v1/nodes/$NODE/proxy/configz" | jq .
會發現 0s 沒有被套用到,且使用預設值:
...
"nodeStatusUpdateFrequency": "10s",
"nodeStatusReportFrequency": "5m0s",
"nodeLeaseDurationSeconds": 40,
...
不過嘗試修改一個非 0s 的參數,確實是有作用的:
# vi /var/lib/kubelet/config.yaml
nodeStatusReportFrequency: 6m0s
nodeStatusUpdateFrequency: 15s
nodeLeaseDurationSeconds: 60
#
sudo systemctl restart kubelet
#
curl -X GET http://127.0.0.1:8001/api/v1/nodes/$NODE/proxy/configz | jq .
"nodeStatusUpdateFrequency": "15s",
"nodeStatusReportFrequency": "6m0s",
"nodeLeaseDurationSeconds": 60,
在修改完 kubelet 的 nodeLeaseDurationSeconds
參數後,要把 對應的 lease 資源刪除,duration 欄位才會更新上去:
# 更新前
❯ k get lease -n kube-node-lease k8s-master1 -o yaml
...
spec:
holderIdentity: k8s-master1
leaseDurationSeconds: 40
#
❯ k delete lease -n kube-node-lease k8s-master1
❯ k get lease -n kube-node-lease k8s-master1 -o yaml
...
spec:
holderIdentity: k8s-master1
leaseDurationSeconds: 60
稍微檢查 renew time 的間隔,可以發現是約 15 秒一次 (60 *0.25)
❯ k describe leases.coordination.k8s.io -n kube-node-lease k8s-master1
Spec:
Holder Identity: k8s-master1
Lease Duration Seconds: 60
Renew Time: 2024-09-15T02:47:19.489134Z
...
#
Spec:
Holder Identity: k8s-master1
Lease Duration Seconds: 60
Renew Time: 2024-09-15T02:47:34.576858Z
node 的狀態更新與 kubelet 的參數息息相關,也與 controller-manager 幾個參數有關
要更了解 nodes 的其他機制,就必須要好好看看 kubelet 的相關參數
下一篇來看看根據這些狀態,node pressure 會如何應對吧 ~
https://kubernetes.io/docs/concepts/architecture/nodes/
https://kubernetes.io/docs/reference/node/node-status/
https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-subdomain-names
https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/
https://kubernetes.io/docs/tasks/administer-cluster/kubelet-config-file/
https://www.hwchiu.com/docs/2023/node-failure-1