概述

Deployment 是 Kubernetes 中最常用的工作负载资源,用于声明式地管理 Pod 和 ReplicaSet,提供滚动更新、回滚、扩缩容等功能。

核心功能:

  • 🔄 声明式更新和回滚
  • 📊 副本数量管理
  • 🚀 滚动更新策略
  • 💚 健康检查和自愈
  • 🎯 资源配额管理

适用场景:

  • 无状态应用部署
  • 微服务容器化
  • 应用版本管理
  • 高可用服务

Deployment 完整配置

基本结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: apps/v1              # API 版本
kind: Deployment # 资源类型
metadata: # Deployment 自身的元数据
name: my-app # Deployment 名称
namespace: default # 命名空间
labels: # Deployment 标签
app: my-app
spec: # Deployment 规范
replicas: 3 # Pod 副本数
selector: # Pod 选择器
matchLabels:
app: my-app
strategy: # 更新策略
type: RollingUpdate
template: # Pod 模板
metadata: # Pod 的元数据
labels:
app: my-app
spec: # Pod 规范
containers:
- name: app
image: nginx:1.21

完整配置详解

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-application # Deployment 名称(必需)
namespace: production # 命名空间(可选,默认 default)
labels: # Deployment 标签(可选)
app: my-app
version: v1
annotations: # 注解(可选)
description: "My Application Deployment"

spec:
# === 副本数配置 ===
replicas: 3 # Pod 副本数量

# === 选择器配置 ===
selector: # Pod 选择器(必需)
matchLabels: # 必须匹配 template.metadata.labels
app: my-app

# === 更新策略 ===
strategy:
type: RollingUpdate # 滚动更新(默认)
rollingUpdate:
maxSurge: 1 # 最多超出副本数
maxUnavailable: 0 # 最多不可用副本数

# === Pod 模板 ===
template:
metadata:
labels: # Pod 标签(必需)
app: my-app
version: v1
annotations:
prometheus.io/scrape: "true"

spec:
# --- 容器配置 ---
containers:
- name: app # 容器名称
image: nginx:1.21 # 镜像地址
imagePullPolicy: Always # 镜像拉取策略

# 启动参数
args:
- "--config=/etc/app/config.yaml"

# 环境变量
env:
- name: ENV
value: "production"

# 端口配置
ports:
- name: http
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP

# 资源配置
resources:
limits: # 资源上限
cpu: "1000m" # 1 核 = 1000m
memory: "2Gi" # 1Gi = 1024Mi
requests: # 资源请求
cpu: "500m"
memory: "1Gi"

# 就绪探针
readinessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3

# 存活探针
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3

# 生命周期钩子
lifecycle:
preStop: # 优雅关闭
exec:
command:
- /bin/sh
- -c
- "sleep 15" # 等待 15 秒

# 卷挂载
volumeMounts:
- name: config
mountPath: /etc/app

# --- Pod 配置 ---
restartPolicy: Always # 重启策略
terminationGracePeriodSeconds: 30 # 优雅关闭时间
dnsPolicy: ClusterFirst # DNS 策略

# 卷定义
volumes:
- name: config
configMap:
name: app-config

配置详解

metadata vs template.metadata

关键区别:

属性描述对象必需字段用途
metadataDeployment 自身name标识 Deployment 资源
template.metadata将要创建的 Podlabels标识和选择 Pod

示例对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Deployment 的元数据
metadata:
name: my-deployment # Deployment 名称 ✅ 必需
namespace: default
labels:
tier: backend # Deployment 的标签

spec:
selector:
matchLabels:
app: my-app # 必须匹配 template.metadata.labels

# Pod 模板的元数据
template:
metadata:
# name: xxx # ❌ 通常不需要,会自动生成
labels:
app: my-app # Pod 的标签 ✅ 必需
version: v1

命名规则:

1
2
3
4
5
6
7
# Deployment 名称
metadata:
name: my-app # 固定名称

# Pod 名称(自动生成)
# 格式:<deployment-name>-<replicaset-hash>-<random-string>
# 示例:my-app-5d4f6c7b8-x9k2m

注意事项:

规则说明
metadata.name 必需Deployment 必须有名称
template.metadata.labels 必需用于 selector 匹配
template.metadata.name 通常不设置Pod 名称自动生成
⚠️ Job 等资源例外Job 的 Pod 需要显式设置名称

更新策略

滚动更新(RollingUpdate):

1
2
3
4
5
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 可以超出副本数的 Pod 数量
maxUnavailable: 0 # 最多不可用的 Pod 数量

参数说明:

参数说明示例效果
maxSurge最多额外创建的 Pod1 或 25%更新时最多 4 个 Pod
maxUnavailable最多不可用的 Pod0 或 25%保证至少 3 个 Pod 可用

