K8s学习笔记:02-Deployment控制器

目标:理解为什么需要 Deployment,掌握创建、扩缩容、滚动更新和回滚


2.1 Pod 的局限与 Deployment 的诞生

回顾:Pod 能干什么

第一章你学会了用 kubectl run 创建 Pod。Pod 能跑起来,但它有个致命问题:

1
2
kubectl delete pod my-nginx
# Pod 删了就是删了,没人会帮你重建

Pod 是”宠物”,不是”牛”——死了就是死了。

真实需求

需求 Pod 能做到吗?
挂了自动重启
想跑 3 个副本
更新镜像不停机
版本出问题回滚

Deployment 出场

1
2
3
4
5
6
7
┌────────── Deployment ───────────┐
│ replicas: 3 │
│ image: nginx:alpine │
│ ┌──────── ReplicaSet ────────┐ │
│ │ Pod-abc Pod-def Pod-ghi│ │
│ └────────────────────────────┘ │
└─────────────────────────────────┘

Deployment 是 Pod 的”管理者”。你告诉它”我想要 3 个 nginx”,它通过 ReplicaSet 确保始终有 3 个 Pod 在跑。Pod 挂了?自动补一个。想更新镜像?一个一个替换,保证服务不中断。

类比 Docker

Docker K8s
docker run Pod
docker-compose up Deployment

2.2 创建与管理 Deployment

创建第一个 Deployment

1
kubectl create deployment my-nginx-deploy --image=nginx:alpine --port=80

查看 Deployment

1
2
3
4
5
6
7
8
9
10
11
kubectl get deploy
# NAME READY UP-TO-DATE AVAILABLE AGE
# my-nginx-deploy 1/1 1 1 10s

kubectl get rs
# NAME DESIRED CURRENT READY AGE
# my-nginx-deploy-xxxxxxxxxx 1 1 1 10s

kubectl get pods
# NAME READY STATUS RESTARTS AGE
# my-nginx-deploy-xxxxxxxxxx-xxxxx 1/1 Running 0 10s

注意 Pod 名字的变化:不再是 my-nginx,而是 my-nginx-deploy-<rs-hash>-<pod-hash>。Deployment 创建了 ReplicaSet,ReplicaSet 创建了 Pod。三层关系:

1
Deployment → ReplicaSet → Pod

查看详细信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
kubectl describe deploy my-nginx-deploy

