掌握這些Kubernetes Pod技巧,成為企業(yè)必備技能人才
Kubernetes Pod 是什么?
Kubernetes Pod 是 Kubernetes 應(yīng)用的基本執(zhí)行單元??梢园阉胂蟪蓱?yīng)用程序運(yùn)行的獨(dú)特環(huán)境,封裝了一個(gè)或多個(gè)應(yīng)用容器以及共享的存儲(chǔ)/網(wǎng)絡(luò)資源。Kubernetes 有很多封裝服務(wù)、端點(diǎn)和其他實(shí)體的概念,但歸根結(jié)底一個(gè) Pod 是你的代碼運(yùn)行的地方。
Kubernetes Pod 和容器的區(qū)別
從概念上來(lái)說(shuō),Pod 可以和 Docker Compose 中的容器進(jìn)行比較。在與 Docker Compose 相比時(shí),Pod 在 Kubernetes 中扮演的角色與容器在 Docker Compose 中扮演的角色相同,但 Pod 實(shí)際上是一種對(duì)一個(gè)或多個(gè)容器的抽象,具有相關(guān)的網(wǎng)絡(luò)和存儲(chǔ)配置。Pod 可以包含幾個(gè)容器,但是最佳實(shí)踐是有一個(gè)運(yùn)行應(yīng)用代碼的主容器,以及 0 個(gè)或多個(gè)提供應(yīng)用額外功能(如日志、監(jiān)控和網(wǎng)絡(luò))的支持容器,這種方式稱為 Sidecar,這些支持容器稱為 sidecar 容器。
Kubernetes Pod 和節(jié)點(diǎn)的區(qū)別
節(jié)點(diǎn)是 Kubernetes 中的工作器,Pod 就是在節(jié)點(diǎn)上運(yùn)行。節(jié)點(diǎn)可以是虛擬的,例如 AWS EC2 實(shí)例,或者物理的計(jì)算機(jī)服務(wù)器。Pod 被分配到節(jié)點(diǎn)上,并在這些節(jié)點(diǎn)上運(yùn)行,消耗節(jié)點(diǎn)提供給集群的容量。Pod 并非明確綁定到節(jié)點(diǎn),它們是由 Kubernetes 控制平面分配的,如果有必要可以從一個(gè)節(jié)點(diǎn)移動(dòng)到另一個(gè)節(jié)點(diǎn)。
Kubernetes Pod 和集群的區(qū)別
集群本質(zhì)上是一組提供容量的節(jié)點(diǎn)、一組運(yùn)行應(yīng)用程序的 Pod 以及其他配置(如服務(wù)或入口控制器),所有這些都由 Kubernetes 控制平面管理。從概念上講,Pod 可以被視為 Kubernetes 運(yùn)行應(yīng)用程序的方式。
Kubernetes Pod 的工作方式
Pod 是在主容器(運(yùn)行我們代碼的容器)之上的一層抽象,以及零個(gè)或多個(gè)支持或 sidecar 容器。除了容器之外,Pod 在 Kubernetes 集群中還有一個(gè)身份和幾個(gè)配置。
Pod 的生命周期
Pod 在其生命周期中可以經(jīng)歷幾個(gè)階段:
- Pending:系統(tǒng)已接受該 Pod,但一個(gè)或多個(gè)容器尚未設(shè)置和運(yùn)行。
- Running:該 Pod 已綁定到一個(gè)節(jié)點(diǎn),其所有容器都已創(chuàng)建。
- Succeeded:Pod 中的所有容器已成功終止并不會(huì)重啟。該 Pod 不再綁定到一個(gè)節(jié)點(diǎn)和消耗資源。
- Failed:Pod 中至少有一個(gè)容器以失敗狀態(tài)終止。該 Pod 不再綁定到一個(gè)節(jié)點(diǎn)和消耗資源。
- Unknown:當(dāng)由于與 Pod 主機(jī)節(jié)點(diǎn)的某些通信問(wèn)題導(dǎo)致?tīng)顟B(tài)不明確時(shí)。當(dāng)一個(gè)節(jié)點(diǎn)無(wú)法向 Kubernetes 控制平面報(bào)告其狀態(tài)時(shí),在該節(jié)點(diǎn)上運(yùn)行的 Pod 會(huì)進(jìn)入 Unknown 狀態(tài)。
Pod 如何管理多個(gè)容器
一個(gè) Pod 可以封裝多個(gè)容器,確保它們共享相同的存儲(chǔ)和網(wǎng)絡(luò)命名空間。這使我們可以將應(yīng)用程序幫助進(jìn)程與主應(yīng)用程序耦合在一起,而不必處理它們之間的網(wǎng)絡(luò)配置。在同一個(gè) Pod 中運(yùn)行的容器共享本地網(wǎng)絡(luò)和存儲(chǔ)。這通常用于 sidecar 容器,例如日志記錄、監(jiān)控或網(wǎng)絡(luò)配置。例如,這樣配置一個(gè)具有多個(gè)容器的 Pod:
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app: myapp
spec:
containers:
- name: myapp-container
image: busybox
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
- name: log-container
image: busybox
command: ['sh', '-c', 'tail -f /dev/null']
這將在一個(gè) Pod 中運(yùn)行兩個(gè)容器,一個(gè)運(yùn)行應(yīng)用,另一個(gè)記錄日志。它們共享網(wǎng)絡(luò)和文件系統(tǒng)。這就是 Pod 的強(qiáng)大之處。
使用 Kubernetes 中的 Pod
Kubernetes 是一個(gè)復(fù)雜的平臺(tái),運(yùn)行生產(chǎn)負(fù)載需要比只定義一個(gè)包含容器的 Pod 更多的知識(shí)。以下是有效管理 Pod 需要理解的一些額外知識(shí)點(diǎn)。
Pod 更新和替換
直接更新正在運(yùn)行的 Pod 不是一個(gè)好的實(shí)踐,因?yàn)樗`反了 Pod 的不變性假設(shè)(本質(zhì)上與容器的不變性相同)。事實(shí)上,Kubernetes 在 Pod 層面上執(zhí)行這種不變性,這意味著它拒絕對(duì) Pod 進(jìn)行更新。相反,我們應(yīng)該部署 Pod 的新版本,并平滑地將流量重定向到較新版本。如果這種部署是逐步進(jìn)行的,每次替換一個(gè) Pod(當(dāng)為同一應(yīng)用程序運(yùn)行多個(gè) Pod 時(shí)相關(guān)),這稱為滾動(dòng)更新。如果部署一組全新的 Pod,將流量重定向到它們,驗(yàn)證它們是否正常工作,然后才終止舊的 Pod,這稱為藍(lán)綠部署。
當(dāng)創(chuàng)建一個(gè) Deployment,其中包含一組 Pod 時(shí),可以定義更新策略。例如,以下是如何定義滾動(dòng)更新策略:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
...
這將逐步更新 Pod,每次更新一個(gè),同時(shí)保持可用 Pod 數(shù)量至少為 2。
Pod 資源限制
可以為 Pod 定義 CPU 和內(nèi)存請(qǐng)求和限制,以防止 Pod 消耗太多節(jié)點(diǎn)資源。例如:
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
這將請(qǐng)求 64MB 內(nèi)存和 0.25 CPU 核心,并限制為 128MB 內(nèi)存和 0.5 CPU 核心。了解這些概念將幫助我們?cè)谏a(chǎn)中安全可靠地運(yùn)行 Pod。
Kubernetes 中的 Pod 存儲(chǔ)
Pod 僅具有短暫的存儲(chǔ),這是通過(guò)工作內(nèi)存實(shí)現(xiàn)的。可以使用 Persistent Volume 來(lái)創(chuàng)建持久存儲(chǔ),并通過(guò) Persistent Volume Claim 與 Pod 關(guān)聯(lián)。從概念上講,持久卷可以與節(jié)點(diǎn)進(jìn)行比較:它們使底層資源(在這種情況下是存儲(chǔ),而不是計(jì)算)可用于 Kubernetes 集群。Persistent Volume Claim 為 Pod 預(yù)留這些可用資源,與它們相關(guān)聯(lián)。這些 Persistent Volume Claim 可以作為卷關(guān)聯(lián)到 Pod 內(nèi)的容器,并作為容器本地文件系統(tǒng)的一部分進(jìn)行訪問(wèn)。
重要的是,它們可以由 Pod 中的所有容器共享,允許在同一 Pod 中基于文件在容器之間進(jìn)行通信。日志 sidecar 容器通常使用這種方法來(lái)從主容器讀取日志,并將其導(dǎo)出到像 AWS CloudWatch Logs 這樣的外部日志聚合器。
下面是如何定義一個(gè) Persistent Volume Claim,并將其作為卷關(guān)聯(lián)到 Pod 中的一個(gè)容器:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! > /mnt/vol1/hello-file']
volumeMounts:
- mountPath: /mnt/vol1
name: vol1
volumes:
- name: vol1
persistentVolumeClaim:
claimName: my-pvc
這將在 /mnt/vol1 路徑掛載 PVC my-pvc,容器可以在其中讀寫文件。使用持久卷可以確保Pod重新啟動(dòng)時(shí)數(shù)據(jù)不會(huì)丟失。
Pod 網(wǎng)絡(luò)
每個(gè) Pod 都在整個(gè)集群中分配一個(gè)唯一的 IP 地址,可以從集群內(nèi)部訪問(wèn)該地址。還可以定義服務(wù),它允許通過(guò)單個(gè) IP 地址或?qū)S?DNS 名稱尋址同類 Pod 組(通常是 Deployment),并在這些 Pod 之間負(fù)載均衡流量。還可以定義 Ingress 來(lái)通過(guò) Ingress Controller 將服務(wù)暴露到集群外部。Pod 之間默認(rèn)是可以相互通信的,不需要額外的網(wǎng)絡(luò)配置。但是,有時(shí)可能需要進(jìn)一步隔離 Pod 網(wǎng)絡(luò)。這可以通過(guò) Kubernetes 網(wǎng)絡(luò)策略來(lái)實(shí)現(xiàn),它允許根據(jù)標(biāo)簽選擇器控制 Pod 之間的流量。
例如,以下網(wǎng)絡(luò)策略只允許具有 role=frontend 的 Pod 訪問(wèn)具有 role=backend 的 Pod:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-policy
spec:
podSelector:
matchLabels:
role: backend
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
理解 Pod 網(wǎng)絡(luò)對(duì)于在 Kubernetes 中運(yùn)行基于網(wǎng)絡(luò)的應(yīng)用程序非常重要。主流的網(wǎng)絡(luò)模型包括 Flannel、Calico、Cilium 等。
總結(jié)
Kubernetes是一個(gè)非常強(qiáng)大的平臺(tái),但這種強(qiáng)大也帶來(lái)了巨大的復(fù)雜性。Pod只是一個(gè)起點(diǎn),但理解它們的工作方式對(duì)于掌握Kubernetes在Pod之上用于部署生產(chǎn)級(jí)負(fù)載的抽象和配置是必要的。
理解Pod的基礎(chǔ)知識(shí),比如它們的生命周期、如何管理多個(gè)容器、存儲(chǔ)、資源限制等,是開(kāi)始使用Kubernetes的關(guān)鍵第一步。一旦你理解了這些基礎(chǔ)知識(shí),你就可以構(gòu)建更復(fù)雜的應(yīng)用程序部署,利用Kubernetes提供的服務(wù)發(fā)現(xiàn)、負(fù)載均衡、滾動(dòng)更新等高級(jí)功能。