iT邦幫忙

2024 iThome 鐵人賽

0
Kubernetes

一起來看 Kubernetes 官方文件吧!系列 第 17

Day17 - 一起來看 Kubernetes 官方文件吧!- Node status

  • 分享至 

  • xImage
  •  

前言

在 k8s 的 nodes 上面有許多資訊,來看看裡面到底有哪些吧

今日目標

  • 看看 node 內的一些資訊
  • 理解 node status 與 heratbeat 的機制

Nodes

Nodes 相較於 control plane,是在 k8s 中執行 workload 的單位。Nodes 上面會執行 kubelet, CRI 與 kube-proxy 三個元件

Management

要把機器當作 nodes 加入到 k8s cluster 中,有兩種做法

  1. 透過 kubelet 的自動註冊機制,註冊至 control plane
  2. 管理者手動在 k8s cluster 新增 Node object

和其他 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 中,包含以下:

  • 不能超過 253 個字元
  • 只能包含小寫符號,使用 -. 符號
  • 以字元符號開始與結尾

與其他 object 一樣,在 metadata.name 中的欄位必須是唯一的。

Node status

Nodes 的狀態有以下四項:

  • Address:IP 位置,可以是 Hostname (DNS), ExternalIP (對外), InternalIP (對 k8s nodes 內部用)
  • Conditions (狀態):根據不同的資源表示狀態,若到達一定上限會讓 nodes 無法再部屬 pods,且進行驅逐的動作
  • Capacity and Allocatable (資源總量與可分配數量):通常指的是 CPU, memory, 以及最多能跑的 pods
  • Info:node 上的基本資訊。包含 kernel version, k8s version (指 kubelet 與 kube-proxy 的版本)

Node Conditions

在所有 running 的 node 上,都可以查看這些資訊,來知道 node 的狀態,conditions 有五項:

  1. Ready:當 True 時代表 node 可接受 pods,False 則代表 node 不健康且不接受 pods。
    另外還有 Unknown 的狀態,代表 node controller 超過一定時間沒有接受到由 node kubelet 發送過來的訊息了 (使用 node-monitor-grace-period 參數調整,預設為 40s)
  2. DiskPressure:當 True 時代表磁碟空間不足
  3. MemoryPressure:當 True 時代表記憶體不足
  4. PIDPressure:當 True 時代表 node 上有過多的 process
  5. NetworkUnavailable:當 True 時代表網路配置不正確

可以透過以下指令列出所有 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 上。

Heartbeats

node 有兩種方式通知是否存活:

  • 更新 nodes 的 .status 欄位 (由 kubelet 更新)
  • kube-node-lease namespace 中的 Lease 欄位 (每一個 node 都會有一個對應的 lease)

原本 node status 與 Heartbeats 是綁在一起送的,但因為 node status 傳送的資料比較多,若是頻繁的傳送會造成效能影響。

因此在 k8s 1.12 之後,使用 Lease Heartbeats 的方式將 status 和 heartheat 拆開,若在大規模的叢集可以降地效能影響

  • kubelet 更新 nodes 的 .status 預設是 5 分鐘一次,這比 controller-manager 的 40 秒 timeout 還長很多
  • kubelet 每 10 秒更新一次 lease,這與 .status 的更新是分開的。當 Lease 更新失敗時,kubelet 會以 200ms 的頻率開始重試,並會陸續延長頻率時間,最長到 7 秒重試一次。

括號內為預設值

  • 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

查看 kubelet config

在當初使用 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,

https://ithelp.ithome.com.tw/upload/images/20241225/201688011qaTzwxw4e.png

在修改完 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


上一篇
Day16 - 一起來看 Kubernetes 官方文件吧!- PodDisruptionBudget
下一篇
Day18 - 一起來看 Kubernetes 官方文件吧!- Node-pressure Eviction
系列文
一起來看 Kubernetes 官方文件吧!19
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言