在 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 get和kubectl describe。
kubectl get:kubectl get命令是一個列表操作;您使用此命令來列出一組物件。例如,列出叢集中的Pod:
$ kubectl get pods
kubectl describe:kubectl 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
內容解密:
kubectl port-forward:此命令用於將本地埠轉發到 Kubernetes Pod 中的特定埠。pod/nginx-pod:指定要轉發到的 Pod 名稱。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 對外公開。
重點整理:
- 使用
kubectl describe命令可以取得 Pod 的詳細資訊。 - 可以使用
-o或--output選項自定義kubectl命令的輸出格式。 - 使用
kubectl port-forward命令可以將本地埠轉發到 Pod 中的特定埠,以便從外部存取 Pod。 - 可以使用
-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 物件。
- 註解提供有關資源的額外資訊,但不如標籤重要。
- 正確使用標籤和註解有助於保持叢集資源的有序和可管理性。