📄 Deployment 详解(完整版)------让 Pod 拥有"不死之身"
直接跑 Pod 有个问题:Pod 挂了就真的挂了。Deployment 就是来解决这个问题的!🧟
一、为什么需要 Deployment?
想象一下:你的应用跑得好好的,突然 Pod 挂了 → 用户访问不了了 → 你被老板骂了 😱
Deployment 就是来解决这个问题的!
它让你的 Pod 拥有:
- 🧟 多副本:同时跑多个 Pod,挂了一个还有备份
- 💊 自愈能力:Pod 挂了自动重启/重建
- 📈 扩缩容:流量大了加副本,流量小了减副本
- 🔄 滚动更新:升级不停机,用户无感知
一句话:Deployment 就是给 Pod 买了"保险"+请了"管家" 🛡️
二、什么是 Deployment?
Deployment 并不直接管理 Pod ,而是通过管理 ReplicaSet(副本集) 来间接管理 Pod。
Deployment → 管理 → ReplicaSet → 管理 → Pod(1个或多个副本)
就像大老板(Deployment)不直接管员工(Pod),而是通过部门经理(ReplicaSet)来管 🏢
Deployment 的六大核心功能
| 功能 | 说明 |
|---|---|
| 📦 创建和管理 Pod | 通过 Pod 模板定义容器配置,自动创建指定数量的 Pod 实例 |
| 🔄 滚动更新 | 不停机升级应用,逐步替换旧 Pod 为新 Pod(丝滑无感 ✨) |
| 📈 扩缩容 | 手动或自动调整副本数量 |
| 💊 健康检查 & 自愈 | 容器挂了自动重启,节点挂了自动迁移到其他节点 |
| 🔙 版本回滚 | 更新出问题?一键回到上一个版本(后悔药随时吃 💊) |
| 🎯 版本控制 | 每次更新都记录版本,方便追溯和管理 |
三、Deployment 基本操作
1️⃣ 清理环境
bash
kubectl get pod
sh
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx 1/1 Running 0 50m
my-pod 2/2 Running 0 24m
bash
kubectl delete pod my-nginx my-pod -n default
sh
[root@k8s-master k8s]# kubectl delete pod my-nginx my-pod -n default
pod "my-nginx" deleted
pod "my-pod" deleted
[root@k8s-master k8s]# kubectl get pod
No resources found in default namespace.
2️⃣ 使用 Deployment 创建 Pod
bash
kubectl create deployment <deployment名> --image=<镜像名>
sh
[root@k8s-master k8s]# kubectl create deployment tomcat --image=tomcat:8.5.92
deployment.apps/tomcat created
3️⃣ Deployment vs 普通 Pod 的区别
bash
# Deployment 创建
kubectl create deployment tomcat --image=tomcat:8.5.92
# run 创建(普通 Pod)
kubectl run nginx --image=nginx
sh
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 9s
tomcat-d7f8f49fc-nt5xg 1/1 Running 0 22s
😲 用
deployment创建的 Pod,名字后面多了一串随机字符串 (tomcat-d7f8f49fc-nt5xg)!
4️⃣ 删除 Pod 测试自愈能力
bash
kubectl delete pod nginx
kubectl delete pod tomcat-d7f8f49fc-nt5xg
sh
[root@k8s-master k8s]# kubectl delete pod nginx
pod "nginx" deleted
[root@k8s-master k8s]# kubectl delete pod tomcat-d7f8f49fc-nt5xg
pod "tomcat-d7f8f49fc-nt5xg" deleted
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
tomcat-d7f8f49fc-f54r7 1/1 Running 0 4s
| 创建方式 | 删除后 | 原因 |
|---|---|---|
kubectl run nginx |
彻底删除 ❌ | 就是个普通 Pod,没人管 |
kubectl create deployment tomcat |
自动复活 ✅ | Deployment 在管着,保证副本数 |
💡 结论 :通过 Deployment 部署的 Pod 拥有极强的自愈能力 ------只要 Deployment 还在,Pod 挂了就会无限重生!就像打不死的小强 🪳
⚠️ 想删掉 Deployment 创建的 Pod?先删 Deployment!
5️⃣ 查看 Deployment
bash
# 查看 default 命名空间下的所有 Deployment
kubectl get deploy
# 查看所有命名空间下的 Deployment
kubectl get deploy -A
# 查看指定命名空间下的 Deployment
kubectl get deploy -n <namespace>
sh
[root@k8s-master k8s]# kubectl get deploy -A
NAMESPACE NAME READY UP-TO-DATE AVAILABLE AGE
default tomcat 1/1 1 1 14m
kube-system calico-kube-controllers 1/1 1 1 7h54m
kube-system coredns 2/2 2 2 8h
kubernetes-dashboard dashboard-metrics-scraper 1/1 1 1 7h18m
kubernetes-dashboard kubernetes-dashboard 1/1 1 1 7h18m
[root@k8s-master k8s]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
tomcat 1/1 1 1 15m
[root@k8s-master k8s]# kubectl get deploy -n default
NAME READY UP-TO-DATE AVAILABLE AGE
tomcat 1/1 1 1 15m
6️⃣ 删除 Deployment
bash
kubectl delete deploy <deployment名> -n <namespace>
sh
[root@k8s-master k8s]# kubectl delete deploy tomcat -n default
deployment.apps "tomcat" deleted
[root@k8s-master k8s]# kubectl get pod
No resources found in default namespace.
💡 删除 Deployment 后,它管理的 Pod 也会一起被删除!
四、多副本能力
bash
kubectl create deployment nginx-deploy --image=nginx --replicas=3
sh
[root@k8s-master ~]# kubectl create deployment nginx-deploy --image=nginx --replicas=3
deployment.apps/nginx-deploy created
[root@k8s-master ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 3 3 43s
# 启动了 3 个 Pod
[root@k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-d845cc945-8xml2 1/1 Running 0 55s
nginx-deploy-d845cc945-bwjmm 1/1 Running 0 55s
nginx-deploy-d845cc945-rwbs5 1/1 Running 0 55s
查看 Pod 分布(自动分散到不同节点):
bash
kubectl get pod -o wide
sh
[root@k8s-master ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-d845cc945-8xml2 1/1 Running 0 94s 192.169.36.74 k8s-node1 <none> <none>
nginx-deploy-d845cc945-bwjmm 1/1 Running 0 94s 192.169.169.135 k8s-node2 <none> <none>
nginx-deploy-d845cc945-rwbs5 1/1 Running 0 94s 192.169.36.73 k8s-node1 <none> <none>
五、深入理解:Deployment → ReplicaSet → Pod 的关系
Pod 的名字结构:
nginx-deploy-d845cc945-8xml2
↑ ↑ ↑
| | └── 随机字符串(区分不同 Pod)
| └─────────── ReplicaSet 的 hash 值(固定)
└──────────────────────── Deployment 名称
d845cc945 是 Deployment 与 ReplicaSet 的映射标签,K8s 用这个来保证 Deployment 可以映射到唯一的 ReplicaSet。
bash
# 查看 ReplicaSet,带标签
kubectl get replicaset --show-labels
sh
[root@k8s-master ~]# kubectl get replicaset --show-labels
NAME DESIRED CURRENT READY AGE LABELS
nginx-deploy-d845cc945 3 3 3 12m app=nginx-deploy,pod-template-hash=d845cc945
bash
# 查看 Pod,带标签
kubectl get pod --show-labels
sh
[root@k8s-master ~]# kubectl get pod --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx-deploy-d845cc945-8xml2 1/1 Running 0 13m app=nginx-deploy,pod-template-hash=d845cc945
nginx-deploy-d845cc945-bwjmm 1/1 Running 0 13m app=nginx-deploy,pod-template-hash=d845cc945
nginx-deploy-d845cc945-rwbs5 1/1 Running 0 13m app=nginx-deploy,pod-template-hash=d845cc945
📌 关键点 :ReplicaSet 的标签和 Pod 的标签中的
pod-template-hash是一致的!这就是它们之间的"血缘关系" 🧬
六、使用 YAML 文件创建 Deployment
创建 my-deploy.yaml:
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
labels:
run: nginx-deploy
spec:
replicas: 3
selector:
matchLabels:
app: nginx-deploy
template:
metadata:
labels:
app: nginx-deploy
spec:
containers:
- image: nginx
name: nginx
应用配置:
bash
# 先删除旧的 deployment
kubectl delete deploy nginx-deploy
# 执行 YAML 文件创建
kubectl apply -f my-deploy.yaml
sh
[root@k8s-master k8s]# kubectl delete deploy nginx-deploy
deployment.apps "nginx-deploy" deleted
[root@k8s-master k8s]# kubectl apply -f my-deploy.yaml
deployment.apps/nginx-deploy created
[root@k8s-master k8s]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 3 3 2m19s
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-d845cc945-7mtfk 1/1 Running 0 2m23s
nginx-deploy-d845cc945-jbbhz 1/1 Running 0 2m23s
nginx-deploy-d845cc945-ntx8m 1/1 Running 0 2m23s
访问 Pod 中的 Nginx:
bash
kubectl get pod -o wide
curl 192.169.169.136:80
html
[root@k8s-master k8s]# curl 192.169.169.136:80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
七、YAML 文件结构精讲
yaml
apiVersion: apps/v1 # 指定 Deployment 的 API 版本
kind: Deployment # 指定资源类型
metadata: # Deployment 的元数据
name: nginx # Deployment 名称
labels: # Deployment 的标签(可自定义)
app: demo
spec: # Deployment 的资源规格
replicas: 2 # 副本数(默认 1)
selector: # 标签选择器(必须匹配 template 中的标签)
matchLabels:
app: demo
template: # Pod 模板
metadata: # Pod 的元数据
labels: # Pod 的标签(必须与 selector 匹配)
app: demo
spec: # Pod 的资源规格
containers: # 容器列表
- name: nginx # 容器名
image: nginx:1.20.0 # 镜像及版本
ports:
- containerPort: 80 # 容器端口
八、查看 K8s 支持的 API 版本
bash
kubectl api-versions
sh
[root@k8s-master k8s]# kubectl api-versions
admissionregistration.k8s.io/v1
apiextensions.k8s.io/v1
apiregistration.k8s.io/v1
apps/v1
authentication.k8s.io/v1
authorization.k8s.io/v1
autoscaling/v1
autoscaling/v2
batch/v1
certificates.k8s.io/v1
coordination.k8s.io/v1
crd.projectcalico.org/v1
discovery.k8s.io/v1
events.k8s.io/v1
flowcontrol.apiserver.k8s.io/v1beta2
flowcontrol.apiserver.k8s.io/v1beta3
networking.k8s.io/v1
node.k8s.io/v1
policy/v1
rbac.authorization.k8s.io/v1
scheduling.k8s.io/v1
storage.k8s.io/v1
v1
💡 如果你写的
apiVersion不在这个列表里,K8s 会报错!所以写 YAML 前可以先确认一下 ✅
九、Deployment 扩缩容(Scale)
场景:系统流量变大了,扛不住了 → 需要扩容;流量减少了 → 需要缩容省钱 💰
bash
kubectl scale deploy <deployment名> --replicas=<副本数>
sh
[root@k8s-master k8s]# kubectl scale deploy nginx-deploy --replicas=5
deployment.apps/nginx-deploy scaled
[root@k8s-master k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-d845cc945-45bn6 1/1 Running 0 36s
nginx-deploy-d845cc945-75d5h 1/1 Running 0 36s
nginx-deploy-d845cc945-7mtfk 1/1 Running 0 15m
nginx-deploy-d845cc945-cnkrk 1/1 Running 0 2m22s
nginx-deploy-d845cc945-lxhgr 1/1 Running 0 36s
🔄 缩容 就是把
--replicas设得比当前副本数少,K8s 会自动减少 Pod 数量。
十、Deployment 故障转移与自愈
如果某个节点宕机了,K8s 会自动在其他可用节点上重建 Pod,保证副本数量。
⏱️ 注意 :K8s 的 Taint(污点)与 Toleration(容忍)机制 会导致等待约 5 分钟,才会将 Pod 迁移到其他节点。
服务中断时间 = 5分钟等待 + 重建时间 + 服务启动时间 + 健康检查时间
❓ 节点恢复后,原来的 Pod 还能回来吗?
答案:不能。 服务数量严格遵循 Deployment 的副本数配置。如果 node2 恢复了,Pod 也不会再调度回去,因为 K8s 只关心"有多少个 Pod 在运行",不关心"它们具体在哪运行"。
十一、Deployment 滚动更新(Rolling Update)
1️⃣ 实时监控 Pod 变化
bash
kubectl get pod -w
sh
[root@k8s-master k8s]# kubectl get pod -w
NAME READY STATUS RESTARTS AGE
nginx-deploy-d845cc945-45bn6 1/1 Running 0 19m
nginx-deploy-d845cc945-75d5h 1/1 Running 0 19m
nginx-deploy-d845cc945-7mtfk 1/1 Running 0 34m
nginx-deploy-d845cc945-cnkrk 1/1 Running 0 21m
nginx-deploy-d845cc945-lxhgr 1/1 Running 0 19m
2️⃣ 更新镜像(滚动升级)
打开两个终端 ,一个跑
kubectl get pod -w实时监控,另一个执行更新命令:
bash
kubectl set image deploy nginx-deploy nginx=nginx:1.19.2 --record
sh
[root@k8s-master ~]# kubectl set image deploy nginx-deploy nginx=nginx:1.19.2 --record
Flag --record has been deprecated, --record will be removed in the future
deployment.apps/nginx-deploy image updated
监控窗口输出:
sh
nginx-deploy-86b5d68f7b-g8v2n 0/1 Pending 0 0s
nginx-deploy-86b5d68f7b-fnj68 0/1 Pending 0 0s
nginx-deploy-86b5d68f7b-g8v2n 0/1 Pending 0 0s
nginx-deploy-86b5d68f7b-fnj68 0/1 Pending 0 0s
nginx-deploy-86b5d68f7b-g8v2n 0/1 ContainerCreating 0 0s
nginx-deploy-86b5d68f7b-fnj68 0/1 ContainerCreating 0 0s
nginx-deploy-86b5d68f7b-5mnsp 0/1 Pending 0 0s
nginx-deploy-86b5d68f7b-5mnsp 0/1 Pending 0 0s
nginx-deploy-86b5d68f7b-5mnsp 0/1 ContainerCreating 0 0s
nginx-deploy-d845cc945-75d5h 1/1 Terminating 0 22m
nginx-deploy-d845cc945-75d5h 0/1 Terminating 0 22m
nginx-deploy-86b5d68f7b-fnj68 0/1 ContainerCreating 0 1s
nginx-deploy-86b5d68f7b-g8v2n 0/1 ContainerCreating 0 1s
nginx-deploy-86b5d68f7b-5mnsp 0/1 ContainerCreating 0 1s
nginx-deploy-d845cc945-75d5h 0/1 Terminating 0 22m
nginx-deploy-d845cc945-75d5h 0/1 Terminating 0 22m
🔄 滚动更新过程 :新 Pod 先启动,旧 Pod 再销毁------始终保证至少有一个服务在运行!用户无感知 ✨
十二、Deployment 版本历史与回滚
1️⃣ 查看历史版本
bash
kubectl rollout history deploy nginx-deploy
sh
[root@k8s-master k8s]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy
REVISION CHANGE-CAUSE
1 <none>
2 kubectl set image deploy nginx-deploy nginx=nginx:1.19.2 --record=true
2️⃣ 查看指定版本详情
bash
kubectl rollout history deploy nginx-deploy --revision=2
sh
[root@k8s-master k8s]# kubectl rollout history deploy nginx-deploy --revision=2
deployment.apps/nginx-deploy with revision #2
Pod Template:
Labels: app=nginx-deploy
pod-template-hash=86b5d68f7b
Annotations: kubernetes.io/change-cause: kubectl set image deploy nginx-deploy nginx=nginx:1.19.2 --record=true
Containers:
nginx:
Image: nginx:1.19.2
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
3️⃣ 回滚版本
bash
# 回滚到上一个版本
kubectl rollout undo deploy nginx-deploy
# 回滚到指定版本
kubectl rollout undo deploy nginx-deploy --to-revision=2
sh
[root@k8s-master k8s]# kubectl rollout undo deploy nginx-deploy
deployment.apps/nginx-deploy rolled back
[root@k8s-master k8s]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy
REVISION CHANGE-CAUSE
2 kubectl set image deploy nginx-deploy nginx=nginx:1.19.2 --record=true
3 <none>
[root@k8s-master k8s]# kubectl rollout undo deploy nginx-deploy --to-revision=2
deployment.apps/nginx-deploy rolled back
[root@k8s-master k8s]# kubectl rollout history deploy nginx-deploy
deployment.apps/nginx-deploy
REVISION CHANGE-CAUSE
3 <none>
4 kubectl set image deploy nginx-deploy nginx=nginx:1.19.2 --record=true
💊 后悔药随时吃:更新出问题了?一键回滚!😎
十三、Deployment 命令速查表
| 命令 | 说明 |
|---|---|
kubectl get deploy |
查看 Deployment 列表 |
kubectl get deploy -A |
查看所有命名空间的 Deployment |
kubectl get deploy -n <ns> |
查看指定命名空间的 Deployment |
kubectl describe deploy <name> |
查看 Deployment 详情 |
kubectl create deploy <name> --image=<image> |
创建 Deployment |
kubectl scale deploy <name> --replicas=N |
扩缩容 |
kubectl set image deploy <name> <容器名>=<新镜像> |
更新镜像(触发滚动更新) |
kubectl rollout status deploy <name> |
查看更新状态 |
kubectl rollout history deploy <name> |
查看历史版本 |
kubectl rollout history deploy <name> --revision=N |
查看指定版本详情 |
kubectl rollout undo deploy <name> |
回滚到上一个版本 |
kubectl rollout undo deploy <name> --to-revision=N |
回滚到指定版本 |
kubectl delete deploy <name> |
删除 Deployment |
kubectl get rs |
查看 ReplicaSet |
kubectl get rs --show-labels |
查看 ReplicaSet 并显示标签 |
kubectl get pod --show-labels |
查看 Pod 并显示标签 |
kubectl api-versions |
查看所有支持的 API 版本 |
十四、本章小结
🎉 你学会了:
Deployment 基础:
- ✅ 为什么需要 Deployment
- ✅ Deployment 的概念和六大核心功能
- ✅ Deployment vs 普通 Pod 的区别
- ✅ Deployment 的自愈能力
Deployment 操作:
- ✅ 命令行创建 Deployment
- ✅ YAML 文件创建 Deployment
- ✅ 查看、删除 Deployment
- ✅ 多副本能力
Deployment 高级功能:
- ✅ 扩缩容(Scale)
- ✅ 滚动更新(Rolling Update)
- ✅ 版本回滚(Rollback)
- ✅ Deployment → ReplicaSet → Pod 的层级关系
🏆 恭喜你! 学完这一章,你已经掌握了 K8s 最核心的控制器之一------Deployment。它让你的 Pod 拥有了"不死之身",是生产环境中部署应用的首选方式!
下篇见!👋