建立靜態 Pod

靜態 Pod(Static Pods)由特定節點上的 kubelet 守護程序直接管理,而不被API 伺服器監視。與由控制平面管理的 Pod(例如Deployment)不同,kubelet 會監視每個靜態 Pod(並在其失敗時重新啟動它)。

靜態 Pod 總是繫結到特定節點上的一個Kubelet

kubelet 會自動嘗試為每個靜態 Pod 在 Kubernetes API 伺服器上建立一個映象 Pod。這意味著在節點上執行的 Pod 在 API 伺服器上是可見的,但不能從那裡控制。Pod 名稱將附加節點主機名,並帶有一個前導連字元。

準備工作

你需要擁有一個 Kubernetes 叢集,並且 kubectl 命令列工具必須配置為與你的叢集通訊。建議在至少有兩個不充當控制平面主機的節點的叢集上執行本教程。如果你還沒有叢集,可以使用 minikube 建立一個,或者使用這些 Kubernetes 操場之一。

要檢查版本,請輸入 kubectl version

本頁面假設你正在使用 CRI-O 執行 Pod,並且你的節點正在執行 Fedora 作業系統。其他發行版或 Kubernetes 安裝的說明可能會有所不同。

建立靜態 Pod

你可以使用檔案系統託管的配置檔案Web 託管的配置檔案來配置靜態 Pod。

檔案系統託管的靜態 Pod 清單

清單是特定目錄中 JSON 或 YAML 格式的標準 Pod 定義。在 kubelet 配置檔案中使用 staticPodPath: <目錄> 欄位,該欄位會定期掃描目錄並在 YAML/JSON 檔案出現/消失時建立/刪除靜態 Pod。請注意,kubelet 在掃描指定目錄時會忽略以點開頭的檔案。

例如,這是如何將一個簡單的 Web 伺服器作為靜態 Pod 啟動

  1. 選擇要執行靜態 Pod 的節點。在本例中是 my-node1

    ssh my-node1
    
  2. 選擇一個目錄,例如 /etc/kubernetes/manifests,並將 Web 伺服器 Pod 定義放在那裡,例如 /etc/kubernetes/manifests/static-web.yaml

    # Run this command on the node where kubelet is running
    mkdir -p /etc/kubernetes/manifests/
    cat <<EOF >/etc/kubernetes/manifests/static-web.yaml
    apiVersion: v1
    kind: Pod
    metadata:
      name: static-web
      labels:
        role: myrole
    spec:
      containers:
        - name: web
          image: nginx
          ports:
            - name: web
              containerPort: 80
              protocol: TCP
    EOF
    
  3. 在該節點上配置 kubelet,在 kubelet 配置檔案中設定 staticPodPath 值。
    有關更多資訊,請參閱透過配置檔案設定 Kubelet 引數

    一種替代且已棄用的方法是,透過命令列引數,配置該節點上的 kubelet 以查詢本地的靜態 Pod 清單。要使用此已棄用的方法,請使用以下引數啟動 kubelet:
    --pod-manifest-path=/etc/kubernetes/manifests/ 引數。

  4. 重啟 kubelet。在 Fedora 上,你可以執行

    # Run this command on the node where the kubelet is running
    systemctl restart kubelet
    

Web 託管的靜態 Pod 清單

Kubelet 會定期下載由 --manifest-url=<URL> 引數指定的檔案,並將其解釋為包含 Pod 定義的 JSON/YAML 檔案。與檔案系統託管的清單的工作方式類似,kubelet 會按計劃重新獲取清單。如果靜態 Pod 列表發生更改,kubelet 會應用這些更改。