更新过程示例(replicas=3):

1
2
3
4
5
6
7
初始状态:[Pod1] [Pod2] [Pod3]

maxSurge=1, maxUnavailable=0:
Step 1: [Pod1] [Pod2] [Pod3] [Pod4-new] ← 创建新 Pod
Step 2: [Pod2] [Pod3] [Pod4-new] [Pod5-new] ← 删除旧 Pod
Step 3: [Pod3] [Pod4-new] [Pod5-new] [Pod6-new]
Step 4: [Pod4-new] [Pod5-new] [Pod6-new] ← 完成

重建策略(Recreate):

1
2
strategy:
type: Recreate # 先删除所有旧 Pod,再创建新 Pod

对比:

1
2
滚动更新:[Old] → [Old+New] → [New]  ✅ 无停机
重建: [Old] → [空] → [New] ❌ 有停机

镜像拉取策略

1
imagePullPolicy: Always      # 镜像拉取策略

策略对比:

策略说明适用场景
Always每次都拉取生产环境(确保最新)
IfNotPresent本地有则不拉取开发环境(节省时间)
Never从不拉取私有镜像(已预加载)

默认行为:

1
2
3
4
5
# tag 为 latest 或未指定
image: nginx:latest imagePullPolicy: Always

# tag 为具体版本
image: nginx:1.21 imagePullPolicy: IfNotPresent

资源配置

1
2
3
4
5
6
7
resources:
limits: # 资源上限(硬限制)
cpu: "1000m" # 1 核 = 1000 millicore
memory: "2Gi" # 1Gi = 1024Mi
requests: # 资源请求(调度依据)
cpu: "500m"
memory: "1Gi"

单位说明:

资源单位换算
CPUm(millicore)1 核 = 1000m
内存Mi, Gi1Gi = 1024Mi = 1024×1024Ki

配置建议:

1
2
3
4
5
6
7
8
9
10
11
# 生产环境推荐
resources:
requests:
cpu: "500m" # 确保最少资源
memory: "1Gi"
limits:
cpu: "2000m" # 防止资源耗尽
memory: "2Gi" # 防止 OOM

# 注意:移除 CPU limits 可能提升性能
# 参考:《移除CPU限制,服务运行更快》

健康检查

就绪探针(Readiness Probe):

1
2
3
4
5
6
7
8
9
10
readinessProbe:
httpGet: # HTTP 检查
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 30 # 初始延迟
periodSeconds: 10 # 检查间隔
timeoutSeconds: 5 # 超时时间
successThreshold: 1 # 成功阈值
failureThreshold: 3 # 失败阈值

探针类型对比:

探针类型用途失败后果
readinessProbe是否准备好接收流量从 Service 移除,不重启
livenessProbe是否存活Pod 重启
startupProbe是否已启动禁用其他探针,失败则重启

检查方式对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# HTTP 检查
httpGet:
path: /health
port: 8080

# TCP 检查
tcpSocket:
port: 3306

# 命令检查
exec:
command:
- cat
- /tmp/healthy

参数说明:

参数说明推荐值
initialDelaySeconds容器启动后多久开始检查30-60s
periodSeconds检查间隔10s
timeoutSeconds超时时间5s
successThreshold成功几次视为健康1
failureThreshold失败几次视为不健康3

生命周期钩子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
lifecycle:
preStop: # Pod 停止前执行
exec:
command:
- /bin/sh
- -c
- "sleep 15 && curl -X POST http://localhost:8080/shutdown"

postStart: # Pod 启动后执行
exec:
command:
- /bin/sh
- -c
- "echo 'Started' > /tmp/started"

优雅关闭流程:

1
2
3
4
5
6
1. Pod 收到 TERM 信号
2. 执行 preStop 钩子
3. 等待 preStop 完成
4. 发送 SIGTERM 给容器
5. 等待 terminationGracePeriodSeconds
6. 如果还未停止,发送 SIGKILL

最佳实践:

1
2
3
4
5
6
7
8
9
10
# 推荐配置
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- "sleep 15" # 等待流量切走

terminationGracePeriodSeconds: 30 # 总超时时间

DNS 策略

1
dnsPolicy: ClusterFirst      # DNS 解析策略

策略对比:

策略说明使用场景
ClusterFirst优先集群 DNS(默认)大部分场景
Default使用节点 DNS特殊网络配置
None不配置 DNS完全自定义
ClusterFirstWithHostNetHostNetwork + 集群 DNShostNetwork=true 时

重启策略

1
restartPolicy: Always        # 容器重启策略

策略对比:

