我們通常使用 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 內部到底發生了哪些事情:

  1. 使用者通過 kubectl 向 kube-apiserver 發起一個建立 Deployment 物件的請求。

  2. kube-apiserver 在對上述請求進行認證(authn)、授權(authz)、准入控制(admission control)、驗證(validation)等一系列操作後,會建立一個 Deployment 物件。

  3. 上述的 Deployment 建立事件,會被 DeploymentController 通過其內部的 DeploymentInformer 監聽到,然後根據 DeploymentController 內部設定的邏輯,它將會建立一個 ReplicaSet 物件。原始碼 syncDeployment

  4. 上述的 ReplicaSet 建立事件,會被 ReplicaSetController 通過其內部的 ReplicaSetInformer 監聽到,然後根據 ReplicaSetController 內部設定的邏輯,它將建立一個 Pod 物件,而此時 Pod 的 Spec.nodeName 欄位的值為空;原始碼 syncReplicaSet

  5. 上述的 Pod 建立事件,會被 Scheduler 通過其內部的 PodInformer 監聽到,Scheduler 會根據其內部的排程演算法,選擇一個合適的 Node 節點,例如 node-A,並更新 Pod 的 Spec.nodeName 欄位。原始碼 Schedule

  6. 上述的 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):

  1. 為 Pod 建立沙盒,即基礎設施容器 Infrastructure Container(映象名稱為 k8s.gcr.io/pause),它的主要作用是建立並共享程序名稱空間。

  2. 建立 Pod 規格中指定的臨時容器 Ephemeral Containers(Alpha 功能,預設不開啟),臨時容器是一種特殊的容器,該容器在現有 Pod 中臨時執行,以便完成使用者發起的操作,例如故障排查。 你可以使用臨時容器來檢查服務,而不是用它來構建應用程式。

  3. 建立 Pod 規格中指定的初始化容器 Init Containers,初始化容器是一種特殊容器,在 Pod 內的應用容器啟動之前執行。Init 容器可以包括一些應用映象中不存在的實用工具和安裝指令碼。

  4. 依次建立 Pod 規格中指定的常規容器 Containers。

參考

更多

更多經典示例請參考:https://github.com/jxlwqq/kubernetes-examples