文章目錄
- 1、集群架構示意圖
- 2、概述
- 3、管理
- 3.1 節點名稱唯一性
- 3.2 節點自注冊
- 3.3 手動節點管理
- 4、節點狀態
- 4.1 地址(`Addresses`)
- 4.2 狀況(`Condition`)
- 4.3 容量(`Capacity`)與可分配(`Allocatable`)
- 4.4 信息(Info)
- 5、節點心跳
- 6、節點控制器
- 6.1 逐出速率限制
- 6.2 資源容量跟蹤
- 7、節點拓撲
- 8、節點體面關閉
- 9、處理節點非體面關閉
- 10、交換內存管理
1、集群架構示意圖
2、概述
kubernetes通過將容器放入在節點(Node)上運行的Pod中來執行工作負載
節點可以是一個虛擬機或者一臺物理機器,取決于所在集群的配置。
每個節點包含運行Pod所需的服務,這些節點由控制面板負責管理
通常集群中會有若干個節點;節點上的組件包括kubelet
、容器運行時
以及kube-proxy
3、管理
向API服務器添加節點的方式主要有兩種:
- 節點上的
kubelet
向控制面執行自注冊; - 人為手動添加一個Node對象
在創建了Node對象或者節點上的kubelet
執行了自注冊操作之后,控制面會檢查新的Node對象是否合法。
例如:使用下面的SON對象來創建Node對象
{"kind": "Node","apiVersion": "v1","metadata": {"name": "10.240.79.157","labels": {"name": "my-first-k8s-node"}}
}
kubernetes會在內部創建一個Node對象作為節點的表示。kubernetes檢查kubelet
向API服務器注冊節點時使用的metadata.name
字段是否匹配。
如果節點是健康的(即所有必要的服務都在運行中),則該節點可以用來運行Pod。否則,直到該節點變為健康之前,所有的集群活動都會忽略該節點。
說明:
- kubernetes會一直保存著非法節點對應的對象,并持續檢查該節點是否變得健康
- 用戶或某個控制器必須顯式的刪除該node對象以停止健康檢查操作
- Node對象的名稱必須是合法的DNS子域名
3.1 節點名稱唯一性
節點的名稱用來標識Node對象。沒有兩個Node可以同時使用相同的名稱。
kubernetes還假定名字相同的資源是同一個對象。就Node而言,隱式假定使用相同名稱的實例會具有相同的狀態(如網絡配置、根磁盤內容)和類似節點標簽這種屬性。這可能在節點被更改但其名稱未變時導致系統狀態不一致。
如果某個Node需要被替換或者大量變更,需要從API服務器移除現有的Node對象,之后再在更新之后重新將其加入。
3.2 節點自注冊
當kubelet
標志--register-node
為**True(默認)**時,它會嘗試向API服務注冊自己。這是首選模式,被絕大多數發行版使用。
對于自注冊模式,kubelet使用以下參數啟動:
--kubeconfig
:用于向API服務器執行身份認證所用的憑據的路徑--cloud-provider
:與某云驅動進行通信以讀取與自身相關的元數據的方式--register-node
:自動向API服務器注冊--register-with-taints
:使用所給的污點列表(逗號分隔的<key>=<value>:<effect>
)注冊節點,當register-node
為false時無效--node-ip
:可選的以英文逗號隔開的節點IP地址列表。只能為每個地址簇指定一個地址。例如:在單協議棧IPv4集群中,需要將此值設置為kubelet應使用的節點IPv4地址。如果沒有提供這個參數,kubelet將會使用節點默認的IPv4地址,如果節點沒有IPv4地址,則使用節點默認的IPv6地址。--node-labels
:在集群中注冊節點時需要添加的標簽--node-status-update-frequency
:指定kubelet向API服務器發送其節點狀態的頻率
當Node鑒權模式和NodeRestriction準入插件
被啟用后,僅授權kubelet創建/修改自己的Node資源
說明:
- 由于節點名稱唯一性,當Node的配置需要更新時,一種好的做法是:重新向API服務器注冊該節點。例如:如果kubelet重啟時其
--node-labels
是新的值,但同一個Node名稱已經被使用,則所做變更不會起作用,因為節點的標簽是在Node注冊時完成的。 - 如果在
kubelet
重啟期間Node
配置發生了變化,已經被調度到某Node上的Pod可能會出現行為不正常或者其他問題。例如:已經運行的Pod可能通過污點機制設置了與Node上新設置的標簽相排斥的規則,也有一些其他Pod,本來與此Pod之間存在不兼容問題,也會因為新的標簽設置被調度到同一節點。節點重新注冊操作可以確保節點上所有的Pod都被排空并且被正確的重新調度
3.3 手動節點管理
可是使用kubectl 來創建和修改Node對象。
如果希望手動創建Node對象,需要設置kubelet標志--register-node=false
可以修改Node對象。如:修改節點上的標簽標記為不可被調度
結合使用Node上的標簽個Pod上的選擇算符來控制調度。如:限制某Pod只能在符合要求的節點子集上運行。
如果 標記節點為不可調度(unschedulable
),將阻止新Pod調度到該Node之上,但不會影響任何已經在其上的Pod。這是重啟節點或者執行其他維護操作之前的一個有用的準備步驟。
要標記一個Node為不可調度:kubectl cordon $NODENAME
4、節點狀態
一個節點的狀態包含以下信息:
- 地址(
Addresses
) - 狀況(
Condition
) - 容量(
Capacity
)與可分配(Allocatable
) - 信息(
Info
)
可以通過kubectl
來查看節點狀態和其他細節信息:
kubectl describe node <節點名稱>
4.1 地址(Addresses
)
這些字段的用法取決于云服務商或者物理機配置
hostName
:由節點的內核報告。可以通過kubelet的--hostname-override
參數覆蓋ExternalIP
:通常是節點的可外部路由(從集群外可訪問)的IP地址InternalIP
:通常是節點的僅可在集群內部路由的IP地址。
4.2 狀況(Condition
)
conditions
字段描述了所有 running 節點的狀況。狀況的示例包括:
節點狀況 | 描述 |
---|---|
Ready | 取值有三個,True、False、UnknownTrue :節點是健康的并且已經準備好接收PodFalse :節點不健康且不能接收PodUnknown :表示節點控制器在最近node-monitor-grace-period 期間沒有收到節點的消息(默認40s) |
DiskPressure | True 表示節點存在磁盤空間壓力,即磁盤可用量低,否則為 False |
MemoryPressure | True 表示節點存在內存壓力,即節點內存可用量低,否則為 False |
PIDPressure | True 表示節點存在進程壓力,即節點上進程過多;否則為 False |
NetworkUnavailable | True 表示節點網絡配置不正確;否則為 False |
在 Kubernetes API 中,節點的狀況表示節點資源中 .status
的一部分。 例如,以下 JSON 結構描述了一個健康節點:
"conditions": [{"type": "Ready","status": "True","reason": "KubeletReady","message": "kubelet is posting ready status","lastHeartbeatTime": "2019-06-05T18:38:35Z","lastTransitionTime": "2019-06-05T11:41:27Z"}
]
當節點上出現問題時,kubernetes控制面會自動創建與影響節點狀況對應的污點。
如:當Ready
狀況的status
保持Unknown
或者False
的時間長于kube-controller-manager的NodeMonitorGracePeriod
(默認40秒)時,會造成Unknown
狀態下為節點添加node.kubernetes.io/unreachable
污點或者False
狀態下為節點添加node.kubernetes.io/not-ready
污點。
這些污點會影響懸決的Pod,因為調度器在將Pod分配到節點時會考慮節點的污點。已調度到節點的當前Pod可能會由于施加NoExecute
污點被驅逐。Pod還可以設置容忍度,使得這些Pod仍然能夠調度到且繼續運行在設置了特定污點的節點上。
4.3 容量(Capacity
)與可分配(Allocatable
)
這兩個值描述節點山的可用資源:CPU、內存、可以調度到節點上的Pod個數上限。
capacity
塊中的字段標示節點擁有的資源總量。 allocatable
塊指示節點上可供普通 Pod 使用的資源量
4.4 信息(Info)
Info指的是節點的一般信息,如內核版本、kubernetes版本、容器運行時詳細信息、以及節點使用的操作系統
kubelet從節點收集這些信息并將其發布到kubernetes API
5、節點心跳
kubernetes節點發送的心跳幫助你的集群確定每個節點的可用性,并在檢測到故障時采取行動。
對于節點,有兩種形式的心跳:
- 更新節點的
.status
kube-node-lease
命名空間中的Lease(租約)
對象。每個節點都有一個關聯的Lease對象。
與節點的.status
更新相比,Lease是一種輕量級資源。使用Lease來表達心跳在大型集群中可以減少這些更新對性能的影響。
kubelet負責創建和更新節點的.status
,以及更新他們對應的Lease
- 當節點狀態發生變化時,或者在配置的時間間隔內沒有更新事件時,kubelet會更新
.status
。.status
更新的默認間隔為 5 分鐘(比節點不可達事件的 40 秒默認超時時間長很多) - kubelet會創建并每10秒(默認更新間隔時間)更新Lease對象。 Lease的更新獨立于節點的
.status
更新而發生。如果Lease的更新操作失敗,kubelet會采用指數回退機制,從 200 毫秒開始重試, 最長重試間隔為 7 秒鐘。
6、節點控制器
節點控制器是kubernetes控制面板組件,管理節點的方方面面。
節點控制器在節點的生命周期每扮演多個角色:
- 節點注冊時為其分配一個CIDR區段(如果啟用了CIDR分配)
- 保持節點控制器里的節點列表與云服務商提供的可用機器列表同步
如果在云環境下運行,只要某節點不健康,節點控制器就會詢問云服務是否節點的虛擬機仍可用。如果不可用,節點控制器會將該節點從他的節點列表中刪除。 - 監控節點的健康狀況
3.1 在節點不可達的情況下,在Node的.status
中更新Ready
狀況。在這種情況下,節點控制器將NodeReady
狀況更新為Unknown
3.2 如果節點仍然無法訪問:對于不可達節點上的所有Pod觸發API發起的逐出操作。默認情況下,節點控制器在將節點標記為 Unknown 后等待 5 分鐘提交第一個驅逐請求。
默認情況下,節點控制器每 5 秒檢查一次節點狀態,可以使用 kube-controller-manager 組件上的 --node-monitor-period 參數來配置周期
6.1 逐出速率限制
大部分情況下,節點控制器把逐出速率限制在每秒--node-eviction-rate
個(默認為0.1)。這表示他每10秒內至多從一個節點驅逐Pod
當一個可用區域(Availability Zone
)中的節點變不健康時,節點的驅逐行為將發生改變。節點控制器會同時檢查可用區域中不健康(Ready
狀況為Unknown
或False
)節點的百分比:
- 如果不健康節點的比例超過
--unhealthy-zone-threshold
(默認為0.55),驅逐速率將會降低 - 如果集群較小(小于等于
--large-cluster-size-threshold
個節點,默認為50),驅逐操作將會停止 - 否則,驅逐速率將會降為每秒
--secondary-node-eviction-rate
個(默認為0.01)
在逐個可用區域中實施這些策略的主要原因是:當一個可用區域可能從控制面脫離時其他可用區域可能仍然保持連接。如果你的集群沒有跨越云服務商的多個可用區域,那真個集群就只有一個可用區域。
跨多個可用區域部署節點的一個關鍵原因是:當某個可用區域整體出現故障時,工作負載可以轉移到健康的可用區域。因此,如果一個可用區域中的節點都不健康時,節點控制器會以正常的速率(--node-eviction-rate
)進行驅逐操作。在所有可用區域都不健康(即整個集群中沒有健康節點)的極端情況下,節點控制器將假設控制面與節點間的連接出了某些問題,他將停止所有驅逐動作(如果故障后部分節點重新連接,節點控制器會從剩下的不健康或者不可達的節點中驅逐Pod)
節點控制器還負責驅逐運行在擁有NoExecute
污點的節點上的Pod,除非這些Pod能夠容忍污點。節點控制器還負責根據節點故障(如不可訪問或沒有就緒)為其添加污點,這意味著調度器不會將Pod調度到不健康的節點上。
6.2 資源容量跟蹤
Node對象會跟蹤節點上資源的容量(例如:可用內存和CPU數量)。通過自注冊機制生成的Node對象會在注冊期間報告自身容量。如果是手動添加Node,需要在添加節點時手動設置節點容量。
kubernetes調度器保證節點上有足夠的資源供其上的Pod使用。他會檢查節點上所有容器的請求的資源的總和不會超過節點的容量。
總的請求包括由kubelet啟動的所有容器,但不包括由容器運行時直接啟動的容器,也不包括不受kubectl控制的其他進程
7、節點拓撲
如果啟用了topologyManager
特性門控,kubelet可以在做出資源分配決策時使用拓撲提示。
8、節點體面關閉
kubelet會嘗試檢測節點系統關閉事件 并 終止在節點上運行的所有Pod。
在節點終止期間,kubelet保證Pod遵從常規的Pod終止流程,且不接受新的Pod(即使這些Pod已經綁定到該節點)
節點體面關閉特性依賴于systemd
,因為他要利用systemd 抑制鎖機制,在給定的期限內延遲節點關閉。
節點體面關閉受GracefulNodeShutdown
特性門控制,在1.21版本中是默認啟用的。
注意:默認情況下,shutdownGracePeriod
和shutdownGracePeriodCriticalPods
都是被設置為0的,因此不會激活節點體面關閉功能。要激活此特性,這兩個kubelet配置選項要適當配置,并設置為非0值。
一旦systemd檢測到或通知節點關閉,kubelet就會在節點上設置一個NotReady
狀況,并將reason
設置為node is shutting down
, kube-scheduler會重視此狀況,不將Pod調度到受影響的節點上;其他第三方調度程序也應當遵循相同的邏輯。這意味著新的Pod不會被調度到該節點上,因此不會有新Pod啟動。
如果檢測到節點關閉過程正在進行中,kubelet 也會 在PodAdmission
階段拒絕Pod,即使是該Pod帶有node.kuberbetes.io/not-ready:NoSchedule
的容忍度。
同時,當kubelet通過API在其Node上設置該狀況時,kubelet也開始終止在本地運行的所有Pod
在體面關閉節點過程中,kubelet分兩個階段來終止Pod:
- 終止在節點上運行的常規Pod
- 終止在節點上運行的關鍵Pod
節點體面關閉的特性對應兩個kubeletConfiguration
選項:
shutdownGracePeriod
:指定節點應延遲關閉的總持續時間,此時間是Pod體面終止的時間總和,不區分常規Pod和關鍵PodshutdownGracePeriodCriticalPods
:在節點關閉期間指定用于終止關鍵 Pod 的持續時間。該值應小于shutdownGracePeriod
注意:在某些情況下,節點終止過程會被系統取消(或者由管理員手動取消),無論那種情況下,節點都會返回到Ready
狀態。然而,已經開始終止進程的Pod將不會被kubelet恢復,需要被重新調度。
9、處理節點非體面關閉
節點關閉的操作可能無法被kubelet的節點關閉管理器檢測到,是因為該命令不會觸發kubelet所使用的的抑制鎖定機制,或者是因為用戶錯誤的原因(ShutdownGracePeriod
和 ShutdownGracePeriodCriticalPod
配置不正確)
當某節點關閉但是kubelet的節點關閉管理器未檢測到這一事件的時候,在那個已關閉節點上, 屬于 StatefulSet
的pod 將停滯于終止狀態,并且不能移動到新的運行節點上。這是因為:已關閉節點上的kubelet已不存在,亦無法刪除pod,因此 StatefulSet無法創建同名的新pod。
如果 pod 使用了卷,則 VolumeAttachments
不會從原來已關閉節點上刪除,因此 這些pod所使用的卷也不能掛載到新運行的節點上。所以:那些以StatefulSet形式運行的應用無法正常工作。
如果原來的已關閉節點被恢復,kubelet將刪除pod,新的pod將會在不同的運行節點上被創建、如果原來的已關閉節點沒有被恢復,那些在已關閉節點上的pod將永遠滯留在終止狀態。
為了緩解上述情況,用戶可以 手動將具有NoExecute
或 NoSchedule
效果的node.kubernetes.io/out-of-service
污點添加到節點上,標記其無法提供服務。
如果在kube-controller-manager
上啟用了NodeOutOfServiceVolumeDetach
特性門控,并且 節點被通過污點標記為無法提供服務,如果節點pod上沒有設置對應的容忍度,那么這樣的pod將會被強制刪除,并且在該節點上被終止的pod將立即進行卷分離操作。這樣就允許那些無法提供服務節點上的pod能在其他節點上快速恢復。
在非體面關閉期間,pod分兩個階段終止:
- 強制刪除沒有匹配的
out-of-service
容忍度的pod - 立即對此類pod執行分離卷操作
說明:
- 在添加
node.kubernetes.io/out-of-service
污點之前,應該驗證節點已經處于關閉或斷電狀態,而不是在重新啟動中 - 將pod移動到新節點后,用戶需要手動移除停止服務的污點,并且用戶要檢查關閉節點是否已恢復,因為該用戶是最初添加污點的用戶。
10、交換內存管理
要在節點上啟用交換內存,必須啟用kubelet的NodeSwap
特性門控,同時使用 --fail-swap-on
命令行參數或者將failSwapOn
配置設置為 false
注意:
- 當內存交換功能被啟用之后,kubernetes數據可以被交換到磁盤
用戶還可以選擇配置memorySwap.swapBehavior
以指定節點使用交換內存的方式。
e.g:
memorySwap:swapBehavior: UnlimitedSwap
UnlimitedSwap
(默認):kubernetes工作負載 可以根據請求使用盡可能多的交換內存,一直達到系統限制為止。LimitedSwap
:kubernetes工作負載對交換內存的使用受到限制,只有具有Burstable QoS
的 Pod 可以使用交換空間。
如果啟用了特性門 但是沒有指定memorySwap
的配置,默認情況下kubelet將使用與 UnlimitedSwap
設置相同的行為。
采用LimitedSwap
時,不屬于 Burstable Qos
分類的pod(BestEffort / Guaranteed
Qos pod)被禁止使用交換內存,為了保持上述的安全性和節點的健康性,在LimitedSwap
生效時,不允許這些pod使用交換內存。
在介紹交換限制的計算之前,先統一以下數據:
nodeTotalMemory
:節點上可用的物理內存的總量totalPodSwapAvailable
:節點上可供pod使用的交換內存總量(一些交換內存可能會保留供系統使用)containerMemoryRequest
:容器的內存請求
交換限制被配置為:(containerMemoryRequest / nodeTotalMemory) * totalPodsSwapAvailable
的值。
需要注意:位于 Burstable QoS Pod 中的容器可以通過將內存請求設置為與內存限制相同來選擇不使用交換空間。 以這種方式配置的容器將無法訪問交換內存