1. 程式人生 > 其它 >建立一個 k8s pod,背後發生了什麼

建立一個 k8s pod,背後發生了什麼

本例使用 kubectl 建立、運行了一個 nginx pod:

kubectl run nginx --image=nginx --restart=Never

通過 tcpdump 抓包、分析,得到的互動流程如下圖所示:

sequenceDiagram autonumber participant C as kubectl participant AS as kube-apiserver participant S as kube-scheduler participant L as kubelet S ->>+ AS: [REQ] GET /api/v1/pods?watch=true<br>&fieldSelector="status.phase!=Succeeded,<br>status.phase!=Failed" AS -->>- S: [RESP]: 200 OK, chunked, wait for chunks... L ->>+ AS: [REQ] GET /api/v1/pods?watch=true<br>&fieldSelector="fieldSelector=spec.nodeName=node-1" AS -->>- L: [RESP]: 200 OK, chunked, wait for chunks... Note over C,L: After k8s setup C ->>+ AS: [REQ] POST /api/v1/namespaces/default/pods - nginx AS ->> S: [RESP-CHUNK]: Pod Added - nginx AS ->>- C: [RESP] 201 Created S ->>+ AS: [REQ] POST /api/v1/namespaces/default/pods/nginx/binding AS ->> L: [RESP-CHUNK]: Pod Added - nginx AS ->>- S: [RESP] 201 Created L ->>+ AS: [REQ] PUT /api/v1/namespaces/default/pods/nginx/status AS ->>- L: [RESP]: 200 OK

註解:

【1~4】為 k8s 啟動時就發生的步驟

【1】scheduler 啟動時向 apiserver 請求監聽所有pod的列表,使用了引數 fieldSelectorstatus.phase!=Succeeded,status.phase!=Failed ,表明對 phase 為 Succeeded 和 Failed 的 pod 不感興趣,排除在監聽物件之外。事實上 scheduler 對 phase 為 Pending 的 pod 更感興趣,因為剛建立的 pod 狀態為 Pending,而 scheduler 的主要職責就是把 Pending 狀態的 pod 排程到某個節點上,由該節點上的 kubelet 把 pod 執行起來。

【2】apiserver 返回的報文如下:

HTTP/1.1 200 OK
...
Transfer-Encoding: chunked

頭部 Transfer-Encoding: chunked 表示 response 的 body 是以 chunk 分塊的形式推送給 scheduler,當前沒有 chunk。換句話說,當 scheduler 請求監聽的pod列表有變動時,apiserver 會把相應的pod資訊推送給 scheduler,scheduler 只需保持連線、耐心等待就行。

【3】kubelet 啟動時 apiserver 請求監聽所有pod的列表,使用了引數 fieldSelectorfieldSelector=spec.nodeName=node-1

,表明只對 spec.nodeName 設定為 node-1 的 pod 感興趣。新建立的 pod 不會設定 spec.nodeName 欄位,經由 scheduler 排程處理後,pod 的 spec.nodeName 欄位會被設定為某個節點的名字,表明應由該節點執行 pod。本例中 kubelet 正是執行在節點 node-1 上,這就是使用引數 fieldSelectorfieldSelector=spec.nodeName=node-1 的意義,因為 kubelet 只對排程到 node-1 上的 pod 感興趣。

【4】返回的報文和【2】類似。

【5】對應使用者執行的kubectl run nginx --image=nginx --restart=Never命令,kubectl 請求 apiserver 建立一個 pod 物件,請求報文 body 如下:

{
  "kind": "Pod",
  "apiVersion": "v1",
  "metadata": {
    "name": "nginx",
    "creationTimestamp": null
  },
  "spec": {
    "containers": [
      {
        "name": "nginx",
        "image": "nginx"
      }
    ],
    "restartPolicy": "Never"
  },
  "status": {}
}

【6】由於【1】scheduler 啟動時監聽 pod 列表,然後新建立的 pod 滿足 scheduler 監聽條件,所以這個pod的資訊以 chunk 的形式推送到了 scheduler,對應【2】。

【7】pod 的資源建立後,apiserver 便立即返回了,無需等待 pod 執行。

【8】由於在【6】接收到新的 pod 的資訊,scheduler 經過一些決策,決定將 pod 排程到 node-1,因此向 apiserver 傳送對應的 pod binding 請求,在請求的body中指定了 node-1。

【9】apiserver 收到【8】的請求後,將 pod 的 spec.nodeName 欄位設定為 node-1,這剛好滿足了【3】kubelet 感興趣的 pod 條件,所以更新後的pod的資訊以 chunk 的形式推送到了 kubelet,對應【4】。

【10】apiserver 返回 pod binding 請求成功。

【11】由於在【9】接收到新的 pod 的資訊,kubelet 將 pod 拉起執行,同時將 pod 的最新資訊——包括 pod ip ,node 資訊,執行狀態等同步更新到 apiserver 。

【12】apiserver 返回 pod 資訊更新成功。自此流程結束。