我們通常使用 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-examp...
本作品採用《CC 協議》,轉載必須註明作者和本文連結