策略行为适用资源
Always总是重启(默认)Deployment, StatefulSet
OnFailure失败时重启Job
Never从不重启Job(一次性)

实战示例

生产环境完整配置

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
apiVersion: apps/v1
kind: Deployment
metadata:
name: production-app
namespace: production
labels:
app: myapp
tier: backend
env: production
annotations:
description: "Production application deployment"
contact: "team@example.com"

spec:
replicas: 3

selector:
matchLabels:
app: myapp
tier: backend

strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0

template:
metadata:
labels:
app: myapp
tier: backend
version: v1.2.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"

spec:
containers:
- name: app
image: registry.example.com/myapp:1.2.0
imagePullPolicy: Always

ports:
- name: http
containerPort: 8080
protocol: TCP
- name: metrics
containerPort: 9090
protocol: TCP

env:
- name: JAVA_OPTS
value: "-Xmx1g -Xms1g"
- name: ENV
value: "production"
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-secret
key: host

resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
memory: "2Gi"
# CPU limits 已移除以提升性能

readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3

livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
failureThreshold: 3

lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- "sleep 15"

volumeMounts:
- name: config
mountPath: /app/config
- name: logs
mountPath: /app/logs

restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst

volumes:
- name: config
configMap:
name: app-config
- name: logs
emptyDir: {}

常用操作命令

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
# 创建 Deployment
kubectl apply -f deployment.yaml

# 查看 Deployment
kubectl get deployment
kubectl get deploy -o wide

# 查看详情
kubectl describe deployment my-app

# 查看 Pod
kubectl get pods -l app=my-app

# 扩缩容
kubectl scale deployment my-app --replicas=5

# 更新镜像
kubectl set image deployment/my-app app=nginx:1.22

# 查看更新状态
kubectl rollout status deployment/my-app

# 查看更新历史
kubectl rollout history deployment/my-app

# 回滚
kubectl rollout undo deployment/my-app
kubectl rollout undo deployment/my-app --to-revision=2

# 暂停/恢复更新
kubectl rollout pause deployment/my-app
kubectl rollout resume deployment/my-app

# 删除 Deployment
kubectl delete deployment my-app

最佳实践

资源配置建议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ✅ 推荐
resources:
requests:
cpu: "500m" # 保证调度
memory: "1Gi"
limits:
memory: "2Gi" # 防止 OOM
# cpu: 不设置 limits # 避免不必要的流控

# ❌ 不推荐
resources:
limits:
cpu: "1000m" # 可能导致流控
memory: "10Gi" # 过大,浪费资源
# 缺少 requests # 调度不准确

健康检查建议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ✅ 推荐配置
readinessProbe:
httpGet:
path: /health/readiness # 专门的就绪检查端点
port: 8080
initialDelaySeconds: 30 # 给应用足够启动时间
periodSeconds: 10
failureThreshold: 3 # 容忍短暂失败

livenessProbe:
httpGet:
path: /health/liveness # 专门的存活检查端点
port: 8080
initialDelaySeconds: 60 # 比 readiness 更长
periodSeconds: 10
failureThreshold: 3

# ❌ 常见错误
# 1. readiness 和 liveness 使用相同端点
# 2. initialDelaySeconds 太短
# 3. failureThreshold 太小(容易误杀)

标签管理建议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# ✅ 推荐的标签结构
metadata:
labels:
app: myapp # 应用名称
version: v1.2.0 # 版本
tier: backend # 层级
env: production # 环境
team: platform # 团队
cost-center: engineering # 成本中心

template:
metadata:
labels:
app: myapp # 必须与 selector 匹配
version: v1.2.0
tier: backend

故障排查

常见问题

问题1:Pod 一直处于 Pending

1
2
3
4
5
6
7
# 检查事件
kubectl describe pod <pod-name>

# 常见原因
# 1. 资源不足
# 2. 镜像拉取失败
# 3. 节点选择器不匹配

问题2:Pod 频繁重启

1
2
3
4
5
6
7
8
# 查看日志
kubectl logs <pod-name>
kubectl logs <pod-name> --previous

# 常见原因
# 1. 应用崩溃
# 2. 健康检查失败
# 3. OOM Kill

问题3:更新失败

1
2
3
4
5
6
7
8
# 查看更新状态
kubectl rollout status deployment/my-app

# 查看事件
kubectl describe deployment my-app

# 回滚
kubectl rollout undo deployment/my-app

总结

Deployment 核心要点:

方面要点建议
元数据metadata vs template.metadata理解两者差异
更新策略滚动更新 vs 重建通常用滚动更新
资源配置requests + limits设置合理值
健康检查readiness + liveness独立端点
优雅关闭preStop + terminationGrace处理流量切换

快速开始:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 最简配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80

参考资料