返回文章列表

Kubernetes容器佈署與資源管理

本文介紹如何在 Kubernetes 叢集中佈署和管理容器,涵蓋使用 kubectl 命令操作 Pod、理解標籤和摘要、使用 YAML 檔案進行宣告式佈署、管理名稱空間、檢索 Pod 資訊和後設資料、埠轉發、容器內部操作以及標籤和註解的應用。

容器技術 DevOps

在 Kubernetes 環境中,佈署容器化應用程式需要熟悉核心概念和工具。本文將引導您使用 kubectl 命令佈署 Pod,並探討容器映象版本管理、資源組態和資訊檢索等關鍵環節,最後說明如何利用標籤和註解提升叢集管理效率。這些實務技巧將協助您更有效地管理 Kubernetes 叢集中的容器化應用程式。

$ kubectl run nginx-pod --image nginx:latest
$ kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
nginx-pod 1/1     Running   0          79s
$ kubectl delete pod nginx-pod
pod "nginx-pod" deleted
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:latest
$ kubectl apply -f nginx-pod.yaml
pod/nginx-pod created
$ kubectl describe pod nginx-pod
Name:         nginx-pod
Namespace:    default
...
$ kubectl port-forward pod/nginx-pod 8080:80
$ kubectl exec -it nginx-pod -- bash
root@nginx-pod:/# hostname
nginx-pod
$ kubectl delete pods nginx-pod

在Kubernetes中執行容器

要在Kubernetes叢集上建立Pod,您需要使用kubectl run命令。這是讓Pod在Kubernetes叢集上執行的最簡單、最快的方式。以下是該命令的呼叫方式:

$ kubectl run nginx-pod --image nginx:latest

在這個命令中,Pod的名稱被設定為nginx-pod。這個名稱很重要,因為它是指向Pod的指標:當您需要在這個Pod上執行更新或刪除命令時,您必須指定這個名稱來告訴Kubernetes應該對哪個Pod執行操作。--image標誌用於指定這個Pod將執行的容器。一旦叢集建立了Pod,就可以透過以下方式檢查其狀態:

$ kubectl get pods
NAME      READY   STATUS    RESTARTS   AGE
nginx-pod 1/1     Running   0          79s

這裡,您告訴Kubernetes根據Docker Hub上託管的nginx:latest容器映象構建一個Pod。這個nginx-pod Pod只包含一個根據nginx:latest映象的容器:您不能在這裡指定多個映象;這是命令式語法的限制。

標籤與摘要 - 確保映象一致性

在建立Pod時,您可能會遇到對標籤和摘要的參照。兩者都用於標識容器映象,但有一個關鍵區別:

  • 標籤:將標籤視為映象版本的人類可讀名稱。它們可以被更改為指向同一映象的不同版本,可能會導致意外行為。
  • 摘要:這些是映象的唯一指紋,確保您始終參照確切所需的版本。這對於安全性和可重複性至關重要,特別是在潛在的軟體供應鏈攻擊面前。

例如,您可以使用nginx@sha256:1445eb9c6dc5e9619346c836ef6fbd6a95092e4663f27dcfce116f051cdbd232(摘要)而不是nginx:latest(標籤)。您可以從註冊表本身或使用podman manifest inspect nginx:latest命令取得容器映象的摘要資訊。

內容解密:

此段落說明瞭在建立Pod時,如何使用標籤和摘要來確保容器映象的一致性。其中,標籤容易被更改,可能導致非預期的結果;而摘要則是唯一的,能夠保證所參照的映象版本是正確的。

使用宣告式語法建立Pod

使用宣告式語法建立Pod也很簡單。您需要建立一個包含Pod定義的YAML檔案,並使用kubectl apply -f命令將其應用到Kubernetes叢集。

首先,您需要刪除之前建立的同名Pod:

$ kubectl delete pod nginx-pod
pod "nginx-pod" deleted

以下是nginx-pod.yaml檔案的內容,您可以在本地工作站上建立它:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:latest

內容解密:

此YAML檔案定義了一個名為nginx-pod的Pod,其中包含一個名為nginx-container的容器,該容器根據nginx:latest映象。檔案的結構清晰,易於理解。

一旦儲存了nginx-pod.yaml檔案,就可以執行以下命令來建立Pod:

$ kubectl apply -f nginx-pod.yaml
pod/nginx-pod created

如果叢集中已經存在一個名為nginx-pod的Pod,此命令將失敗。嘗試編輯YAML檔案以更新Pod的名稱,然後再次應用它。

Kubernetes中的名稱空間

如果在建立資源時省略指定名稱空間,則預設為default名稱空間。

讀取Pod的資訊和後設資料

此時,您應該在Kubernetes叢集上執行了一個Pod。在這裡,我們將嘗試讀取其資訊。在任何時候,我們都需要能夠檢索和讀取有關在Kubernetes叢集上建立的資源的資訊;對於Pod來說尤其如此。讀取Kubernetes叢集可以使用兩個kubectl命令:kubectl getkubectl describe

  • kubectl getkubectl get命令是一個列表操作;您使用此命令來列出一組物件。例如,列出叢集中的Pod:
$ kubectl get pods
  • kubectl describekubectl describe命令則用於檢索一個特定物件的完整資訊集。例如,檢索之前建立的Pod的資訊:
$ kubectl describe pod nginx-pod
Name:         nginx-pod
Namespace:    default
...(為簡潔起見,已刪除部分內容)...
Containers:
  nginx-container:
    Container ID:   containerd://3afbbe30b51b77994df69f4c4dbefb02fc304efb2bf0f5bdb65a65

內容解密:

這兩個命令用於取得Pod的資訊。kubectl get用於列出多個Pod,而kubectl describe則提供了一個特定Pod的詳細資訊。

在 Kubernetes 中執行容器

取得 Pod 詳細資訊

要取得 Kubernetes 中 Pod 的詳細資訊,可以使用 kubectl describe 命令。這個命令提供了關於特定 Pod 的豐富資訊,包括 Pod 名稱、名稱空間、容器詳細資訊、Pod 狀態和相關事件。

$ kubectl describe pod nginx-pod

輸出範例:

Name:         nginx-pod
Namespace:    default
...
Conditions:
  Type              Status
  PodReadyToStartContainers   True
  Initialized                 True
...
Events:
  Type    Reason     Age   From               Message
  
---
-    
---
---
     
---
-  
---
-               
---
-
---
  Normal  Created    112s  kubelet            Created container nginx-container
  Normal  Started    112s  kubelet            Started container nginx-container

從輸出中可以讀取到許多有用的資訊,包括:

  • Pod 名稱和名稱空間
  • 容器詳細資訊(例如映像名稱、資源請求/限制和目前狀態)
  • Pod 狀態(例如執行中、擱置中或當機迴圈)
  • 相關事件(例如建立、重新啟動或錯誤)

以 JSON 或 YAML 列出物件

kubectl 命令列工具提供了 -o--output 選項,允許自定義輸出格式。預設情況下,kubectl get pods 命令以格式化的方式傳回叢集中的 Pod 清單。可以使用 -o 選項以 JSON 或 YAML 格式檢索此資訊。

$ kubectl get pods --output yaml  # 以 YAML 格式輸出
$ kubectl get pods --output json  # 以 JSON 格式輸出

如果知道 Pod 名稱,也可以取得特定的 Pod:

$ kubectl get pods <POD_NAME> -o yaml
# 或
$ kubectl get pods <POD_NAME> -o json

備份資源

可以使用 -o 選項備份 Kubernetes 資源。例如,如果使用命令式方法建立 Pod,可以使用以下命令檢索其 YAML 宣告檔案:

$ kubectl get pods/nginx-pod -o yaml > nginx-pod-output.yaml

這將建立一個 YAML 檔案,其中包含 nginx-pod 資源的目前組態。可以將輸出檔案與原始 YAML 宣告進行比較,以分析差異。

從外部存取 Pod

