當你創建了一個 Deployment 時,Kubernetes 內部發生了什麼?
- 2021 年 9 月 27 日
- 筆記
- Kubernetes
我們通常使用 kubectl 來管理我們的 Kubernetes 集群。 當我們需要一個 Nginx 服務時,可以使用以下命令來創建:
kubectl create deployment nginx --image nginx
返回:
deployment.apps/nginx created
稍等片刻,一個包含 Nginx 容器的 Pod 就會啟動成功。那麼在我們執行在上述命令後,Kubernetes 內部發生了什麼呢?
核心組件
在介紹內部發生了什麼之前,我們首先需要了解一下以下 4 個核心組件在 Kubernetes 集群中的角色和作用:
-
kube-apiserver: Kubernetes API 伺服器驗證並配置 API 對象的數據, 這些對象包括 pods、services 等。 API 伺服器為 REST 操作提供服務,並為集群的共享狀態提供前端, 所有其他組件都通過該前端進行交互。
-
kube-controller-manager: 運行控制器進程的控制平面組件。 從邏輯上講,每個控制器都是一個單獨的進程, 但是為了降低複雜性,它們都被編譯到同一個可執行文件,並在一個進程中運行,所以它會被稱作為
manager
。它包含 DeploymentController、ReplicaSetController、JobController 等一系列控制器。 -
kube-scheduler: 控制平面組件,負責監視新創建的、未指定運行節點(node)的 Pods,選擇節點讓 Pod 在上面運行。 調度決策考慮的因素包括單個 Pod 和 Pod 集合的資源需求、硬體/軟體/策略約束、親和性和反親和性規範、數據位置、工作負載間的干擾和最後時限。
-
kubelet: 一個在集群中每個節點(node)上運行的代理。 它保證容器(containers)都運行在 Pod 中。 kubelet 接收一組通過各類機制提供給它的 PodSpecs,確保這些 PodSpecs 中描述的容器處於運行狀態且健康。
簡化的核心過程
在了解上述核心組件的角色後,我們來看一下 Kubernetes 內部到底發生了哪些事情:
-
用戶通過 kubectl 向 kube-apiserver 發起一個創建 Deployment 對象的請求。
-
kube-apiserver 在對上述請求進行認證(authn)、授權(authz)、准入控制(admission control)、驗證(validation)等一系列操作後,會創建一個 Deployment 對象。
-
上述的 Deployment 創建事件,會被 DeploymentController 通過其內部的 DeploymentInformer 監聽到,然後根據 DeploymentController 內部設定的邏輯,它將會創建一個 ReplicaSet 對象。源碼 syncDeployment
-
上述的 ReplicaSet 創建事件,會被 ReplicaSetController 通過其內部的 ReplicaSetInformer 監聽到,然後根據 ReplicaSetController 內部設定的邏輯,它將創建一個 Pod 對象,而此時 Pod 的 Spec.nodeName 欄位的值為空;源碼 syncReplicaSet
-
上述的 Pod 創建事件,會被 Scheduler 通過其內部的 PodInformer 監聽到,Scheduler 會根據其內部的調度演算法,選擇一個合適的 Node 節點,例如 node-A,並更新 Pod 的 Spec.nodeName 欄位。源碼 Schedule
-
上述的 Pod 更新事件,會被 node-A 節點上 kubelet 感知到,它會發現自己的 nodeName 和 Pod 的 Spec.nodeName 相匹配,接著 kubelet 將按照一定的步驟順序啟動 Pod 中的容器,並將容器已啟動的資訊寫入 Pod 的 Status 中。源碼 syncPod
如上所述,DeploymentController、ReplicaSetController 等許多獨立的控制循環都是通過監聽 kube-apiserver 上對象的變化進行通訊,而這些變化會通過各種 Informer 觸發事件,執行其對應的業務邏輯。之所以這麼設計,是為了減少對 apiserver 的壓力。
kubelet 創建 Pod 的過程
Pod 的創建的過程大體上可以分為 4 個步驟(實際上為 7 步,這裡省略了前置的 3 個步驟。源碼 SyncPod):
-
為 Pod 創建沙盒,即基礎設施容器 Infrastructure Container(鏡像名稱為 k8s.gcr.io/pause),它的主要作用是創建並共享進程命名空間。
-
創建 Pod 規格中指定的臨時容器 Ephemeral Containers(Alpha 功能,默認不開啟),臨時容器是一種特殊的容器,該容器在現有 Pod 中臨時運行,以便完成用戶發起的操作,例如故障排查。 你可以使用臨時容器來檢查服務,而不是用它來構建應用程式。
-
創建 Pod 規格中指定的初始化容器 Init Containers,初始化容器是一種特殊容器,在 Pod 內的應用容器啟動之前運行。Init 容器可以包括一些應用鏡像中不存在的實用工具和安裝腳本。
-
依次創建 Pod 規格中指定的常規容器 Containers。
參考
- 張磊《深入剖析 Kubernetes》
- Michael Hausenblas, Stefan Schimanski《Kubernetes 編程》
- Kubernetes 組件
- 詳解 Kubernetes Deployment 的實現原理
- 詳解 Kubernetes ReplicaSet 的實現原理
- 詳解 Kubernetes Pod 的實現原理
- Kubernetes CRI 分析 – kubelet 創建 Pod 分析
更多
更多經典示例請參考://github.com/jxlwqq/kubernetes-examples