什么是 Kubernetes Pod?用實際例子解釋
Kubernetes(簡稱K8S)是一個開源的容器編排平臺,用于自動化容器化應用的部署、擴展和管理。在Kubernetes中,Pod是最小的部署單元。理解Pod的概念對于掌握Kubernetes至關(guān)重要。本篇文章將詳細解釋什么是Kubernetes Pod,并通過實際例子幫助讀者更好地理解這一概念。
一、什么是 Kubernetes Pod?
在了解 Kubernetes Pod 概念之前,先來了解容器容器,眾所周知,是一個自包含的環(huán)境,用于打包應用程序及其依賴項。通常,一個容器運行單個進程(盡管也有方法可以運行多個進程)。每個容器都有一個IP地址,并且可以附加存儲卷以及控制CPU和內(nèi)存資源等。這些都是通過命名空間和控制組(namespaces and control groups)的概念實現(xiàn)的。
Kubernetes 是一個用于部署、擴展和管理容器化應用程序的容器編排系統(tǒng),它有自己運行容器的方式,我們稱之為 Pod。Pod 是 Kubernetes 中最小的可部署單元,代表一個應用程序的單個實例。
例如,如果你想運行 Nginx 應用程序,你可以將它運行在一個 Pod 中。
1.那么,Pod 與容器有何不同呢?
容器是一個單獨的單位。然而,Pod 可以包含多個容器。你可以將 Pod 想象成一個可以同時容納一個或多個容器的盒子。
Pod 提供了更高層次的抽象,允許你將多個容器作為一個單元進行管理。在這里,每個容器不再單獨獲得 IP 地址,而是 Pod 獲得一個唯一的 IP 地址,并且運行在 Pod 內(nèi)的容器通過 localhost 在不同端口上相互連接。
這意味著 Kubernetes Pod 內(nèi)的容器共享以下內(nèi)容:
- 網(wǎng)絡命名空間:Pod 內(nèi)的所有容器通過 localhost 進行通信。
- IPC 命名空間:所有容器使用共享的進程間通信命名空間。
- UTS 命名空間:所有容器共享相同的主機名。
2.Pod 內(nèi)的容器不共享什么?
- 默認情況下,PID 命名空間不共享,但 Kubernetes 提供選項,通過 shareProcessNamespace 選項在 Pod 內(nèi)啟用進程共享。
- 掛載命名空間不在容器之間共享。每個容器都有自己的私有文件系統(tǒng)和目錄。然而,Pod 掛載的存儲卷在容器之間共享。
總的來說,你需要了解以下關(guān)于 Pod 的信息:
- Pod 是 Kubernetes 中最小的可部署單元。
- Pod 具有短暫性;它們可以被創(chuàng)建、刪除和更新。
- 一個 Pod 可以有多個容器;沒有限制一個 Pod 中可以運行多少個容器。
- 每個 Pod 都有一個唯一的 IP 地址。
- Pod 之間通過 IP 地址進行通信。
- Pod 內(nèi)的容器使用 localhost 通過不同的端口進行連接。
- 在 Pod 內(nèi)運行的容器應該有不同的端口號,以避免端口沖突。
- 你可以為 Pod 內(nèi)運行的每個容器設置 CPU 和內(nèi)存資源。
- Pod 內(nèi)的容器共享相同的存儲卷掛載。
- Pod 內(nèi)的所有容器都調(diào)度到同一個節(jié)點上;它不能跨多個節(jié)點。
- 如果有多個容器,在 Pod 啟動期間,所有主要容器并行啟動。而 Pod 內(nèi)的 init 容器按順序運行。
二、Pod YAML
現(xiàn)在我們已經(jīng)對 Pod 有了基本的了解,接下來看看如何定義 Pod。Pod 是原生的 Kubernetes 對象,如果你想創(chuàng)建一個 Pod,需要以 YAML 格式聲明 Pod 的需求。你也可以使用 kubectl 命令創(chuàng)建 Pod,這將在后面的主題中介紹。
以下是一個創(chuàng)建 Nginx Web 服務器 Pod 的 Pod YAML 示例。這個 YAML 文件只是一個 Pod 的聲明性期望狀態(tài)。
apiVersion: v1
kind: Pod
metadata:
name: web-server-pod
labels:
app: web-server
environment: production
annotations:
description: This pod runs the web server
spec:
containers:
- name: web-server
image: nginx:latest
ports:
- containerPort: 80
讓我們來了解這個 Pod YAML。一旦你理解了基本的 YAML 格式,就會更容易操作 Pod 和相關(guān)對象,如 Deployment、DaemonSet、StatefulSet 等。
每個 Kubernetes 對象都有一些通用的參數(shù)。這些參數(shù)的值會根據(jù)我們創(chuàng)建的對象類型而變化。讓我們看看 Kubernetes Pod 對象。
我們現(xiàn)在已經(jīng)看到了一個基本的Pod YAML清單。需要注意的是,這個清單文件支持許多參數(shù)。我們將逐步探索這些額外的參數(shù)與實踐的方法。
現(xiàn)在我們對Pod有了一些基本的了解,讓我們創(chuàng)建一個Pod。
三、創(chuàng)建Pod
你可以用兩種方法創(chuàng)建pod:
- 使用kubectl命令式命令:主要用于學習和測試目的。命令式命令有其自身的局限性。
- 聲明式方法:使用YAML方式。在開發(fā)項目時,YAML清單文件用于部署pods。
讓我們看看這兩個方式。我們將使用以下內(nèi)容創(chuàng)建一個NGINX pod:
- pod的名稱是web-server-pod
- 它應該有標簽:app: web-server和environment: production
- 添加一個注釋來描述pod。
- 使用nginx:1.14.2容器鏡像。
- 暴露集裝箱端口80。
方法1:使用Kubectl命令創(chuàng)建Pod
對于討論的pod需求,這里是kubectl命令。
kubectl run web-server-pod \
--image=nginx:1.14.2 \
--restart=Never \
--port=80 \
--labels=app=web-server,environment=production \
--annotations description="This pod runs the web server"
在這里,pod被部署在默認命名空間中。你可以獲得部署的pod kubectl的狀態(tài)。
kubectl get pods
部署pod后,您將看到pod的運行狀態(tài),如下所示。在我們的例子中,pod中只有一個容器。所以它顯示1/1就緒并運行。
如果你想知道運行pod的所有細節(jié),可以使用kubectl describe pod。
kubectl describe pod web-server-pod
在下面的輸出中,你可以看到pod的所有細節(jié)。它的IP地址、命名空間、容器細節(jié)、QoS類等。
這里是描述命令顯示的所有重要pod信息的圖形視圖。
現(xiàn)在讓我們使用以下命令刪除pod。
kubectl delete pod web-server-pod
方法2:使用聲明式Y(jié)AML創(chuàng)建Pod
在實際項目中,你將不得不通過聲明的方法來創(chuàng)建pods。
讓我們看看如何使用YAML清單文件創(chuàng)建pod。
創(chuàng)建名為nginx的文件。內(nèi)容如下:
apiVersion: v1
kind: Pod
metadata:
name: web-server-pod
labels:
app: web-server
environment: production
annotations:
description: This pod runs the web server
spec:
containers:
- name: web-server
image: nginx:1.14.2
ports:
- containerPort: 80
現(xiàn)在,要部署清單文件,您需要使用文件名執(zhí)行以下kubectl命令:
kubectl create -f nginx.yaml
我們應該記住創(chuàng)建YAML時的每個參數(shù)嗎?不用。你可以使用--dry-run標志創(chuàng)建YAML文件:
kubectl run nginx-pod --image=nginx:1.14.2 --dry-run=client -o yaml
四、訪問在 Pod 中運行的應用程序
現(xiàn)在我們有了一個運行中的pod和Nginx web服務器。整個想法是部署和訪問在pod中運行的應用程序。
Kubectl提供了一個port-forward命令來從本地工作站訪問Kubernetes集群中運行的pods。
我們有一個名為web-server-pod的運行pod。讓我們通過port-forward命令訪問它。
現(xiàn)在,如果您打開瀏覽器并訪問http://localhost:8080,您應該會看到如下所示的Nginx主頁。網(wǎng)頁由我們的Nginx web服務器pod提供服務。
現(xiàn)在你可以按CTRL+C斷開端口轉(zhuǎn)發(fā)。
以下是運行kubectl port-forward時發(fā)生的情況:
- Kubectl綁定本地系統(tǒng)中的指定端口。在我們的例子中是8080。
- 然后,它與Kubernetes集群API通信,以建立到所需節(jié)點的隧道(單個HTTP連接),然后到指定的pod和容器端口(80)。
注意:kubectl端口轉(zhuǎn)發(fā)更多的是一個調(diào)試實用程序。你需要使用Kubernetes服務對象來公開在pod中運行的應用程序。我們將在另一個博客中實際地研究Kubernetes service 的概念。
五、訪問 Pod Shell
我們已經(jīng)學習了如何訪問在pod中運行的應用程序。
現(xiàn)在如果你想進入Pod shell怎么辦?
有許多用例需要終端訪問pod。一個主要用例是調(diào)試和故障排除。
這就是kubectl exec命令派上用場的地方。
您可以使用以下命令訪問web-server-pod的shell。
kubectl exec -it web-server-pod -- /bin/sh
在下面的輸出中,我正在pod內(nèi)執(zhí)行whoami命令。
六、Pod 的生命周期
關(guān)于pod你應該知道的另一個重要概念是它的生命周期。pod通常由ReplicaSet controller、Deployment controller等控制器管理。當您使用YAML創(chuàng)建單個pod時,它不受任何控制器的管理。在這兩種情況下,pod都會經(jīng)歷不同的生命周期階段。Pod的生命周期包括以下幾個階段:
- Pending:Pod已被Kubernetes API Server接受,但還沒有被調(diào)度到Node上。
- Running:Pod已被調(diào)度到Node上,所有容器都已啟動。
- Succeeded:Pod中的所有容器都正常終止,且不會再被重啟。
- Failed:Pod中的某個容器意外終止,且不會再被重啟。
- Unknown:由于某種原因,無法獲取Pod的狀態(tài)。
如果你通過kubectl describe pod命令查看Pod的詳細信息,你可以看到Pod的狀態(tài)。這里有一個例子。
七、Pod 功能
我們已經(jīng)部署了一個簡單的Nginx pod,配置非常少。但是,pod具有許多用于資源管理、配置、機密、可用性、安全性等方面的特性。
如果你是初學者,一次性學習所有這些概念將是多余的。在使用與pod相關(guān)的對象(如具有實際用例的Deployment)時,學習所有這些概念更有意義。
此外,您需要通過實際用例詳細了解每個特性。
以下是與pod相關(guān)的主要特性:
- Resource Requests and Limits: Pod CPU/內(nèi)存分配
- Labels: 附加在pod上的鍵值對,用于對資源進行分類。
- Selectors: 根據(jù)標簽對資源進行分組。
- Liveness, Readiness和Startup Probes: 容器運行狀況檢查
- ConfigMaps: 用于配置管理
- Secrets: 用于秘密管理
- Volumes: 持久數(shù)據(jù)存儲
- Init Containers: 在主容器之前運行的容器。
- Ephemeral Containers: 添加到pod中的臨時容器,用于調(diào)試或故障排除。
- Service Account: :用于限制對Kubernetes對象和資源的訪問。
- SecurityContext:主機權(quán)限和特權(quán)。
- Affinity and Anti-Affinity Rules: 跨節(jié)點的Pod放置控制。
- Pod Preemption & Priority: 設置Pod調(diào)度和驅(qū)逐的優(yōu)先級。
- Pod Disruption Budget: 在自愿中斷期間需要運行的Pod副本的最小數(shù)量。
- Container Life Cycle Hooks:根據(jù)pod的生命周期階段變化執(zhí)行自定義腳本。
全面的 Pod YAML 配置
如果您添加我上面列出的pod特性,您將得到一個全面的pod YAML配置,如下所示。此外,這些選項將與Deployment、Statefulset等對象一起使用。
apiVersion: v1
kind: Pod
metadata:
name: web-server-pod
spec:
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', 'echo "Init container started!"']
containers:
- name: web-server
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: shared-data
mountPath: /usr/share/nginx/html
- name: secret-volume
mountPath: /etc/my-secret
- name: configmap-volume
mountPath: /etc/config
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /index.html
port: 80
initialDelaySeconds: 15
periodSeconds: 20
startupProbe:
httpGet:
path: /index.html
port: 80
failureThreshold: 30
periodSeconds: 10
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo 'PostStart'"]
preStop:
exec:
command: ["/bin/sh", "-c", "echo 'PreStop'"]
serviceAccountName: nginx-service-account
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
shareProcessNamespace: true
volumes:
- name: shared-data
emptyDir: {}
- name: secret-volume
secret:
secretName: nginx-secret
- name: configmap-volume
configMap:
name: nginx-configmap
八、Pod 關(guān)聯(lián)對象
當談到在Kubernetes上運行應用程序時,我們不會運行單個pod。因為Kubernetes是關(guān)于擴展和維護pod可用性的。
所以如果你運行一個單獨的pod,它將是一個單點故障。因為Pod本身不能直接縮放。
正如我們在Kubernetes架構(gòu)中討論的那樣,我們需要像Replicaset這樣的控制器來確保始終運行所需數(shù)量的pod。
針對不同的用例,Kubernetes有不同類型的對象與pod相關(guān)聯(lián)。
以下是與pod相關(guān)的重要對象:
- Replicaset: 維護一組穩(wěn)定的pod副本在任何給定時間運行。
- Deployment: 運行無狀態(tài)應用程序,如web服務器、api等
- StatefulSets: 運行有狀態(tài)的應用程序,如分布式數(shù)據(jù)庫。
- Daemonsets: 在所有Kubernetes節(jié)點上運行代理。
- Jobs: 用于批處理
- CronJobs: 計劃的作業(yè)
總結(jié)
Kubernetes Pod是容器編排的基本單元,包含一個或多個共享網(wǎng)絡和存儲的容器。通過理解Pod的概念和生命周期,我們可以更有效地在Kubernetes中部署和管理應用。本文通過一個簡單的Nginx Pod示例展示了如何創(chuàng)建和訪問Pod,希望能幫助讀者更好地理解Kubernetes Pod的基本原理。