大家好,歡迎來到《云原生核心技術》系列的第七篇!
在上一篇,我們成功地使用 Minikube 或 kind 在自己的電腦上搭建起了一個迷你但功能完備的 Kubernetes 集群。現在,我們就像一個擁有了一塊嶄新數字土地的農場主,是時候在這片土地上播種、耕作了。
那么問題來了,我們該如何把之前用 Docker 打包好的應用(容器)種植到 K8s 這片廣袤的土地上呢?直接扔進去嗎?
當然不行。K8s 有一套自己的“種植”規則。今天,我們就來學習這套規則里最基本的兩個概念:Pod 和 Deployment。它們是你在 K8s 世界里打交道最多的兩個朋友。
一、 Pod:K8s 世界的“原子單位”,為什么不是直接部署容器?
在 Docker 的世界里,我們操作的最小單位是“容器”。但到了 K8s,你會發現最小的部署單位是一個叫 Pod 的東西。
一個常見的疑問是:為什么 K8s 不直接管理容器,非要引入一個 Pod 的概念呢?
為了回答這個問題,我們先來看一個比喻:
把一個容器想象成一個人。
那么 Pod 就像一套房子。
K8s 分配資源時,不是按“人頭”(容器)分的,而是按“戶口”(Pod)分的。它可以給一套房子(一個Pod)分配一個獨立的 IP 地址、主機名和一套獨立的“水電煤氣”(網絡、存儲等資源)。
這套房子里,可以只住一個人(單容器 Pod),這也是最常見的用法。但 K8s 也允許你讓多個人(多容器)合租在同一套房子里。
合租的好處是什么?
住在同一屋檐下的人,他們:
- 共享同一個“家庭住址”(共享網絡命名空間):他們可以用
localhost
直接互相訪問,就像家人之間串門一樣,不需要出門繞到大街上(外部網絡)。這對于需要緊密協作的程序(比如一個業務容器和一個日志收集容器)來說非常高效。 - 共享“儲藏室”(共享存儲卷 Volume):他們可以輕松地共享文件,就像家人共用一個冰箱一樣。
總結一下:Pod 是 K8s 調度、管理和資源分配的最小單位。它將一個或多個緊密關聯的容器打包在一起,為它們提供共享的存儲和網絡資源,形成一個內聚的服務單元。
動手:編寫并運行你的第一個 Pod
在 K8s 中,我們通常不使用命令行直接創建資源,而是通過編寫 YAML 文件來“聲明”我們想要的狀態。這就像給 K8s 一張建筑藍圖,它會負責照著藍圖施工。
創建一個名為 nginx-pod.yaml
的文件,內容如下:
# nginx-pod.yaml# API 版本,表明這個對象屬于哪個 API 組
apiVersion: v1
# 資源類型,我們正在創建一個 Pod
kind: Pod
# 元數據,包含資源的名稱、標簽等信息
metadata:name: nginx-hello-podlabels:app: web
# 規格,定義了這個 Pod 的期望狀態
spec:# Pod 中包含的容器列表containers:# 第一個容器- name: nginx-container# 使用的 Docker 鏡像image: nginx:1.21# 容器需要暴露的端口ports:- containerPort: 80
現在,打開你的終端,使用 kubectl
來應用這個藍圖:
# 確保你的 kubectl 已經連接到 Minikube 或 kind 集群
kubectl apply -f nginx-pod.yaml
執行后,K8s 就會開始創建這個 Pod。我們可以查看它的狀態:
kubectl get pods# 你會看到類似下面的輸出:
# NAME READY STATUS RESTARTS AGE
# nginx-hello-pod 1/1 Running 0 15s
Running
狀態表示我們的 Nginx Pod 已經成功運行起來了!
二、 Deployment:應用的“狀態維護者”與“智能管家”
我們現在有了一個正在運行的 Pod。但是,如果這個 Pod 因為某些原因(比如程序 Bug、節點故障)掛掉了怎么辦?它就真的消失了,沒有人會去管它。這在生產環境中是絕對無法接受的。
我們需要一個更高級的“管家”,它能確保我們的應用:
- 永不宕機:如果一個 Pod 掛了,它能自動創建一個新的來替代。
- 數量可控:我們可以告訴它,“請確保始終有3個相同的 Pod 在運行”,它就會自動維護這個數量。
- 輕松更新:當我們想更新應用版本時,它能平滑地、滾動地用新版 Pod 替換舊版 Pod,保證業務不中斷。
- 一鍵回滾:如果新版本有問題,它能一鍵回退到上一個穩定版本。
這個智能管家,就是 Deployment。
再次使用比喻:
如果 Pod 是一間公寓,那么 Deployment 就是這棟公寓的物業經理。
你不會親自去管理每一間公寓的入住和維修。你只需要告訴物業經理:“我需要這棟樓里始終有50間公寓是租出去并且正常運作的,租戶是 Nginx v1.21”。
經理會負責招租(創建 Pod),檢查水電(監控 Pod 健康),如果租戶跑了(Pod 掛了)就立刻找新租戶(創建新 Pod),如果你想升級所有公寓的裝修(更新應用版本),經理會一間一間地施工(滾動更新)。
動手:用 Deployment 部署應用
讓我們來創建一個 nginx-deployment.yaml
文件,用 Deployment 的方式來部署 Nginx。
# nginx-deployment.yamlapiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deployment
spec:# 期望的 Pod 副本數量replicas: 3# 選擇器,告訴 Deployment 要管理哪些 Pod# Deployment 通過這個標簽找到它應該管理的 Podselector:matchLabels:app: nginx-server# Pod 模板,這就是 Deployment 創建新 Pod 時使用的“藍圖”# 注意,這里的結構和我們上面定義的 Pod YAML 的 spec 部分幾乎一樣template:metadata:# Pod 的標簽,必須和上面的 selector.matchLabels 匹配labels:app: nginx-serverspec:containers:- name: nginximage: nginx:1.21ports:- containerPort: 80
應用這個 YAML 文件:
kubectl apply -f nginx-deployment.yaml
查看 Deployment 和它創建的 Pods:
kubectl get deployment# 輸出:
# NAME READY UP-TO-DATE AVAILABLE AGE
# nginx-deployment 3/3 3 3 20skubectl get pods# 輸出: (注意,Pod 名稱是 Deployment 名稱加上隨機字符串)
# NAME READY STATUS RESTARTS AGE
# nginx-deployment-6b6c47948c-7v9d8 1/1 Running 0 25s
# nginx-deployment-6b6c47948c-8l9f4 1/1 Running 0 25s
# nginx-deployment-6b6c47948c-k5z2x 1/1 Running 0 25s
看!Deployment 嚴格按照我們的要求 replicas: 3
,創建并維護了3個 Nginx Pod。
三、實戰演練:見證 Deployment 的“魔法時刻”
現在,讓我們親眼見證 Deployment 作為“智能管家”的神奇能力。
1. 魔法一:故障自愈 (Self-healing)
我們來手動“干掉”一個 Pod,模擬一次故障。
首先,獲取 Pod 列表,隨便挑一個名字記下來:
kubectl get pods
然后,無情地刪除它:
# 將 <your-pod-name> 替換為你復制的 Pod 名稱
kubectl delete pod <your-pod-name>
現在,立刻、馬上再次查看 Pod 列表,并使用 -w
(watch) 參數持續觀察變化:
kubectl get pods -w
你會看到一個激動人心的場面:
- 你刪除的那個 Pod 狀態會變為
Terminating
(正在終止)。 - 幾乎在同一時間,一個新的 Pod 會立刻出現,狀態從
Pending
->ContainerCreating
->Running
。 - 最終,Pod 的總數依然是3個!
這就是 K8s 的故障自愈能力,由 Deployment 精確執行。
2. 魔法二:滾動更新 (Rolling Update)
我們的應用要發布新版本了,比如把 Nginx 從 1.21
升級到 1.22
。
直接編輯 nginx-deployment.yaml
文件,將 image: nginx:1.21
修改為 image: nginx:1.22
。
# ...spec:containers:- name: nginximage: nginx:1.22 # <--- 修改這里ports:- containerPort: 80
保存文件后,再次執行 apply
命令:
kubectl apply -f nginx-deployment.yaml
再次用 -w
觀察 Pod 變化:kubectl get pods -w
你會看到 K8s 正在進行“滾動更新”:
它會先創建一個新版本的 Pod,等新 Pod 啟動并準備就緒后,再優雅地終止一個舊版本的 Pod。如此循環,直到所有 Pod 都被更新為新版本。整個過程服務不中斷!
你可以通過以下命令查看更新狀態:
kubectl rollout status deployment/nginx-deployment
3. 魔法三:一鍵回滾 (Rollback)
糟糕!新版本 1.22
有一個重大 Bug,我們需要緊急回退到上一個版本!
別慌,Deployment 已經為我們記錄了歷史版本。執行回滾命令即可:
kubectl rollout undo deployment/nginx-deployment
再次觀察 Pod 變化 kubectl get pods -w
,你會發現 K8s 又開始了一次滾動操作,這次是把 1.22
版本的 Pod 逐個替換回 1.21
版本。危機解除!
總結
今天我們學習了 K8s 中兩個最核心、最基礎的概念:
- Pod: K8s 的原子調度單元,是容器的“家”,為內部容器提供共享的網絡和存儲。
- Deployment: Pod 的“智能管家”,負責保證 Pod 的數量(副本)、實現故障自愈、并以安全、平滑的方式進行應用更新和回滾。
你現在已經掌握了在 K8s 中部署、更新和維護無狀態應用的基本技能。我們已經成功地讓應用在集群內部“活起來”并且“活得很好”。
但是,新的問題又來了:現在這些 Nginx 服務都運行在 K8s 集群內部,我們作為外部用戶,如何才能訪問到它們呢?
別急,這正是我們下一篇文章要解決的問題。在下一篇 《K8s 核心概念白話解讀(下)》 中,我們將揭秘 Service 和 Ingress 這兩個負責“對外暴露服務”和“管理流量”的關鍵角色。敬請期待!