
一、節(jié)點(node)
Kubernetes 通過將容器放入在節(jié)點(Node)上運行的 Pod 中來執(zhí)行你的工作負載。 節(jié)點可以是一個虛擬機或者物理機器,取決于所在的集群配置。 每個節(jié)點包含運行 Pods 所需的服務(wù), 這些 Pods 由 控制面 負責管理。
節(jié)點上的組件包括 kubelet、 容器運行時以及 kube-proxy。
1.1 節(jié)點管理
向 API 服務(wù)器添加節(jié)點的方式主要有兩種:
- 節(jié)點上的
kubelet向控制面執(zhí)行自注冊; - 你,或者別的什么人,手動添加一個 Node 對象。
在你創(chuàng)建了 Node 對象或者節(jié)點上的 kubelet 執(zhí)行了自注冊操作之后, 控制面會檢查新的 Node 對象是否合法。例如,如果你使用下面的 JSON 對象來創(chuàng)建 Node 對象:
{
"kind": "Node",
"apiVersion": "v1",
"metadata": {
"name": "10.240.79.157",
"labels": {
"name": "my-first-k8s-node"
}
}
}
Kubernetes 會在內(nèi)部創(chuàng)建一個 Node 對象作為節(jié)點的表示。Kubernetes 檢查 kubelet 向 API 服務(wù)器注冊節(jié)點時使用的 metadata.name 字段是否匹配。 如果節(jié)點是健康的(即所有必要的服務(wù)都在運行中),則該節(jié)點可以用來運行 Pod。 否則,直到該節(jié)點變?yōu)榻】抵?,所有的集群活動都會忽略該?jié)點。
說明: Kubernetes 會一直保存著非法節(jié)點對應(yīng)的對象,并持續(xù)檢查該節(jié)點是否已經(jīng) 變得健康。 你,或者某個控制器必需顯式地 刪除該 Node 對象以停止健康檢查操作。
Node 對象的名稱必須是合法的 DNS 子域名。
1.1.1 節(jié)點自注冊
當 kubelet 標志 --register-node 為 true(默認)時,它會嘗試向 API 服務(wù)注冊自己。 這是首選模式,被絕大多數(shù)發(fā)行版選用。
對于自注冊模式,kubelet 使用下列參數(shù)啟動:
-
--kubeconfig- 用于向 API 服務(wù)器表明身份的憑據(jù)路徑。 -
--cloud-provider- 與某云驅(qū)動 進行通信以讀取與自身相關(guān)的元數(shù)據(jù)的方式。 -
--register-node- 自動向 API 服務(wù)注冊。 -
--register-with-taints- 使用所給的污點列表(逗號分隔的<key>=<value>:<effect>)注冊節(jié)點。 當register-node為 false 時無效。 -
--node-ip- 節(jié)點 IP 地址。 -
--node-labels- 在集群中注冊節(jié)點時要添加的 標簽。 (參見 NodeRestriction 準入控制插件所實施的標簽限制)。 -
--node-status-update-frequency- 指定 kubelet 向控制面發(fā)送狀態(tài)的頻率。
啟用節(jié)點授權(quán)模式和 NodeRestriction 準入插件 時,僅授權(quán) kubelet 創(chuàng)建或修改其自己的節(jié)點資源。
1.1.2 手動節(jié)點管理
你可以使用 kubectl 來創(chuàng)建和修改 Node 對象。
如果你希望手動創(chuàng)建節(jié)點對象時,請設(shè)置 kubelet 標志 --register-node=false。
你可以修改 Node 對象(忽略 --register-node 設(shè)置)。 例如,修改節(jié)點上的標簽或標記其為不可調(diào)度。
你可以結(jié)合使用節(jié)點上的標簽和 Pod 上的選擇算符來控制調(diào)度。 例如,你可以限制某 Pod 只能在符合要求的節(jié)點子集上運行。
如果標記節(jié)點為不可調(diào)度(unschedulable),將阻止新 Pod 調(diào)度到該節(jié)點之上,但不會 影響任何已經(jīng)在其上的 Pod。 這是重啟節(jié)點或者執(zhí)行其他維護操作之前的一個有用的準備步驟。
要標記一個節(jié)點為不可調(diào)度,執(zhí)行以下命令:
kubectl cordon $NODENAME
說明: 被 DaemonSet 控制器創(chuàng)建的 Pod 能夠容忍節(jié)點的不可調(diào)度屬性。 DaemonSet 通常提供節(jié)點本地的服務(wù),即使節(jié)點上的負載應(yīng)用已經(jīng)被騰空,這些服務(wù)也仍需 運行在節(jié)點之上。
1.2 節(jié)點狀態(tài)
一個節(jié)點的狀態(tài)包含以下信息:
你可以使用 kubectl 來查看節(jié)點狀態(tài)和其他細節(jié)信息:
kubectl describe node <節(jié)點名稱>
1.3 節(jié)點優(yōu)雅關(guān)閉
FEATURE STATE: Kubernetes v1.20 [alpha]
如果你啟用了 GracefulNodeShutdown 特性門控, 那么 kubelet 嘗試檢測節(jié)點的系統(tǒng)關(guān)閉事件并終止在節(jié)點上運行的 Pod。 在節(jié)點終止期間,kubelet 保證 Pod 遵從常規(guī)的 Pod 終止流程。
當啟用了 GracefulNodeShutdown 特性門控時, kubelet 使用 systemd 抑制器鎖 在給定的期限內(nèi)延遲節(jié)點關(guān)閉。在關(guān)閉過程中,kubelet 分兩個階段終止 Pod:
- 終止在節(jié)點上運行的常規(guī) Pod。
- 終止在節(jié)點上運行的關(guān)鍵 Pod。
節(jié)點體面關(guān)閉的特性對應(yīng)兩個 KubeletConfiguration 選項:
-
ShutdownGracePeriod:- 指定節(jié)點應(yīng)延遲關(guān)閉的總持續(xù)時間。此時間是 Pod 體面終止的時間總和,不區(qū)分常規(guī) Pod 還是 關(guān)鍵 Pod。
-
ShutdownGracePeriodCriticalPods:- 在節(jié)點關(guān)閉期間指定用于終止 關(guān)鍵 Pod 的持續(xù)時間。該值應(yīng)小于
ShutdownGracePeriod。
- 在節(jié)點關(guān)閉期間指定用于終止 關(guān)鍵 Pod 的持續(xù)時間。該值應(yīng)小于
例如,如果設(shè)置了 ShutdownGracePeriod=30s 和 ShutdownGracePeriodCriticalPods=10s,則 kubelet 將延遲 30 秒關(guān)閉節(jié)點。 在關(guān)閉期間,將保留前 20(30 - 10)秒用于體面終止常規(guī) Pod,而保留最后 10 秒用于終止 關(guān)鍵 Pod
二、管理面與數(shù)據(jù)面節(jié)點通信方式(API Server)
數(shù)據(jù)面到管理面
Kubernetes 采用的是中心輻射型(Hub-and-Spoke)API 模式。 所有從集群(或所運行的 Pods)發(fā)出的 API 調(diào)用都終止于 apiserver(其它控制面組件都沒有被設(shè)計為可暴露遠程服務(wù))。 apiserver 被配置為在一個安全的 HTTPS 端口(443)上監(jiān)聽遠程連接請求, 并啟用一種或多種形式的客戶端身份認證機制。 一種或多種客戶端鑒權(quán)機制應(yīng)該被啟用, 特別是在允許使用匿名請求 或服務(wù)賬號令牌的時候。
應(yīng)該使用集群的公共根證書開通節(jié)點,這樣它們就能夠基于有效的客戶端憑據(jù)安全地連接 apiserver。 一種好的方法是以客戶端證書的形式將客戶端憑據(jù)提供給 kubelet。 請查看 kubelet TLS 啟動引導(dǎo) 以了解如何自動提供 kubelet 客戶端證書。
想要連接到 apiserver 的 Pod 可以使用服務(wù)賬號安全地進行連接。 當 Pod 被實例化時,Kubernetes 自動把公共根證書和一個有效的持有者令牌注入到 Pod 里。 kubernetes 服務(wù)(位于 default 名字空間中)配置了一個虛擬 IP 地址,用于(通過 kube-proxy)轉(zhuǎn)發(fā) 請求到 apiserver 的 HTTPS 末端。
控制面組件也通過安全端口與集群的 apiserver 通信。
這樣,從集群節(jié)點和節(jié)點上運行的 Pod 到控制面的連接的缺省操作模式即是安全的, 能夠在不可信的網(wǎng)絡(luò)或公網(wǎng)上運行。
管理面到數(shù)據(jù)面
從控制面(apiserver)到節(jié)點有兩種主要的通信路徑。 第一種是從 apiserver 到集群中每個節(jié)點上運行的 kubelet 進程。 第二種是從 apiserver 通過它的代理功能連接到任何節(jié)點、Pod 或者服務(wù)。
API 服務(wù)器到 kubelet
apiserver 到節(jié)點、Pod 和服務(wù)
SSH 隧道
Kubernetes 支持使用 SSH 隧道來保護從控制面到節(jié)點的通信路徑。在這種配置下,apiserver 建立一個到集群中各節(jié)點的 SSH 隧道(連接到在 22 端口監(jiān)聽的 SSH 服務(wù)) 并通過這個隧道傳輸所有到 kubelet、節(jié)點、Pod 或服務(wù)的請求。 這一隧道保證通信不會被暴露到集群節(jié)點所運行的網(wǎng)絡(luò)之外。
SSH 隧道目前已被廢棄。除非你了解個中細節(jié),否則不應(yīng)使用。 Konnectivity 服務(wù)是對此通信通道的替代品。
Konnectivity 服務(wù)
EATURE STATE: Kubernetes v1.18 [beta]
作為 SSH 隧道的替代方案,Konnectivity 服務(wù)提供 TCP 層的代理,以便支持從控制面到集群的通信。 Konnectivity 服務(wù)包含兩個部分:Konnectivity 服務(wù)器和 Konnectivity 代理,分別運行在 控制面網(wǎng)絡(luò)和節(jié)點網(wǎng)絡(luò)中。Konnectivity 代理建立并維持到 Konnectivity 服務(wù)器的網(wǎng)絡(luò)連接。 啟用 Konnectivity 服務(wù)之后,所有控制面到節(jié)點的通信都通過這些連接傳輸。
請瀏覽 Konnectivity 服務(wù)任務(wù) 在你的集群中配置 Konnectivity 服務(wù)。
三、控制器
在機器人技術(shù)和自動化領(lǐng)域,控制回路(Control Loop)是一個非終止回路,用于調(diào)節(jié)系統(tǒng)狀態(tài)。
這是一個控制環(huán)的例子:房間里的溫度自動調(diào)節(jié)器。
當你設(shè)置了溫度,告訴了溫度自動調(diào)節(jié)器你的期望狀態(tài)(Desired State)。 房間的實際溫度是當前狀態(tài)(Current State)。 通過對設(shè)備的開關(guān)控制,溫度自動調(diào)節(jié)器讓其當前狀態(tài)接近期望狀態(tài)。
在 Kubernetes 中,控制器通過監(jiān)控集群 的公共狀態(tài),并致力于將當前狀態(tài)轉(zhuǎn)變?yōu)槠谕臓顟B(tài)。
3.1 控制器模式
一個控制器至少追蹤一種類型的 Kubernetes 資源。這些 對象 有一個代表期望狀態(tài)的 spec 字段。 該資源的控制器負責確保其當前狀態(tài)接近期望狀態(tài)。
控制器可能會自行執(zhí)行操作;在 Kubernetes 中更常見的是一個控制器會發(fā)送信息給 API 服務(wù)器,這會有副作用。 具體可參看后文的例子。
3.1.1通過 API 服務(wù)器來控制
Job 控制器是一個 Kubernetes 內(nèi)置控制器的例子。 內(nèi)置控制器通過和集群 API 服務(wù)器交互來管理狀態(tài)。
Job 是一種 Kubernetes 資源,它運行一個或者多個 Pod, 來執(zhí)行一個任務(wù)然后停止。 (一旦被調(diào)度了,對 kubelet 來說 Pod 對象就會變成了期望狀態(tài)的一部分)。
在集群中,當 Job 控制器拿到新任務(wù)時,它會保證一組 Node 節(jié)點上的 kubelet 可以運行正確數(shù)量的 Pod 來完成工作。 Job 控制器不會自己運行任何的 Pod 或者容器。Job 控制器是通知 API 服務(wù)器來創(chuàng)建或者移除 Pod。 控制面中的其它組件 根據(jù)新的消息作出反應(yīng)(調(diào)度并運行新 Pod)并且最終完成工作。
創(chuàng)建新 Job 后,所期望的狀態(tài)就是完成這個 Job。Job 控制器會讓 Job 的當前狀態(tài)不斷接近期望狀態(tài):創(chuàng)建為 Job 要完成工作所需要的 Pod,使 Job 的狀態(tài)接近完成。
控制器也會更新配置對象。例如:一旦 Job 的工作完成了,Job 控制器會更新 Job 對象的狀態(tài)為 Finished。
(這有點像溫度自動調(diào)節(jié)器關(guān)閉了一個燈,以此來告訴你房間的溫度現(xiàn)在到你設(shè)定的值了)。
3.1.2 直接控制
相比 Job 控制器,有些控制器需要對集群外的一些東西進行修改。
例如,如果你使用一個控制回路來保證集群中有足夠的 節(jié)點,那么控制器就需要當前集群外的 一些服務(wù)在需要時創(chuàng)建新節(jié)點。
和外部狀態(tài)交互的控制器從 API 服務(wù)器獲取到它想要的狀態(tài),然后直接和外部系統(tǒng)進行通信 并使當前狀態(tài)更接近期望狀態(tài)。
(實際上有一個控制器 可以水平地擴展集群中的節(jié)點。)
這里,很重要的一點是,控制器做出了一些變更以使得事物更接近你的期望狀態(tài), 之后將當前狀態(tài)報告給集群的 API 服務(wù)器。 其他控制回路可以觀測到所匯報的數(shù)據(jù)的這種變化并采取其各自的行動。
在溫度計的例子中,如果房間很冷,那么某個控制器可能還會啟動一個防凍加熱器。 就 Kubernetes 集群而言,控制面間接地與 IP 地址管理工具、存儲服務(wù)、云驅(qū)動 APIs 以及其他服務(wù)協(xié)作,通過擴展 Kubernetes 來實現(xiàn)這點。
3.2 期望狀態(tài)與當前狀態(tài)
Kubernetes 采用了系統(tǒng)的云原生視圖,并且可以處理持續(xù)的變化。
在任務(wù)執(zhí)行時,集群隨時都可能被修改,并且控制回路會自動修復(fù)故障。 這意味著很可能集群永遠不會達到穩(wěn)定狀態(tài)。
只要集群中的控制器在運行并且進行有效的修改,整體狀態(tài)的穩(wěn)定與否是無關(guān)緊要的。
3.3 設(shè)計
作為設(shè)計原則之一,Kubernetes 使用了很多控制器,每個控制器管理集群狀態(tài)的一個特定方面。 最常見的一個特定的控制器使用一種類型的資源作為它的期望狀態(tài), 控制器管理控制另外一種類型的資源向它的期望狀態(tài)演化。
使用簡單的控制器而不是一組相互連接的單體控制回路是很有用的。 控制器會失敗,所以 Kubernetes 的設(shè)計正是考慮到了這一點。
說明:
可以有多個控制器來創(chuàng)建或者更新相同類型的對象。 在后臺,Kubernetes 控制器確保它們只關(guān)心與其控制資源相關(guān)聯(lián)的資源。
例如,你可以創(chuàng)建 Deployment 和 Job;它們都可以創(chuàng)建 Pod。 Job 控制器不會刪除 Deployment 所創(chuàng)建的 Pod,因為有信息 (標簽)讓控制器可以區(qū)分這些 Pod。
運行控制器的方式
Kubernetes 內(nèi)置一組控制器,運行在 kube-controller-manager 內(nèi)。 這些內(nèi)置的控制器提供了重要的核心功能。
Deployment 控制器和 Job 控制器是 Kubernetes 內(nèi)置控制器的典型例子。 Kubernetes 允許你運行一個穩(wěn)定的控制平面,這樣即使某些內(nèi)置控制器失敗了, 控制平面的其他部分會接替它們的工作。
你會遇到某些控制器運行在控制面之外,用以擴展 Kubernetes。 或者,如果你愿意,你也可以自己編寫新控制器。 你可以以一組 Pod 來運行你的控制器,或者運行在 Kubernetes 之外。 最合適的方案取決于控制器所要執(zhí)行的功能是什么。
四、云控制管理器
FEATURE STATE: Kubernetes v1.11 [beta]
使用云基礎(chǔ)設(shè)施技術(shù),你可以在公有云、私有云或者混合云環(huán)境中運行 Kubernetes。 Kubernetes 的信條是基于自動化的、API 驅(qū)動的基礎(chǔ)設(shè)施,同時避免組件間緊密耦合。
組件 cloud-controller-manager 是指云控制器管理器, 云控制器管理器是指嵌入特定云的控制邏輯的 控制平面組件。 云控制器管理器允許您鏈接聚合到云提供商的應(yīng)用編程接口中, 并分離出相互作用的組件與您的集群交互的組件。
通過分離 Kubernetes 和底層云基礎(chǔ)設(shè)置之間的互操作性邏輯, 云控制器管理器組件使云提供商能夠以不同于 Kubernetes 主項目的速度進行發(fā)布新特征。
cloud-controller-manager 組件是基于一種插件機制來構(gòu)造的, 這種機制使得不同的云廠商都能將其平臺與 Kubernetes 集成。