Kubernetes Deployment
Deployment 是 Kubernetes 中最常用的工作负载(Workload)之一,用于:
- 管理 无状态应用(stateless)
- 滚动升级(Rolling Update)
- 回滚(Rollback)
- 自动重建副本(self-healing)
- 控制 Pod 副本数(ReplicaSet)
Deployment 通过 ReplicaSet 来管理 Pod,但用户几乎不直接操作 ReplicaSet,而是操作 Deployment,K8s 自动维护一致性。
最简 Deployment 示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
replicas: 3
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
image: nginx:1.27
结构解读:
| 字段 | 含义 |
|---|---|
| replicas | Pod 副本数量 |
| selector | Deployment 使用 selector 绑定 ReplicaSet |
| template | Pod 模板,变化时触发滚动更新 |
| strategy | 更新策略(RollingUpdate / Recreate) |
Deployment -> 创建 ReplicaSet(RS) -> RS 创建 Pod
当 Deployment 模板变化时:
- 生成新的 ReplicaSet
- 逐步扩容新的 RS
- 逐步缩容旧的 RS
- 完成后旧 RS 保留(用于回滚)
可以同时存在多个历史 ReplicaSet。
Deployment 默认使用:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
含义:
| 字段 | 含义 |
|---|---|
| maxUnavailable | 更新期间允许“最少缺失”的 Pod 比例或数量 |
| maxSurge | 更新期间允许“多出来”的 Pod 比例或数量 |
例如:replicas=4,maxSurge=1,maxUnavailable=1
更新时允许:
- 最多 5 个 Pod 运行(4 + 1)
- 最少 3 个 Pod 可用(4 - 1)
可避免服务中断,是推荐方式。
strategy:
type: Recreate
更新时:
- 先删光所有 Pod
- 再创建新 Pod
适用场景:
-
需要唯一访问控制,如:
- MySQL(除非 StatefulSet)
- ElasticSearch 单节点
- 某些不能并发运行的 legacy app
保留多少条历史 ReplicaSet(用于回滚)
revisionHistoryLimit: 10
默认值是 10。
Deployment 更新最大时间,超时则标记失败。
progressDeadlineSeconds: 600
默认 600 秒。
新建 Pod 在 ready 状态至少保持多长时间才算“成功”。
minReadySeconds: 5
适合需要预热的服务。
哪些变化会触发新 RS?
会触发的:
- 镜像 tag变化
- 环境变量变化
- configmap/secret 名称变化
- command/args 变化
- labels(template 部分)变化
- 资源限制变化(CPU/Mem)
- 端口配置变化
不会触发的:
- Deployment 的注解变更
- Deployment 的 labels(不影响 template)
kubectl set image deploy/demo demo=nginx:1.28
Kubernetes 会自动滚动更新。
用于进行参数修改后,统一 apply。
kubectl rollout pause deploy/demo
然后更新字段:
kubectl edit deploy/demo
完成后:
kubectl rollout resume deploy/demo
kubectl rollout status deploy/demo
kubectl rollout history deploy/demo
回滚到上一个版本:
kubectl rollout undo deploy/demo
回滚到指定 revision:
kubectl rollout undo deploy/demo --to-revision=3
以下内容非常关键,基本上所有生产集群都建议遵循。
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
不设置意味着 Node 资源调度不可控,引发过载。
livenessProbe:
httpGet: { path: /healthz, port: 8080 }
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet: { path: /ready, port: 8080 }
initialDelaySeconds: 5
periodSeconds: 5
服务可用性明显提升。
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: demo
topologyKey: kubernetes.io/hostname
确保 Pod 分散在多个节点。
保证滚动升级或节点维护不会一次性干掉太多 Pod。
apiVersion: policy/v1
kind: PodDisruptionBudget
spec:
minAvailable: 2
selector:
matchLabels:
app: demo
自动扩容(需 metrics-server):
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
spec:
replicas: 4
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
minReadySeconds: 5
selector:
matchLabels:
app: demo
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: demo
spec:
containers:
- name: demo
image: nginx:1.27
ports:
- containerPort: 80
resources:
requests: { cpu: "200m", memory: "256Mi" }
limits: { cpu: "1", memory: "512Mi" }
readinessProbe:
httpGet: { path: "/", port: 80 }
initialDelaySeconds: 3
livenessProbe:
httpGet: { path: "/", port: 80 }
initialDelaySeconds: 10
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: demo
topologyKey: kubernetes.io/hostname
❗ Pod 不更新?
Deployment template 没有变化,不会触发新 RS。
❗ 更新卡住?
检查:
- readinessProbe 不通过
- 镜像拉取失败
- maxUnavailable 设置过低(如 0)
- PDB 导致无法驱逐旧 Pod
- 新 Pod 调度失败(资源不足)
| Workload | 特点 |
|---|---|
| Deployment | 无状态、滚动更新、回滚 |
| StatefulSet | 有状态、有序启动、稳定网络标识、持久存储 |
| DaemonSet | 每个 Node 一个 Pod |
| Job / CronJob | 一次性任务 / 定时任务 |
| ReplicaSet | Deployment 的底层管理对象,很少直接使用 |
Kubernetes Deployment YAML 配置详解(逐字段解释 + 最佳实践)
内容包括:
- Deployment 整体结构
- 每个字段的详细含义
- 实际 YAML 模板 + 逐行解释
- 多副本滚动更新、探针、资源限制、策略等
- 最佳实践
Deployment 是 Kubernetes 中最常用的 workload,用于:
- 管理 多个副本 Pod
- 自动重建、自动修复
- 提供 滚动更新(rolling update)
- 提供 版本回滚
Deployment 是对 ReplicaSet 的高级封装。
一个 Deployment 主要包含四层:
apiVersion
kind
metadata
spec
├─ replicas
├─ selector
├─ strategy
├─ template
├─ metadata
└─ spec
下面是一个功能最完整的 Deployment 示例,
你可以根据需要裁剪、扩展:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
labels:
app: my-app
spec:
replicas: 3
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
minReadySeconds: 5
paused: false
selector:
matchLabels:
app: my-app
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25% # 更新过程中至少保留多少可用 Pod
maxSurge: 25% # 更新过程中最多超出的 Pod 数量
template:
metadata:
labels:
app: my-app
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
spec:
serviceAccountName: default
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
containers:
- name: my-app
image: my-app:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
env:
- name: ENV
value: "production"
envFrom:
- configMapRef:
name: my-config
- secretRef:
name: my-secret
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
startupProbe:
httpGet:
path: /startup
port: 8080
failureThreshold: 30
periodSeconds: 5
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
livenessProbe:
httpGet:
path: /alive
port: 8080
periodSeconds: 10
volumeMounts:
- name: app-config
mountPath: /etc/my-app
initContainers:
- name: init-db
image: busybox
command: ["sh", "-c", "echo preparing"]
volumes:
- name: app-config
configMap:
name: my-config
metadata:
name: my-app
namespace: default
labels:
app: my-app
- name:Deployment 名称
- namespace:作用的命名空间
- labels:为 Deployment 自身打标签
replicas: 3
期望运行 3 个 Pod。
revisionHistoryLimit: 10
最多保留 10 个旧 ReplicaSet(用于回滚)。
progressDeadlineSeconds: 600
若 600 秒内更新没有完成,则 Deployment 进入 ProgressDeadlineExceeded 状态。
minReadySeconds: 5
Pod 就绪后需要至少 ready 5 秒才算可用。
paused: false
为 true,则暂停滚动更新。
selector:
matchLabels:
app: my-app
用于“选中” template 生成的 Pod。
默认类型是 RollingUpdate:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
- maxUnavailable:更新时最多允许 25% Pod 不可用
- maxSurge:更新时最多多创建 25% Pod
👉 Recreate 模式
strategy:
type: Recreate
- 先删旧 Pod -> 再创建新 Pod
- 适用于:不能并存两个版本的应用(如 MySQL 主节点)。
这是 Deployment 最重要的部分。
labels:
app: my-app
annotations:
prometheus.io/scrape: "true"
labels 与 selector 匹配非常关键。
Deployment 管理的 Pod 内容,例如:
容器列表
containers:
- name: my-app
imagePullPolicy: IfNotPresent
三种:
- Always:每次启动都拉镜像
- IfNotPresent:本地有就不用拉
- Never:永远不拉
🔹 推荐:生产使用 IfNotPresent + tag 固定版本
避免 latest 导致更新不可控。
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
- requests:调度时 Pod 需要的资源
- limits:容器最大可用资源
最佳实践:
- Web 应用:100m–200m
- API 服务:256Mi–512Mi
防止容器还没启动就被重启。
控制 Service 的流量转发。
不健康 -> 自动重启。
initContainers:
- name: init-db
image: busybox
用于初始化:
- 等待数据库
- 初始化目录
initContainers 按顺序执行。
如挂载 ConfigMap / Secret:
volumes:
- name: app-config
configMap:
name: my-config
使用固定标签,不要使用 latest
image: my-app:v1.3.0
使用 readinessProbe 控制流量
避免服务启动早期收到流量而崩溃。
滚动更新策略合理配置
maxUnavailable = 25%
maxSurge = 25%
requests/limits 必须设置(防止节点压力过大)
使用 revisionHistoryLimit 避免副本爆炸
推荐将日志 stdout/stderr 输出到容器标准输出
使用 PodDisruptionBudget(PDB)防止升级导致全挂