root@bote798-ubuntu:~# kubectl describe deploy my-nginx-deploy
Name: my-nginx-deploy
Namespace: default
CreationTimestamp: Mon, 13 Jul 2026 20:32:24 +0800
Labels: app=my-nginx-deploy
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=my-nginx-deploy
Replicas: 1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app=my-nginx-deploy
Containers:
nginx:
Image: nginx:alpine
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Conditions:
Type Status Reason
---- ------ ------
Available True MinimumReplicasAvailable
Progressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: my-nginx-deploy-5d4cc55964 (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 6m10s deployment-controller Scaled up replica set my-nginx-deploy-5d4cc55964 to 1

关注输出里的 ConditionsEvents,和 Pod 的 describe 类似但更宏观。

测试自愈能力

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 记住当前 Pod 的名字
kubectl get pods

NAME READY STATUS RESTARTS AGE
my-nginx-deploy-5d4cc55964-zjl9d 1/1 Running 0 7m29s

# 删掉它
kubectl delete pod <pod-name>

root@bote798-ubuntu:~# kubectl delete pod my-nginx-deploy-5d4cc55964-zjl9d
pod "my-nginx-deploy-5d4cc55964-zjl9d" deleted from default namespace

# 立刻再查——一个新 Pod 已经起来了
kubectl get pods

NAME READY STATUS RESTARTS AGE
my-nginx-deploy-5d4cc55964-n5p7g 1/1 Running 0 5s

Deployment 发现 Pod 少了,立刻让 ReplicaSet 补了一个。这就是”声明式”:你声明了目标状态(1 个 Pod),K8s 持续确保实际状态 = 目标状态。

扩缩容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 扩容到 3 个副本
kubectl scale deploy my-nginx-deploy --replicas=3

kubectl get pods -o wide

NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-nginx-deploy-5d4cc55964-n5p7g 1/1 Running 0 113s 10.244.0.6 kind-control-plane <none> <none>
my-nginx-deploy-5d4cc55964-xrd9n 1/1 Running 0 11s 10.244.0.7 kind-control-plane <none> <none>
my-nginx-deploy-5d4cc55964-zv5cg 1/1 Running 0 11s 10.244.0.8 kind-control-plane <none> <none>
# 三个 Pod,分布在节点上

# 缩容回 1 个
kubectl scale deploy my-nginx-deploy --replicas=1

kubectl get pods

NAME READY STATUS RESTARTS AGE
my-nginx-deploy-5d4cc55964-n5p7g 1/1 Running 0 5m21s
# 只剩一个了

2.3 滚动更新与回滚

更新镜像

1
2
3
4
5
6
7
8
9
10
11
12
# 查看当前镜像
kubectl describe deploy my-nginx-deploy | grep Image

# 更新镜像版本(nginx:alpine → nginx:alpine-perl)
kubectl set image deploy/my-nginx-deploy nginx=nginx:alpine-perl

# 实时观察更新过程
kubectl rollout status deploy/my-nginx-deploy

Waiting for deployment "my-nginx-deploy" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "my-nginx-deploy" rollout to finish: 1 old replicas are pending termination...
deployment "my-nginx-deploy" successfully rolled out

滚动更新的过程:

1
旧 Pod (running) ──→ 新 Pod (creating) ──→ 新 Pod (running) ──→ 旧 Pod (terminating)

每次只替换一个,保证服务不中断。

查看更新历史

1
2
3
4
kubectl rollout history deploy/my-nginx-deploy
# REVISION CHANGE-CAUSE
# 1 <none>
# 2 <none>

回滚

1
2
3
4
5
6
7
8
# 回滚到上一个版本
kubectl rollout undo deploy/my-nginx-deploy

# 或者回滚到指定版本
kubectl rollout undo deploy/my-nginx-deploy --to-revision=1

# 确认回滚成功
kubectl describe deploy my-nginx-deploy | grep Image

2.4 章节练习

练习 1:自愈测试

1
2
3
4
5
# 1. 创建 Deployment,3 个副本,使用 nginx:alpine
# 2. 用 kubectl get pods -o wide 查看 3 个 Pod
# 3. 手动删除其中一个 Pod
# 4. 立刻 kubectl get pods——观察 Pod 数量变化
# 5. 再次删除一个 Pod,记下新旧 Pod 的名字变化

练习 2:扩缩容

1
2
3
4
# 1. 把副本数从 3 扩到 5
# 2. kubectl get pods 确认 5 个都在运行
# 3. 缩到 2
# 4. 确认多余的 3 个被终止

练习 3:滚动更新与回滚

1
2
3
4
5
6
# 1. 把镜像更新为 nginx:alpine-perl
# 2. 用 rollout status 观察更新过程
# 3. 确认更新完成(kubectl describe deploy | grep Image)
# 4. 查看 rollout history
# 5. 回滚到旧版本
# 6. 确认镜像已回滚

练习 4:模拟故障回滚

1
2
3
4
5
# 1. 故意更新为一个不存在的镜像:nginx:not-exist
# 2. kubectl get pods 观察状态(会看到 ImagePullBackOff 或 CrashLoopBackOff)
# 3. kubectl rollout status 会一直等待——Ctrl+C 退出
# 4. kubectl rollout undo 立即回滚
# 5. kubectl get pods——恢复正常

自检清单

  • 理解 Pod vs Deployment 的区别和关系
  • 能看懂 Deployment → ReplicaSet → Pod 的层级
  • 能手操 scale 扩缩容
  • 能手操 set image + rollout undo 更新和回滚
  • 见识过自愈:删 Pod 自动补回
  • 见识过坏更新 + 快速回滚恢复

K8s学习笔记:02-Deployment控制器
https://bote798.top/2026/07/13/K8s学习笔记-02-Deployment控制器/
作者
bote798
发布于
2026年7月13日
更新于
2026年7月14日
许可协议