要使用此方法

  1. 建立 YAML 檔案並將其儲存在 Web 伺服器上,以便你可以將該檔案的 URL 傳遞給 kubelet。

    apiVersion: v1
    kind: Pod
    metadata:
      name: static-web
      labels:
        role: myrole
    spec:
      containers:
        - name: web
          image: nginx
          ports:
            - name: web
              containerPort: 80
              protocol: TCP
    
  2. 透過使用 --manifest-url=<manifest-url> 執行 kubelet,在該選定節點上配置 kubelet 以使用此 Web 清單。在 Fedora 上,編輯 /etc/kubernetes/kubelet 以包含此行

    KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --manifest-url=<manifest-url>"
    
  3. 重啟 kubelet。在 Fedora 上,你可以執行

    # Run this command on the node where the kubelet is running
    systemctl restart kubelet
    

觀察靜態 Pod 的行為

當 kubelet 啟動時,它會自動啟動所有定義的靜態 Pod。由於你已經定義了一個靜態 Pod 並重新啟動了 kubelet,所以新的靜態 Pod 應該已經運行了。

你可以透過執行以下命令(在節點上)檢視正在執行的容器(包括靜態 Pod):

# Run this command on the node where the kubelet is running
crictl ps

輸出可能類似於

CONTAINER       IMAGE                                 CREATED           STATE      NAME    ATTEMPT    POD ID
129fd7d382018   docker.io/library/nginx@sha256:...    11 minutes ago    Running    web     0          34533c6729106

你可以在 API 伺服器上看到映象 Pod

kubectl get pods
NAME                  READY   STATUS    RESTARTS        AGE
static-web-my-node1   1/1     Running   0               2m

靜態 Pod 的標籤會傳播到映象 Pod。你可以像平常一樣透過選擇器等使用這些標籤。

如果你嘗試使用 kubectl 從 API 伺服器刪除映象 Pod,kubelet 不會刪除靜態 Pod

kubectl delete pod static-web-my-node1
pod "static-web-my-node1" deleted

你可以看到 Pod 仍在執行

kubectl get pods
NAME                  READY   STATUS    RESTARTS   AGE
static-web-my-node1   1/1     Running   0          4s

回到執行 kubelet 的節點,你可以嘗試手動停止容器。你會發現,過一段時間後,kubelet 會發現並自動重新啟動 Pod

# Run these commands on the node where the kubelet is running
crictl stop 129fd7d382018 # replace with the ID of your container
sleep 20
crictl ps
CONTAINER       IMAGE                                 CREATED           STATE      NAME    ATTEMPT    POD ID
89db4553e1eeb   docker.io/library/nginx@sha256:...    19 seconds ago    Running    web     1          34533c6729106

一旦你確定了正確的容器,就可以使用 crictl 獲取該容器的日誌

# Run these commands on the node where the container is running
crictl logs <container_id>
10.240.0.48 - - [16/Nov/2022:12:45:49 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nov/2022:12:45:50 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"
10.240.0.48 - - [16/Nove/2022:12:45:51 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.47.0" "-"

要了解有關使用 crictl 除錯的更多資訊,請訪問使用 crictl 除錯 Kubernetes 節點

靜態 Pod 的動態新增和刪除

執行中的 kubelet 會定期掃描已配置的目錄(在我們的示例中為 /etc/kubernetes/manifests)以查詢更改,並在此目錄中檔案出現/消失時新增/刪除 Pod。

# This assumes you are using filesystem-hosted static Pod configuration
# Run these commands on the node where the container is running
#
mv /etc/kubernetes/manifests/static-web.yaml /tmp
sleep 20
crictl ps
# You see that no nginx container is running
mv /tmp/static-web.yaml  /etc/kubernetes/manifests/
sleep 20
crictl ps
CONTAINER       IMAGE                                 CREATED           STATE      NAME    ATTEMPT    POD ID
f427638871c35   docker.io/library/nginx@sha256:...    19 seconds ago    Running    web     1          34533c6729106

下一步

上次修改於 2023 年 12 月 8 日上午 7:08 PST:反映 pod-manifest-path 引數已棄用的更改 (8a0a983d32)