預設情況下,Kubernetes 叢集不會將 Pod 對外公開。要存取 Pod,可以使用 kubectl port-forward 命令,將本地埠轉發到 Pod 中的特定埠。

$ kubectl port-forward pod/nginx-pod 8080:80

此命令將本地埠 8080 轉發到 Pod 中的埠 80。現在,可以在瀏覽器中存取 http://localhost:8080 以檢視 NGINX 預設頁面。

程式碼解析:

$ kubectl port-forward pod/nginx-pod 8080:80

內容解密:

  1. kubectl port-forward:此命令用於將本地埠轉發到 Kubernetes Pod 中的特定埠。
  2. pod/nginx-pod:指定要轉發到的 Pod 名稱。
  3. 8080:80:將本地埠 8080 對應到 Pod 中的埠 80。

完成測試後,可以使用 Ctrl + C 命令結束埠轉發任務。

取得更多資訊

-o wide 格式可以用於擴充套件預設輸出,以新增更多資料。例如,在 Pods 物件上使用此選項時,將獲得 Pod 所執行的 worker 節點名稱:

$ kubectl get pods -o wide

輸出範例:

NAME        READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
nginx-pod   1/1     Running   0          15m   10.244.0.4   minikube   <none>           <none>

此外,-o 選項還支援其他引數,例如 jsonpath,允許直接在 JSON 檔案上執行排序操作,以檢索特定資訊。

Plantuml 圖示說明 Pod 與 Service 的關係:

@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle

title Kubernetes容器佈署與資源管理

package "Kubernetes Cluster" {
    package "Control Plane" {
        component [API Server] as api
        component [Controller Manager] as cm
        component [Scheduler] as sched
        database [etcd] as etcd
    }

    package "Worker Nodes" {
        component [Kubelet] as kubelet
        component [Kube-proxy] as proxy
        package "Pods" {
            component [Container 1] as c1
            component [Container 2] as c2
        }
    }
}

api --> etcd : 儲存狀態
api --> cm : 控制迴圈
api --> sched : 調度決策
api --> kubelet : 指令下達
kubelet --> c1
kubelet --> c2
proxy --> c1 : 網路代理
proxy --> c2

note right of api
  核心 API 入口
  所有操作經由此處
end note

@enduml

此圖示展示了 Kubernetes Cluster 中 Pod 和 Service 的關係,以及如何透過 Service 和 Load Balancer 將 Pod 對外公開。

重點整理:

  1. 使用 kubectl describe 命令可以取得 Pod 的詳細資訊。
  2. 可以使用 -o--output 選項自定義 kubectl 命令的輸出格式。
  3. 使用 kubectl port-forward 命令可以將本地埠轉發到 Pod 中的特定埠,以便從外部存取 Pod。
  4. 可以使用 -o wide 格式擴充套件預設輸出,以新增更多資料。

在 Kubernetes 中執行容器

存取 Pod 中的容器

當 Pod 被啟動後,您可以存取它所包含的容器。在 Docker 中,用於在執行中的容器中執行命令的指令稱為 docker exec。Kubernetes 透過一個名為 kubectl exec 的指令複製了這種行為。使用以下指令來存取我們之前啟動的 nginx-pod 中的 NGINX 容器:

$ kubectl exec -it nginx-pod -- bash
root@nginx-pod:/# hostname
nginx-pod

執行此指令後,您將進入 NGINX 容器的內部。您可以像操作其他容器一樣在這裡進行任何操作。前述指令假設您嘗試存取的容器中已安裝 bash 二進位制檔案。否則,許多容器通常會安裝 sh 二進位制檔案,您可以使用它來存取容器。不要害怕使用完整的二進位制檔案路徑,例如:

$ kubectl exec -it nginx-pod -- /bin/bash

完成測試後,使用 exit 指令離開容器的 bash 環境:

root@nginx-pod:/# exit
exit

現在,讓我們來瞭解如何從 Kubernetes 叢集中刪除 Pod。

刪除 Pod

