K8s kubelet 與 Pod 執行流程
K8s kubelet 與 Pod 執行流程的重點整理。
K8s kubelet 與 Pod 執行流程
Big Picture:從 k run 到容器執行
先提交 Pod → Scheduler 選 Node → 該 Node 的 kubelet 協調 runtime 準備 image 並啟動容器。 API Server、Scheduler 都不負責下載應用程式的 image。
alias k=kubectl
k run nginx --image=nginx
這條指令建立的是 Pod;建立成功只表示 API Server 接受了資源,不表示容器已經啟動。
flowchart TB
U["你執行<br/>k run nginx --image=nginx"]
subgraph CP["Control Plane"]
direction TB
API["① API Server 收到建立 Pod 的請求"]
AUTH["② 身分驗證與授權<br/>你是誰?能不能建立 Pod?"]
ADM["③ Admission<br/>補預設值、解析 PriorityClass<br/>檢查 LimitRange、ResourceQuota 等"]
SAVE["④ 保存 Pod 物件<br/>尚未指派 Node"]
ETCD[("etcd<br/>保存叢集資料")]
subgraph S["⑤ Scheduler:決定放哪台 Node"]
Q["QueueSort<br/>先處理哪個 Pod"]
F["PreFilter → Filter<br/>資源 requests、Affinity<br/>Taint/Toleration 等檢查"]
PF["PostFilter<br/>嘗試搶占等補救,之後重試"]
SC["PreScore → Score<br/>替合格 Node 評分,選一台"]
R["Reserve → Permit<br/>暫記資源、等待或放行"]
B["PreBind → Bind → PostBind<br/>完成綁定與收尾"]
Q --> F
F -->|"沒有合格 Node"| PF
PF -.->|"重新排隊"| Q
F -->|"有合格 Node"| SC
SC --> R --> B
end
BOUND["⑥ 透過 API Server 保存綁定結果<br/>例如 spec.nodeName = node02"]
API --> AUTH --> ADM --> SAVE
SAVE -->|"由 API Server 寫入"| ETCD
SAVE -->|"Scheduler 經 API Server watch<br/>發現尚未指派的 Pod"| Q
B --> BOUND
BOUND -->|"由 API Server 寫入"| ETCD
end
subgraph NODE["被選中的 Node:node02"]
direction TB
K["⑦ kubelet 經 API Server watch<br/>發現這個 Pod 已指派給自己"]
PREP["⑧ 準備 Pod 執行環境<br/>網路、儲存與所需映像"]
RT["Container Runtime<br/>例如 containerd,透過 CRI 配合 kubelet"]
RUN["⑨ 建立並啟動容器<br/>執行 nginx"]
STATUS["⑩ kubelet 持續檢查並回報狀態"]
K --> PREP --> RT --> RUN --> STATUS
end
REG[("Image Registry<br/>例如 Docker Hub")]
U --> API
BOUND --> K
RT <-->|"依 imagePullPolicy<br/>需要時拉取 image"| REG
STATUS -.->|"透過 API Server 更新 Pod 狀態"| API
圖中箭頭表示處理關係:Scheduler 與 kubelet 主動透過 API Server watch 狀態,並不是 API Server 主動派工,也不是 Scheduler 直接把 Pod 傳給 kubelet。Bind 階段完成綁定的保存,PostBind 才做成功後的收尾;圖中為了閱讀將它們放在同一組。Node 端的網路、儲存與 image 準備是簡化呈現,不代表所有動作都嚴格依單一路徑執行。
| 元件 | 工作 |
|---|---|
| API Server/Admission | 接受請求,驗證、授權、檢查與補值,再保存 Pod 定義 |
| Scheduler | 依 Pod 需求與 Node 狀態,決定放在哪台 Node |
| kubelet | 在被選中的 Node 上協調 Pod 執行、檢查健康狀態並回報 |
| Container Runtime | 配合 kubelet 拉取映像、建立並啟動容器 |
API Server 的處理階段、Scheduler 的排程階段與 Node 上的執行階段要分開理解;元件分工見 Kubernetes Components。
Scheduler 的詳細階段、節點選擇、PriorityClass 與多排程器設定統一見 K8s 排程:Scheduler、PriorityClass、Affinity、Taint 與 Toleration。
image 什麼時候下載?
Scheduler 不需要先下載 image 才能排程。ImageLocality 可以利用 Node 回報的映像資訊評分;實際拉取是由選中 Node 上的 kubelet 協調 runtime 執行,是否需連到 registry 或下載內容取決於 imagePullPolicy 與本機快取。Always 也不代表每次都重新下載所有 layers;若對應內容已快取,可以重用。詳見 Images。
用這張圖定位錯誤
| 現象 | 先看哪個階段 |
|---|---|
| Forbidden/Quota 超標,Pod 未建立 | API Server 的授權、Admission;直接建立 Pod 被拒絕時,不會有新 Pod 物件 |
| Pending,Events 有 FailedScheduling | Scheduler 找不到合適 Node |
| 已指派 Node,但 ImagePullBackOff | Node 端拉取 image 失敗,排程已完成 |
| 已指派 Node,但 FailedCreatePodSandBox/FailedMount | Node 端的 sandbox、網路或儲存準備 |
| Running,但尚未 Ready | 容器已啟動,檢查 readiness、容器狀態與應用健康 |
若提交的是 Deployment,Deployment 本身可能建立成功,但它的控制器建立 Pod 時遭 Admission 拒絕;這時也要查 Deployment/ReplicaSet 的 Events。
Admission Controller:資源進入叢集前的關卡
Admission Controller 在 API Server 完成身分驗證與授權後、資源保存前,檢查或修改請求中的物件。它處理建立、修改、刪除等操作,不攔截一般 get/list/watch 讀取。
提交請求 → Authentication → Authorization(例如 RBAC)
→ Mutating Admission → Validating Admission → 保存物件
| 階段 | 問的問題 | 例子 |
|---|---|---|
| Authentication | 你是誰? | 依憑證或 token 識別身分 |
| Authorization | 你有權執行這個操作嗎? | RBAC 是否允許建立 Pod |
| Mutating Admission | 要補上或修改什麼設定? | 依 LimitRange 補預設 request/limit;Priority admission 解析優先權 |
| Validating Admission | 最後內容符合政策嗎? | 檢查配額、資源設定範圍等 |
Admission 先 mutation、再 validation;任一階段都可能拒絕請求。LimitRange 是規則物件,LimitRanger 是執行它的 admission plugin,能補值也能驗證;ResourceQuota 的 admission plugin 則執行配額檢查。
這裡的 Controller 不代表一定有另一個獨立 Pod:內建 admission plugins 是 kube-apiserver 裡的程式碼。若使用 Admission Webhook,API Server 才會呼叫另外部署的 webhook 服務做對應檢查或修改。
與 Scheduler 分清楚 Admission 問「這份物件能不能被接受、需要補什麼」;Scheduler 問「已接受的 Pod 能排到哪台 Node」。直接建立 Pod 被 Admission 拒絕時,不會有新 Pod 物件;Scheduler 找不到位置時,Pod 已存在,通常是 Pending 並有 FailedScheduling 事件。
ImagePolicyWebhook:映像政策驗證小抄
ImagePolicyWebhook 屬於 Validating Admission:API Server 將映像資訊交給外部政策後端決定允許/拒絕,本身不會自動做漏洞掃描。它不是通用的 ValidatingAdmissionWebhook plugin;後者通常搭配 ValidatingWebhookConfiguration,不能把兩種設定混用。
| 檢查點 | 要記住什麼 |
|---|---|
| 啟用 plugin | 在既有 --enable-admission-plugins 清單加入 ImagePolicyWebhook,保留原項目 |
| 載入設定 | --admission-control-config-file 指向 AdmissionConfiguration |
| 後端連線 | imagePolicy.kubeConfigFile 指向政策後端的 kubeconfig,含 HTTPS、CA 與必要憑證 |
| 檔案可見性 | 設定、kubeconfig、憑證必須都能從 API Server 容器內讀到;確認 hostPath/volumeMounts |
| 後端故障 | defaultAllow: false 拒絕放行;true 容許故障時放行,依題意設定 |
這兩個 API Server 啟動參數是最重要的辨識點:
# kube-apiserver 的 command 片段;保留環境原有的 plugins
- --enable-admission-plugins=NodeRestriction,ImagePolicyWebhook
- --admission-control-config-file=/etc/kubernetes/imgvalidation/admission-configuration.yaml
在 kubeadm 常見的 static Pod 環境,修改 /etc/kubernetes/manifests/kube-apiserver.yaml 後,kubelet 偵測變更並重建 API Server。備份放在 manifests 目錄之外,避免也被當作 manifest 讀取。
kubectl get pods -n kube-system
這是查詢 kube-system 中的 Pod 狀態,不是更新 namespace,也不是這條指令觸發重啟。該 namespace 包含控制平面與系統元件,所以到這裡確認 API Server 是否恢復;要驗證政策生效,仍須測試允許與禁止的映像。
API Server 起不來時,在控制平面 Node 查 runtime,不依賴 kubectl:
sudo crictl ps -a --name kube-apiserver
sudo crictl logs <剛查到的容器ID>
舊容器 ID 可能已被清理,要重新查。優先看 YAML/參數錯誤、掛載路徑與憑證;若 API 已回應 Unauthorized,轉查用戶端身分與 --client-ca-file,不能把它直接當成映像政策拒絕。--client-ca-file 用於驗證連進 API Server 的用戶端憑證,與 image policy 後端 kubeconfig 裡的 CA 用途不同。
參考:ImagePolicyWebhook 設定、crictl 排錯。
kubelet 的位置與責任
kubelet 是每個 Node 上的節點代理程式。Node 是執行工作負載的實體機或虛擬機,以及 Kubernetes 中對應的資源物件;kubelet 是其上的程式,兩者不是同義詞。
Scheduler 決定 Pod 要放在哪台 Node;kubelet 持續協調已指派到本機的 Pod,透過 CRI 呼叫 containerd、CRI-O 等 runtime 建立 Pod sandbox、啟動及停止容器,並回報狀態。
flowchart TD
U[kubectl 提交 Pod] --> A[API Server]
S[Scheduler] -->|寫入節點指派結果| A
A -->|kubelet watch 本機 Pod| K[kubelet]
K -->|CRI| R[Container Runtime]
R --> C[Containers]
R -->|呼叫 CNI plugin| N[Pod 網路]
K -->|協調 CSI Node plugin| V[Volume 掛載]
K -->|回報狀態| A
這是一般由 API Server 管理的 Pod 流程;static Pod 可由 kubelet 讀取本機 manifest 管理。
| 功能 | 主要責任 |
|---|---|
| Pod 排程 | kube-scheduler |
| 容器生命週期 | kubelet 透過 CRI 請 runtime 執行 |
| 健康檢查 | kubelet 管理 startup、liveness、readiness probes |
| Pod 網路設定 | Linux 上通常由 CRI runtime 呼叫 CNI plugin |
| Volume 掛載 | kubelet 協調 CSI Node plugin 與 runtime |
| Service 轉送 | kube-proxy,或具備替代能力的網路實作 |
readiness 失敗會影響 Pod 是否作為 Service 的就緒後端;liveness 失敗可能觸發容器重啟;startup probe 成功前會延後其他兩類探測。
元件責任參考 Kubernetes Components。容器層延伸至 K8s Container Runtime 與 dockershim 遷移,網路與儲存分別見 K8s CNI 比較:Cilium、Calico 與 Flannel、K8s CSI、PV、PVC 與雲端儲存。
API 與應用設定
「No hidden internal APIs」可以理解為核心元件透過 API Server 存取 Kubernetes 資源,外部工具也能在授權範圍內使用這些 API。這不代表所有元件的所有通訊都經 API Server,例如 kubelet 與 runtime 使用 CRI。
「Meet users where they are」是配合既有應用的使用方式。應用可以從環境變數或掛載檔案讀取 ConfigMap、Secret,不必為此自行呼叫 Kubernetes API。Secret 的 base64 編碼本身不是加密。
檢查方向
alias k=kubectl
k get nodes -o wide
k get po -A -o wide
k describe po <pod-name> -n <namespace>
先區分 Pending 是排程問題,還是已分配 Node 後卡在 image pull、sandbox/network、volume mount 等階段。Node 上的 kubelet 服務名稱依安裝方式不同,不把一般 systemd 的服務名稱直接套用到 MicroK8s。