刪除 Pod 非常簡單。您可以使用 kubectl delete 指令來完成此操作。您需要知道要刪除的 Pod 名稱。在我們的例子中,Pod 的名稱是 nginx-pod。執行以下指令:

$ kubectl delete pods nginx-pod
# 或...
$ kubectl delete pods/nginx-pod

如果您不知道 Pod 的名稱,請記得執行 kubectl get pods 指令來檢索 Pod 清單並找到您要刪除的 Pod。

重點提示:容器中的安全性和非 root 使用者

一般建議使用非 root 使用者執行容器,以限制潛在漏洞造成的損害。如果漏洞被利用,非 root 使用者的系統存取許可權較低,可以減少影響。同時,遵循最小許可權原則,只授予容器正常運作所需的許可權,可以最小化其攻擊面。我們將在第 18 章「Kubernetes 中的安全性」中探討安全上下文。

如果您使用宣告式語法建立了 Pod,並且仍然擁有其 YAML 設定檔,您可以在不知道容器名稱的情況下刪除 Pod,因為容器名稱包含在 YAML 檔案中。執行以下指令使用宣告式語法刪除 Pod:

$ kubectl delete -f nginx-pod.yaml

執行此指令後,Pod 將以相同的方式被刪除。

為 Pod 新增標籤和註解

現在,我們將討論 Kubernetes 中的另一個關鍵概念:標籤和註解。標籤是可以附加到 Kubernetes 物件的鍵值對。標籤用於使用由您定義的鍵值對來標記 Kubernetes 物件。一旦您的 Kubernetes 物件被標記,您就可以建立自定義查詢以根據它們所持有的標籤檢索特定的 Kubernetes 物件。

什麼是標籤?為什麼我們需要它們?

您可以為物件定義的標籤沒有特定的規則。這些標籤是屬性,將允許您在 Kubernetes 叢集中組織您的物件。例如,您可以為某些 Pod 新增一個名為 environment = prod 的標籤,然後使用 kubectl get pods 指令列出該環境中的所有 Pod。因此,您可以使用一個指令列出屬於生產環境的所有 Pod:

$ kubectl get pods --label "environment=production"

如您所見,可以使用 --label 引數實作此目的,該引數可以使用其縮寫 -l

$ kubectl get pods -l "environment=production"

此指令將列出所有持有名為 environment 且值為 production 的標籤的 Pod。當然,在我們的例子中,由於我們之前建立的 Pod 都沒有持有此標籤,因此不會找到任何 Pod。

使用標籤組織叢集和建立關係

您不僅可以使用標籤組織叢集,還可以在不同的 Kubernetes 物件之間建立關係。您會注意到,一些 Kubernetes 物件會讀取某些 Pod 所攜帶的標籤,並根據它們攜帶的標籤對它們執行某些操作。如果您的 Pod 沒有標籤或標籤命名錯誤或包含錯誤的值,則其中一些機制可能無法按預期工作。

註解與標籤的不同之處

Kubernetes 也使用另一種型別的後設資料,稱為註解。註解與標籤非常相似,也是鍵值對。然而,註解與標籤的使用方式不同。標籤旨在識別資源並在它們之間建立關係,而註解用於提供有關定義它們的資源的上下文資訊。

例如,當您建立一個 Pod 時,您可以新增一個包含支援團隊電子郵件地址的註解,以便在應用程式無法正常運作時聯絡該團隊。此資訊適合放在註解中,但與標籤無關。

雖然強烈建議您盡可能定義標籤,但您可以省略註解:它們對於叢集的操作而言,不如標籤那麼重要。但是,請注意,某些 Kubernetes 物件或第三方應用程式經常讀取註解並將其用作組態。在這種情況下,它們對註解的使用將在其檔案中明確說明。

重點整理

  • 使用 kubectl exec 指令可以存取正在執行的容器。
  • 使用 kubectl delete 指令可以刪除 Pod。
  • 標籤用於組織和管理 Kubernetes 物件。
  • 註解提供有關資源的額外資訊,但不如標籤重要。
  • 正確使用標籤和註解有助於保持叢集資源的有序和可管理性。