Kubernetes Deployment 资源对象
一、Deployment 简介
1.1 什么是 Deployment
Deployment 是 Kubernetes 提供的一种声明式控制器,用于管理 Pod 的部署和更新。它基于 ReplicaSet 实现,提供了应用版本的定义、回滚机制以及滚动更新策略。
plaintext
┌─────────────────────────────────────────────────────────────────────┐
│ Deployment │
│ ┌───────────────────┐ ┌───────────────────┐ │
│ │ Deployment │────▶│ ReplicaSet │ │
│ │ (声明式定义) │ │ (副本管理) │ │
│ └───────────────────┘ └─────────┬─────────┘ │
│ │ │
│ ┌───────────┼───────────┐ │
│ ▼ ▼ ▼ │
│ ┌───────┐ ┌───────┐ ┌───────┐ │
│ │ Pod │ │ Pod │ │ Pod │ │
│ └───────┘ └───────┘ └───────┘ │
└─────────────────────────────────────────────────────────────────────┘
1.2 Deployment 的核心作用
| 功能 | 说明 |
|---|---|
| 副本管理 | 确保指定数量的 Pod 副本持续运行 |
| 滚动更新 | 自动化执行应用的零宕机更新 |
| 版本回滚 | 支持回退到历史的稳定版本 |
| 弹性伸缩 | 手动或自动调整副本数量 |
| 声明式配置 | 声明期望状态,控制器自动调谐 |
1.3 与其他控制器的对比
Kubernetes 提供了多种工作负载控制器,它们各有适用场景:
plaintext
┌──────────────────────────────────────────────────────────────────────┐
│ Kubernetes Workload Controllers │
├──────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Deployment │ │ ReplicaSet │ StatefulSet │ │
│ ├─────────────┤ ├─────────────┤ ├─────────────┤ │
│ │ • 无状态应用 │ │ • 底层副本管理 │ │ • 有状态应用 │ │
│ │ • Web 服务 │ │ • 很少直接使用 │ │ • 数据库 │ │
│ │ • API 服务 │ │ • Deployment │ │ • 消息队列 │ │
│ │ │ │ 的底层实现 │ │ • 持久化存储 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ DaemonSet │ │ Job │ │ CronJob │ │
│ ├─────────────┤ ├─────────────┤ ├─────────────┤ │
│ │ • 守护进程 │ │ • 一次性任务 │ │ • 定时任务 │ │
│ │ • 日志收集 │ │ • 数据迁移 │ │ • 备份任务 │ │
│ │ • 监控代理 │ │ • 批处理作业 │ │ • 报表生成 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────┘
核心区别:
| 控制器 | Pod 标识 | 启动顺序 | 存储 | 典型场景 |
|---|---|---|---|---|
| Deployment | 无序、随机 | 并行 | 共享/无持久化 | Web 服务、API |
| ReplicaSet | 无序、随机 | 并行 | 共享/无持久化 | 很少直接使用 |
| StatefulSet | 固定标识 | 有序 | 独立持久化 | MySQL、Kafka |
| DaemonSet | 固定节点 | 每节点一个 | 本地/无持久化 | 日志、监控 |
| Job | 无标识 | 并行/有序 | 无 | 数据迁移、批处理 |
二、核心概念详解
2.1 Pod 模板(Pod Template)
Pod 模板是 Deployment 的核心组成部分,定义了 Pod 的规格:
yaml
spec:
template:
metadata:
labels:
app: my-app
version: v1
spec:
containers:
- name: my-container
image: nginx:1.25
ports:
- containerPort: 80
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "100m"
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 3
periodSeconds: 10
重要:Deployment 下的 Pod 模板与 Pod 本身的
metadata独立。Deployment 会为 ReplicaSet 生成标签以实现关联。
2.2 副本数(Replicas)
副本数定义了期望运行的 Pod 数量:
yaml
spec:
replicas: 3 # 期望 3 个 Pod 副本
副本数的语义:
plaintext
┌─────────────────────────────────────┐
│ Deployment (replicas: 3) │
│ │
desired replicas ───▶│ [Pod-1] [Pod-2] [Pod-3] │◀─── ready: 3
│ │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 控制器调谐逻辑 │
│ │
│ 期望数 (3) vs 实际数 (2) │
│ ↓ │
│ 差距 = 1,创建新 Pod │
└─────────────────────────────────────┘
2.3 选择器(Selector)
Selector 是 Deployment 连接 ReplicaSet 和 Pod 的桥梁:
yaml
spec:
selector:
matchLabels:
app: my-app
工作原理:
plaintext
┌─────────────────────────────────────────────────────────────────────┐
│ Selector 匹配关系 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Deployment.spec.selector → ReplicaSet.spec.selector │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ matchLabels: │ │ matchLabels: │ │
│ │ app: my-app │────────────▶│ app: my-app │ │
│ └─────────────────────┘ └──────────┬──────────┘ │
│ │ │
│ ▼ │
│ Pod.spec.metadata.labels │
│ ┌─────────────────────┐ │
│ │ labels: │ │
│ │ app: my-app │ │
│ │ version: v1 │ │
│ └─────────────────────┘ │
│ │
│ ⚠️ 注意:Pod 标签必须包含 selector 匹配的所有标签 │
│ Pod 可以有额外的标签,但 selector 必须完全匹配 │
└─────────────────────────────────────────────────────────────────────┘
⚠️ 注意事项:
- Selector 是不可变的,创建后不能修改(除非使用
matchExpressions且在特定版本支持) - Pod 模板中的标签必须匹配 Selector
- 避免与同命名空间下其他 Deployment 的标签重叠
2.4 策略类型(strategy)
Deployment 支持两种更新策略:
2.4.1 RollingUpdate(滚动更新)
yaml
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最大超过副本数
maxUnavailable: 0 # 最大不可用副本数
参数详解:
| 参数 | 类型 | 说明 | 示例值 |
|---|---|---|---|
maxSurge |
int/percentage | 更新过程中最多超出期望副本数 | 1 或 25% |
maxUnavailable |
int/percentage | 更新过程中最多不可用副本数 | 0 或 25% |
滚动更新示意图:
plaintext
初始状态: 3 个 Pod (v1)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Step 1: 启动 1 个新 Pod (v2)
maxSurge=1
┌─────────────────────────────────────────────────────────────┐
│ [Pod-v1] [Pod-v1] [Pod-v1] → [Pod-v2] │
│ ↑ │
│ 新启动 │
└─────────────────────────────────────────────────────────────┘
Step 2: 终止 1 个旧 Pod (v1)
maxUnavailable=0, 所以先增后减
┌─────────────────────────────────────────────────────────────┐
│ [Pod-v1] [Pod-v1] [Pod-v2] │
│ ↓ │
│ 终止 1 个 │
└─────────────────────────────────────────────────────────────┘
Step 3-4: 重复 Step 1-2
┌─────────────────────────────────────────────────────────────┐
│ [Pod-v1] [Pod-v2] [Pod-v2] → [Pod-v1] [Pod-v2] [Pod-v2] │
│ ↓ 替换 ↓ │
│ 终止旧 完成 终止旧 │
└─────────────────────────────────────────────────────────────┘
最终状态: 3 个 Pod (v2)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2.4.2 Recreate(重建)
yaml
spec:
strategy:
type: Recreate
重建策略示意图:
plaintext
┌─────────────────────────────────────────────────────────────────────┐
│ Recreate 策略执行流程 │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ 时间线 ──────────────────────────────────────────────────────▶ │
│ │
│ 阶段1: 终止所有旧 Pod │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ [Pod-v1] [Pod-v1] [Pod-v1] ──X──X──X──▶ (空) │ │
│ │ ✗ ✗ ✗ │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ (等待所有 Pod 真正终止) │
│ ▼ │
│ 阶段2: 创建所有新 Pod │
│ ┌──────────────────────────────────────────────────────────────┐ │
│ │ (空) ──▶ [Pod-v2] [Pod-v2] [Pod-v2] │ │
│ │ + + + │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ⚠️ 注意: 存在服务中断窗口 │
└─────────────────────────────────────────────────────────────────────┘
策略选择建议:
| 策略 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| RollingUpdate | 大多数生产环境 | 零宕机、平滑过渡 | 更新时间长、资源占用高 |
| Recreate | 无法容忍旧新版本共存 | 简单、资源占用低 | 有服务中断窗口 |
三、工作原理深度剖析
3.1 控制器架构
Deployment 控制器是 Kubernetes 控制平面的一部分:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ Kubernetes Control Plane │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ API Server (6443) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │ REST API │ │ Auth N │ │ Validat │ │ Mutate │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ Watch/List │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ etcd (数据存储) │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │
│ │ │Deployments│ │ReplicaSets│ │ Pods │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Controller Manager │ │
│ │ ┌────────────────────┐ ┌────────────────────┐ │ │
│ │ │ Deployment Controller│ │ ReplicaSet Controller│ │ │
│ │ │ • 创建/更新 ReplicaSet│ │ • 管理 Pod 副本 │ │ │
│ │ │ • 管理版本历史 │ │ • 处理 Pod 故障 │ │ │
│ │ └────────────────────┘ └────────────────────┘ │ │
│ │ ┌────────────────────┐ ┌────────────────────┐ │ │
│ │ │ Node Controller │ │ Resource Controller│ │ │
│ │ │ • 节点健康检测 │ │ • HPA 扩缩容 │ │ │
│ │ └────────────────────┘ └────────────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │
└────────────────────────────────────│────────────────────────────────────────┘
│
│ 调度与通信
┌────────────────────────────┼────────────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Node 1 │ │ Node 2 │ │ Node 3 │
│ ┌───────────┐ │ │ ┌───────────┐ │ │ ┌───────────┐ │
│ │ kubelet │ │ │ │ kubelet │ │ │ │ kubelet │ │
│ │ ↓ │ │ │ │ ↓ │ │ │ │ ↓ │ │
│ │ Pod 运行 │ │ │ │ Pod 运行 │ │ │ │ Pod 运行 │ │
│ └───────────┘ │ │ └───────────┘ │ │ └───────────┘ │
└───────────────┘ └───────────────┘ └───────────────┘
3.2 创建流程
Deployment 创建时的资源生成链:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ Deployment 创建流程 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 用户操作 │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ kubectl apply -f deployment.yaml │ │
│ │ 或: kubectl create deployment my-app --image=nginx:latest │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ API Server │ │
│ │ 1. 认证 & 授权 │ │
│ │ 2. 验证 YAML 合法性 │ │
│ │ 3. 写入 etcd (Deployment 对象) │ │
│ │ 4. 返回 success 给客户端 │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ Deployment Controller 监听到新对象 │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Deployment Controller │ │
│ │ │ │
│ │ 1. 创建 ReplicaSet (初始版本 revision=1) │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ ReplicaSet Spec: │ │ │
│ │ │ replicas: 3 │ │ │
│ │ │ selector: {app: my-app} │ │ │
│ │ │ template: {Pod 模板内容} │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ 2. 记录版本历史 (deployment.kubernetes.io/revision-history) │ │
│ │ 3. 设置注解 (deployment.kubernetes.io/revision: "1") │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ ReplicaSet Controller 监听到新对象 │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ ReplicaSet Controller │ │
│ │ │ │
│ │ 计算: desired(3) - current(0) = 需要创建 3 个 Pod │ │
│ │ │ │
│ │ 调用 Scheduler │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ 调度决策: │ │ │
│ │ │ Pod-1 → Node-1 (资源充足) │ │ │
│ │ │ Pod-2 → Node-2 (资源充足) │ │ │
│ │ │ Pod-3 → Node-3 (资源充足) │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ │ kubelet 在各节点上创建 Pod │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ kubelet │ │
│ │ │ │
│ │ 1. 从容器运行时拉取镜像 │ │
│ │ 2. 创建容器 (Pause 容器 + 业务容器) │ │
│ │ 3. 配置网络 (CNI 插件) │ │
│ │ 4. 启动并监控容器 │ │
│ │ 5. 汇报状态给 API Server │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Pod Running ✓ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
3.3 更新流程(滚动更新机制)
Deployment 更新时的滚动升级流程:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ 滚动更新详细流程 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 假设: replicas=3, maxSurge=1, maxUnavailable=0 │
│ 初始: 3 个 v1 Pod │
│ 更新: 镜像从 nginx:1.21 → nginx:1.25 │
│ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Deployment 更新 │ │
│ │ │ │
│ │ 触发方式: │ │
│ │ • kubectl apply -f deployment.yaml │ │
│ │ • kubectl set image deployment/my-app nginx=nginx:1.25 │ │
│ │ • kubectl edit deployment my-app │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ Deployment Controller 处理 │ │
│ │ │ │
│ │ 1. 创建新的 ReplicaSet (revision=2) │ │
│ │ - 副本数: maxSurge (1) │ │
│ │ │ │
│ │ 2. 更新旧 ReplicaSet (revision=1) │ │
│ │ - 副本数: 逐步减少 │ │
│ │ │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
└────────────────────────────────────│────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ 滚动更新进度可视化 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 状态 │ Node-1 │ Node-2 │ Node-3 │ 说明 │
│ ────────┼───────────────┼───────────────┼───────────────┼──────────────── │
│ │ │ │ │ │
│ 初始 │ [Pod-v1] │ [Pod-v1] │ [Pod-v1] │ 3 个 v1 Pod │
│ │ │ │ │ │
│ Step 1 │ [Pod-v1] │ [Pod-v1] │ [Pod-v1] │ 新 RS 启动 1 个 │
│ │ │ │ [Pod-v2] NEW│ v2 Pod (maxSurge)│
│ │ │ │ │ │
│ Step 2 │ [Pod-v1] │ [Pod-v1] │ [Pod-v2] │ 终止 1 个 v1 │
│ │ ✗ │ │ │ (maxUnavailable=0)│
│ │ │ │ │ │
│ Step 3 │ [Pod-v1] │ [Pod-v2] NEW │ [Pod-v2] │ 新 RS 再启动 1 个│
│ │ │ │ │ │
│ Step 4 │ [Pod-v1] │ [Pod-v2] │ [Pod-v2] │ 再终止 1 个 v1 │
│ │ ✗ │ │ │ │
│ Step 5 │ [Pod-v2] NEW │ [Pod-v2] │ [Pod-v2] │ 最后 1 个 v2 │
│ │ │ │ │ │
│ Step 6 │ [Pod-v2] │ [Pod-v2] │ [Pod-v2] │ 最后 1 个 v1 终止 │
│ │ │ ✗ │ │ │
│ │ │ │ │ │
│ 完成 │ [Pod-v2] │ [Pod-v2] │ [Pod-v2] │ 全 v2 ✓ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
3.4 回滚机制
Deployment 自动保存历史版本,支持快速回退:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ 回滚机制原理 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 回滚命令: │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ # 回滚到上一个版本 │ │
│ │ kubectl rollout undo deployment/my-app │ │
│ │ │ │
│ │ # 回滚到指定版本 │ │
│ │ kubectl rollout undo deployment/my-app --to-revision=2 │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ 版本历史管理 │ │
│ │ │ │
│ │ Deployment 注解中的版本信息: │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ kubernetes.io/change-cause: "Update image nginx to 1.25" │ │ │
│ │ │ deployment.kubernetes.io/revision: "3" │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ │ │ │
│ │ 保留的 ReplicaSet 历史 (通过 revisionHistoryLimit 控制): │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ RS (v1) │ │ RS (v2) │ │ RS (v3) │ ← 当前活跃 │ │
│ │ │ revision=1 │ │ revision=2 │ │ revision=3 │ │ │
│ │ │ replicas=0 │ │ replicas=0 │ │ replicas=3 │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ │ │
│ │ revisionHistoryLimit=10 (默认保留 10 个历史版本) │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ 回滚执行过程 │ │
│ │ │ │
│ │ 1. 将目标 ReplicaSet 的副本数调整为期望值 │ │
│ │ 2. 将当前 ReplicaSet 的副本数调整为 0 │ │
│ │ 3. 更新 Deployment 的 revision 注解 │ │
│ │ 4. 生成新的 rollout 历史记录 │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
四、YAML 配置详解
4.1 完整配置示例
yaml
apiVersion: apps/v1 # API 版本
kind: Deployment # 资源类型
metadata:
name: my-nginx # Deployment 名称
namespace: default # 所属命名空间
labels: # Deployment 标签
app: my-nginx
tier: frontend
annotations: # 注解
description: "Nginx web server deployment"
kubernetes.io/change-cause: "Initialize deployment"
spec:
replicas: 3 # 副本数
selector: # Pod 选择器(必须匹配 Pod 标签)
matchLabels:
app: my-nginx
strategy: # 更新策略
type: RollingUpdate # 滚动更新
rollingUpdate:
maxSurge: 1 # 最多超出副本数
maxUnavailable: 0 # 最多不可用副本数
minReadySeconds: 10 # Pod 就绪后最少保持时间
revisionHistoryLimit: 10 # 保留的历史版本数
paused: false # 是否暂停更新
progressDeadlineSeconds: 600 # 进度超时时间
template: # Pod 模板
metadata:
labels:
app: my-nginx # 必须包含 selector 匹配的所有标签
version: v1
spec:
# 容器配置
containers:
- name: nginx
image: nginx:1.25-alpine
imagePullPolicy: IfNotPresent # 镜像拉取策略
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
# 资源管理
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "500m"
# 健康检查
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
failureThreshold: 3
# 启动探针(K8s 1.16+)
startupProbe:
httpGet:
path: /healthz
port: http
failureThreshold: 30
periodSeconds: 10
# 环境变量
env:
- name: APP_ENV
value: "production"
- name: LOG_LEVEL
value: "info"
# 配置挂载
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
readOnly: true
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-run
mountPath: /var/run
# 初始化容器(如需要)
initContainers:
- name: init-myservice
image: busybox:1.36
command: ['sh', '-c', 'echo Waiting for service; sleep 5']
# 亲和性配置
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: my-nginx
topologyKey: kubernetes.io/hostname
# 容忍污点
tolerations:
- key: "node-role"
operator: "Equal"
value: "web"
effect: "NoSchedule"
# 安全上下文
securityContext:
runAsNonRoot: true
runAsUser: 101
fsGroup: 101
# 镜像拉取凭证
imagePullSecrets:
- name: my-registry-secret
# 共享存储卷
volumes:
- name: nginx-config
configMap:
name: nginx-config
items:
- key: default.conf
path: default.conf
- name: nginx-cache
emptyDir:
sizeLimit: "100Mi"
- name: nginx-run
emptyDir: {}
4.2 各字段含义说明
| 字段路径 | 类型 | 必填 | 说明 |
|---|---|---|---|
apiVersion |
string | 是 | API 版本,固定为 apps/v1 |
kind |
string | 是 | 资源类型,固定为 Deployment |
metadata.name |
string | 是 | Deployment 名称,命名空间内唯一 |
metadata.namespace |
string | 否 | 所属命名空间,默认 default |
metadata.labels |
map | 否 | Deployment 的标签 |
metadata.annotations |
map | 否 | 注解信息 |
spec.replicas |
integer | 否 | 期望副本数,默认 1 |
spec.selector |
object | 是 | Pod 选择器,定义如何识别管理的 Pod |
spec.selector.matchLabels |
map | 是 | 标签匹配规则 |
spec.selector.matchExpressions |
list | 否 | 表达式匹配(可选) |
spec.strategy.type |
string | 否 | 更新策略:RollingUpdate 或 Recreate |
spec.strategy.rollingUpdate.maxSurge |
int/string | 否 | 滚动更新时最多超出副本数 |
spec.strategy.rollingUpdate.maxUnavailable |
int/string | 否 | 滚动更新时最多不可用副本数 |
spec.minReadySeconds |
integer | 否 | Pod 就绪后最少保持时间 |
spec.revisionHistoryLimit |
integer | 否 | 保留的历史版本数,默认 10 |
spec.paused |
boolean | 否 | 是否暂停更新 |
spec.progressDeadlineSeconds |
integer | 否 | 进度超时时间(秒) |
spec.template |
object | 是 | Pod 模板规格 |
spec.template.metadata |
object | 是 | Pod 元数据 |
spec.template.spec |
object | 是 | Pod 规格定义 |
4.3 常用配置模式
4.3.1 基础 Web 服务
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-service
spec:
replicas: 3
selector:
matchLabels:
app: web-service
template:
metadata:
labels:
app: web-service
spec:
containers:
- name: web
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "200m"
4.3.2 高可用多副本服务
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ha-service
spec:
replicas: 5
selector:
matchLabels:
app: ha-service
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 2
maxUnavailable: 1
template:
metadata:
labels:
app: ha-service
spec:
affinity:
# Pod 反亲和,确保副本分布在不同节点
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: ha-service
topologyKey: kubernetes.io/hostname
containers:
- name: service
image: myapp:v2.0
ports:
- containerPort: 8080
4.3.3 配置健康检查的服务
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-probes
spec:
replicas: 2
selector:
matchLabels:
app: app-with-probes
template:
metadata:
labels:
app: app-with-probes
spec:
containers:
- name: app
image: myapp:v1.0
ports:
- containerPort: 8080
# 启动探针(容器启动期间使用)
startupProbe:
httpGet:
path: /startup
port: 8080
failureThreshold: 30
periodSeconds: 10
# 存活探针(检测容器是否存活)
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
timeoutSeconds: 3
failureThreshold: 3
# 就绪探针(检测是否可以接收流量)
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
successThreshold: 1
五、常用操作指南
5.1 创建与删除
bash
# 创建 Deployment
kubectl apply -f deployment.yaml
# 或使用命令创建
kubectl create deployment my-app --image=nginx:latest --replicas=3
# 查看创建状态
kubectl get deployment my-app
kubectl rollout status deployment/my-app
# 删除 Deployment(会同时删除关联的 ReplicaSet 和 Pod)
kubectl delete deployment my-app
# 强制删除(如果卡住)
kubectl delete deployment my-app --grace-period=0 --force
# 删除并等待完成
kubectl delete deployment my-app --wait=true
5.2 扩缩容
5.2.1 手动扩缩容
bash
# 扩容到 5 个副本
kubectl scale deployment my-app --replicas=5
# 缩容到 1 个副本
kubectl scale deployment my-app --replicas=1
# 扩缩容多个 Deployment
kubectl scale deployment app1,app2,app3 --replicas=3
# 条件扩缩容(仅当副本数满足条件时才执行)
kubectl scale deployment my-app --current-replicas=3 --replicas=5
5.2.2 HPA 自动扩缩容
bash
# 创建 HPA
kubectl autoscale deployment my-app --min=2 --max=10 --cpu-percent=80
# 查看 HPA
kubectl get hpa
# 删除 HPA
kubectl delete hpa my-app
HPA 配合 Deployment 示例:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ HPA + Deployment 联动 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────┐ │
│ │ HPA │ │
│ │ min=2 │ │
│ │ max=10 │ │
│ │ target=80% │ │
│ └───────┬───────┘ │
│ │ │
│ │ 动态调整 replicas │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Deployment Controller │ │
│ │ │ │
│ │ CPU 使用率 ──▶ 高 ──────────▶ replicas: 2 → 3 → 5 → 8 → 10 │ │
│ │ CPU 使用率 ──▶ 低 ──────────▶ replicas: 10 → 8 → 5 → 3 → 2 │ │
│ │ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ 扩缩容触发条件: │
│ • 当前 CPU 使用率 > targetCPUUtilizationPercentage → 扩容 │
│ • 当前 CPU 使用率 < targetCPUUtilizationPercentage → 缩容 │
│ • 冷却时间: 5 分钟(扩容)、5 分钟(缩容) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
5.3 更新策略配置
bash
# 查看当前更新策略
kubectl get deployment my-app -o jsonpath='{.spec.strategy}'
# 修改更新策略(立即生效)
kubectl patch deployment my-app -p '{"spec":{"strategy":{"type":"RollingUpdate","rollingUpdate":{"maxSurge":2,"maxUnavailable":1}}}}'
# 或使用 edit
kubectl edit deployment my-app
常见策略配置组合:
| 场景 | maxSurge | maxUnavailable | 说明 |
|---|---|---|---|
| 保守更新 | 1 | 0 | 逐个替换,最安全 |
| 快速更新 | 2 | 1 | 平衡速度和安全性 |
| 激进更新 | 3 | 1 | 快速但资源占用高 |
| 最大效率 | 25% | 25% | 按百分比计算 |
5.4 版本回滚
bash
# 查看部署历史
kubectl rollout history deployment/my-app
# 查看特定版本的详细信息
kubectl rollout history deployment/my-app --revision=3
# 回滚到上一个版本
kubectl rollout undo deployment/my-app
# 回滚到指定版本
kubectl rollout undo deployment/my-app --to-revision=2
# 查看回滚状态
kubectl rollout status deployment/my-app
5.5 暂停与恢复更新
bash
# 暂停更新(用于批量修改)
kubectl rollout pause deployment/my-app
# 执行多次修改(不会触发滚动更新)
kubectl set image deployment/my-app nginx=nginx:1.24
kubectl set resources deployment/my-app --limits=cpu=500m,memory=256Mi
kubectl label deployment/my-app version=v2
# 查看暂停状态
kubectl get deployment my-app -o jsonpath='{.spec.paused}' # true 表示暂停
# 恢复更新(触发滚动更新)
kubectl rollout resume deployment/my-app
# ⚠️ 注意事项:恢复时会一次性应用所有暂停期间的变更
暂停/恢复流程:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ 暂停与恢复更新流程 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Step 1: 暂停 │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ kubectl rollout pause deployment/my-app │ │
│ │ │ │
│ │ 结果: spec.paused = true │ │
│ │ Controller 停止监听 Deployment 变更 │ │
│ │ ReplicaSet 保持不变 │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Step 2: 多次修改(不触发滚动更新) │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ kubectl set image deployment/my-app nginx=nginx:1.24 │ │
│ │ kubectl set image deployment/my-app nginx=nginx:1.25 │ │
│ │ kubectl set image deployment/my-app nginx=nginx:1.26 │ │
│ │ │ │
│ │ Deployment spec 已更新,但 ReplicaSet 不受影响 │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ Step 3: 恢复(一次性应用所有变更) │
│ ┌──────────────────────────────────────────────────────────────────────┐ │
│ │ kubectl rollout resume deployment/my-app │ │
│ │ │ │
│ │ Controller 检测到 paused=false │ │
│ │ 发现 spec 与当前 ReplicaSet 不同 │ │
│ │ 创建新 ReplicaSet 并触发一次滚动更新 │ │
│ │ (应用的是最后一次的镜像) │ │
│ └──────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
5.6 其他常用命令
bash
# 获取 Deployment 详情
kubectl describe deployment my-app
# 查看 Pod 分布
kubectl get pods -l app=my-app -o wide
# 查看 Deployment 事件
kubectl get events --field-selector involvedObject.name=my-app
# 导出 YAML
kubectl get deployment my-app -o yaml > deployment-backup.yaml
# 应用部分更新(使用 patch)
kubectl patch deployment my-app -p '{"spec":{"replicas":5}}'
# 强制替换(删除后重建,用于不可修改字段)
kubectl replace --force -f deployment.yaml
六、高级特性
6.1 滚动更新参数详解
yaml
spec:
strategy:
type: RollingUpdate
rollingUpdate:
# maxSurge: 最大超出副本数
# 形式: 整数 (如 1) 或 百分比 (如 25%)
# 效果: 滚动更新期间,Pod 总数可以超过 replicas 数量
maxSurge: 1 # 或 "25%"
# maxUnavailable: 最大不可用副本数
# 形式: 整数 (如 1) 或 百分比 (如 25%)
# 效果: 滚动更新期间,可以有最多这么多 Pod 不可用
maxUnavailable: 0 # 或 "25%"
# minReadySeconds: Pod 就绪后最少保持时间
# Pod 必须持续运行这段时间才被认为可用
minReadySeconds: 10
# progressDeadlineSeconds: 进度超时时间
# 如果在指定秒数内没有进度,Deployment 状态标记为 False
progressDeadlineSeconds: 600
参数组合效果:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ maxSurge 与 maxUnavailable 组合效果 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ replicas=3 时的 Pod 数量变化: │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 配置组合 │ 最大 Pod 数 │ 最小可用 Pod │ 更新速度 │ │
│ ├────────────────────────┼──────────────┼───────────────┼──────────── │ │
│ │ maxSurge=0, maxUnav=0 │ ❌ 不可能(无意义) │ │
│ ├────────────────────────┼──────────────┼───────────────┼──────────── │ │
│ │ maxSurge=1, maxUnav=0 │ 3+1=4 │ 3 │ 慢 │ │
│ ├────────────────────────┼──────────────┼───────────────┼──────────── │ │
│ │ maxSurge=0, maxUnav=1 │ 3 │ 3-1=2 │ 慢 │ │
│ ├────────────────────────┼──────────────┼───────────────┼──────────── │ │
│ │ maxSurge=1, maxUnav=1 │ 3+1=4 │ 3-1=2 │ 中等 │ │
│ ├────────────────────────┼──────────────┼───────────────┼──────────── │ │
│ │ maxSurge=25%, maxUnav=0│ ceil(3*1.25)=4│ 3 │ 慢 │ │
│ ├────────────────────────┼──────────────┼───────────────┼──────────── │ │
│ │ maxSurge=25%, maxUnav=25%│ ceil(3*1.25)=4│ ceil(3*0.75)=3│ 中等 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ 图示: │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ maxSurge=1, maxUnav=0 (最安全,资源消耗大) │ │
│ │ ┌────┬────┬────┬────┐ │ │
│ │ │ v1 │ v1 │ v1 │ v2 │ → ✗ → │ v2 │ v2 │ v2 │ │ │
│ │ └────┴────┴────┴────┘ └────┴────┴────┘ │ │
│ │ 同时最多 4 个 Pod,v1 全部终止后 v2 才完全接管 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ maxSurge=1, maxUnav=1 (平衡模式) │ │
│ │ ┌────┬────┬────┬────┐ │ │
│ │ │ v1 │ v1 │ v1 │ v2 │ → ✗ → │ v1 │ v2 │ v2 │ → ✗ → │ v2 │ v2 │ v2 │ │
│ │ └────┴────┴────┴────┘ └────┴────┴────┘ └────┴────┴────┘ │
│ │ 同时最多 4 个 Pod,最少 2 个可用 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
6.2 金丝雀发布
金丝雀发布允许将新版本逐步推向小部分用户:
yaml
# 1. 主版本 Deployment(v1,承载 95% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-stable
labels:
app: my-app
track: stable
spec:
replicas: 3
selector:
matchLabels:
app: my-app
track: stable
template:
metadata:
labels:
app: my-app
track: stable
spec:
containers:
- name: my-app
image: myapp:v1
ports:
- containerPort: 8080
---
# 2. 金丝雀 Deployment(v2,承载 5% 流量)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-canary
labels:
app: my-app
track: canary
spec:
replicas: 1
selector:
matchLabels:
app: my-app
track: canary
template:
metadata:
labels:
app: my-app
track: canary
spec:
containers:
- name: my-app
image: myapp:v2
ports:
- containerPort: 8080
---
# 3. Service 选择器(同时覆盖两个版本)
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
selector:
app: my-app # 匹配所有 track
ports:
- port: 80
targetPort: 8080
金丝雀发布流量分配:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ 金丝雀发布架构 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 用户请求 │
│ │ │
│ ▼ │
│ ┌────────────────────┐ │
│ │ Service │ │
│ │ (selector: app) │ │
│ └─────────┬──────────┘ │
│ │ │
│ ┌───────────────┴───────────────┐ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Stable (v1) │ │ Canary (v2) │ │
│ │ replicas: 3 │ │ replicas: 1 │ │
│ │ track=stable │ │ track=canary │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Pod-1 v1 ✓ │ │ Pod-4 v2 ✓ │ │
│ │ Pod-2 v1 ✓ │ └─────────────┘ │
│ │ Pod-3 v1 ✓ │ │
│ └─────────────┘ │
│ │
│ 流量比例: 75% ────────────→ Stable │
│ 25% ───→ Canary │
│ │
│ 提升金丝雀: replicas: 1 → 3 (50% 流量) │
│ 完全发布: 合并配置,删除 canary deployment │
│ 回滚: 删除 canary deployment │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
6.3 蓝绿部署
蓝绿部署通过两套完整环境实现即时切换:
yaml
# 蓝环境 Deployment(当前生产环境)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-blue
labels:
app: my-app
env: blue
spec:
replicas: 3
selector:
matchLabels:
app: my-app
env: blue
template:
metadata:
labels:
app: my-app
env: blue
spec:
containers:
- name: my-app
image: myapp:v1
ports:
- containerPort: 8080
---
# 蓝环境 Service
apiVersion: v1
kind: Service
metadata:
name: my-app-svc
spec:
selector:
app: my-app
env: blue
ports:
- port: 80
targetPort: 8080
蓝绿部署流程:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ 蓝绿部署流程 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 阶段 1: 初始状态(蓝环境为生产) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ 蓝 v1 │ ◀── active │ 绿 v2 │ │ │
│ │ │ (生产环境) │ │ (预发布环境) │ │ │
│ │ │ replicas=3 │ │ replicas=3 │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ │ │ │ │ │
│ │ └──────────────┬──────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─────────────────┐ │ │
│ │ │ Service │ │ │
│ │ │ selector: env=blue ← 流量全部进入蓝环境 │ │
│ │ └─────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ 阶段 2: 部署绿环境 │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ # 更新绿环境 Deployment │ │
│ │ kubectl apply -f my-app-green.yaml │ │
│ │ │ │
│ │ 测试绿环境(直接访问) │ │
│ │ kubectl run test --image=curlimages/curl --rm -it --restart=Never │ │
│ │ -- curl http://<green-pod-ip>:8080/health │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ 阶段 3: 切换流量(蓝绿切换) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ # 修改 Service selector 切换到绿环境 │ │
│ │ kubectl patch service my-app-svc -p '{"spec":{"selector":{"env":"green"}}}' │
│ │ │ │
│ │ ┌──────────────────────────────────────────────────────────────┐ │ │
│ │ │ Service selector: env=green │ │ │
│ │ │ ↓ 流量切换 │ │ │
│ │ │ ┌─────────────┐ │ │ │
│ │ │ │ 绿 v2 │ ◀── 新生产环境 (active) │ │ │
│ │ │ └─────────────┘ │ │ │
│ │ │ ✗ │ │ │
│ │ │ ┌─────────────┐ │ │ │
│ │ │ │ 蓝 v1 │ ← 旧环境 (standby) │ │ │
│ │ │ └─────────────┘ │ │ │
│ │ └──────────────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ 阶段 4: 回滚(如需要) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ # 一键回滚到蓝环境 │ │
│ │ kubectl patch service my-app-svc -p '{"spec":{"selector":{"env":"blue"}}}' │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ 优点: 即时切换,零停机,支持快速回滚 │
│ 缺点: 需要双倍资源 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
6.4 与 HPA/VPA 配合
6.4.1 HPA(水平自动扩缩容)
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 缩容冷却 5 分钟
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0 # 扩容立即执行
policies:
- type: Percent
value: 100
periodSeconds: 15
selectPolicy: Max
6.4.2 VPA(垂直自动扩缩容)
yaml
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: my-app-vpa
spec:
targetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app
updatePolicy:
updateMode: "Auto" # Auto 或 Off
resourcePolicy:
containerPolicies:
- containerName: my-app
minAllowed:
cpu: 50m
memory: 64Mi
maxAllowed:
cpu: 2
memory: 1Gi
controlledResources: ["cpu", "memory"]
6.4.3 HPA + VPA 结合
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ HPA 与 VPA 结合使用 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────┐ │
│ │ HPA │ │
│ │ 水平扩缩容 │ │
│ │ 控制 replicas │ │
│ └──────────┬───────────┘ │
│ │ │
│ │ │
│ ┌───────────────────────────────────┼───────────────────────────────────┐ │
│ │ ▼ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ Deployment │ │ │
│ │ │ │ │ │
│ │ │ replicas: 3 → 6 │ │ │
│ │ │ (HPA 扩容) │ │ │
│ │ └──────────┬───────────┘ │ │
│ │ │ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ VPA │ │ │
│ │ │ 垂直扩缩容 │ │ │
│ │ │ 控制 resources │ │ │
│ │ └──────────┬───────────┘ │ │
│ │ │ │ │
│ └───────────────────────────────────┼───────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ Pod │ │
│ │ cpu: 100m → 200m │ │
│ │ memory: 128Mi→ 256Mi │ │
│ │ (VPA 调整) │ │
│ └──────────────────────┘ │
│ │
│ 典型场景: │
│ • HPA: 根据 CPU/内存使用率调整副本数 │
│ • VPA: 根据历史资源使用自动调整容器规格 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
七、状态与生命周期
7.1 状态字段含义
bash
kubectl get deployment my-app -o wide
输出示例与字段说明:
plaintext
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
my-app 3/3 1 3 10m my-app nginx:1.25 app=my-app
| 字段 | 说明 |
|---|---|
READY |
当前就绪 Pod 数 / 期望副本数 (如 3/3) |
UP-TO-DATE |
已更新到期望版本的 Pod 数 |
AVAILABLE |
可用(就绪且非终止状态)的 Pod 数 |
AGE |
Deployment 创建至今的时间 |
完整状态查看:
bash
kubectl get deployment my-app -o jsonpath='{.status}'
json
{
"conditions": [
{
"type": "Available",
"status": "True",
"reason": "MinimumReplicasAvailable",
"message": "Deployment has minimum availability."
},
{
"type": "Progressing",
"status": "True",
"reason": "NewReplicaSetAvailable",
"message": "ReplicaSet \"my-app-7d9b65c8f5\" has successfully progressed."
}
],
"replicas": 3,
"readyReplicas": 3,
"availableReplicas": 3,
"updatedReplicas": 1,
"collisionCount": 0
}
7.2 条件类型判断
Deployment 通过 Conditions 表示当前状态:
| Condition Type | True 含义 | False 含义 |
|---|---|---|
Available |
至少最小可用副本数就绪 | 有 Pod 不可用 |
Progressing |
Deployment 正在推进(创建/更新中) | Deployment 进度卡住 |
ReplicaFailure |
- | 创建 Pod 失败 |
Progressing 条件的详细判断:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ Progressing 条件判断逻辑 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Progressing = True (满足任一条件): │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 1. Deployment 正在执行创建或更新 │ │
│ │ 2. 所有 Pod 都就绪(READY = replicas) │ │
│ │ 3. 没有正在终止的 Pod │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Progressing = False (原因): │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ reason: "ProgressDeadlineExceeded" │ │
│ │ message: "ReplicaSet "xxx" has not progressed... │ │
│ │ │ │
│ │ 可能原因: │ │
│ │ • 超过 progressDeadlineSeconds 未完成更新 │ │
│ │ • 镜像拉取失败 │ │
│ │ • 容器启动失败 │ │
│ │ • 资源不足无法调度 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
7.3 事件查看与排查
bash
# 查看 Deployment 相关事件
kubectl get events --field-selector involvedObject.name=my-app --sort-by='.lastTimestamp'
# 查看更详细的事件
kubectl describe deployment my-app
# 查看 Pod 事件
kubectl get events --field-selector involvedObject.name=my-app-pod-xxx
# 查看命名空间级别所有事件
kubectl get events -n default --sort-by='.lastTimestamp'
# 过滤特定类型事件
kubectl get events --field-selector type=Warning
kubectl get events --field-selector reason=Failed
# 查看最新事件(实时)
kubectl get events --watch
八、常见问题与排查
8.1 更新卡住
症状: Deployment 长时间处于 Progressing 状态,Pod 数量不变化。
排查步骤:
bash
# 1. 检查 Deployment 状态
kubectl get deployment my-app
kubectl describe deployment my-app
# 2. 检查 ReplicaSet 状态
kubectl get rs -l app=my-app
# 3. 检查新 ReplicaSet 的 Pod
kubectl get pods -l app=my-app,pod-template-hash=xxx --show-labels
# 4. 检查 Pod 事件
kubectl describe pod <pod-name>
# 5. 检查 Pod 日志
kubectl logs <pod-name> --previous # --previous 查看前一个容器的日志
常见原因及解决方案:
| 原因 | 诊断方法 | 解决方案 |
|---|---|---|
| 镜像拉取失败 | kubectl describe pod 查看 Failed to pull image |
配置正确的镜像仓库凭证 |
| 容器启动失败 | kubectl logs 查看错误日志 |
修复应用代码或配置 |
| 存活探针失败 | kubectl describe pod 查看探针信息 |
调整探针参数或修复应用 |
| 资源不足 | kubectl describe node 查看资源 |
扩容节点或调整资源请求 |
| 节点不可用 | kubectl get node 查看 NotReady |
修复节点或驱逐 Pod |
强制完成卡住的 Deployment:
bash
# 方法1: 增加 progressDeadlineSeconds
kubectl patch deployment my-app -p '{"spec":{"progressDeadlineSeconds":1200}}'
# 方法2: 标记为 Failed(可用于触发回滚)
kubectl annotate deployment my-app kubernetes.io/change-cause="Force complete"
# 方法3: 删除卡住的 ReplicaSet(慎用)
kubectl delete rs <stuck-replicaset-name>
# 方法4: 回滚
kubectl rollout undo deployment/my-app
8.2 Pod 启动失败
症状: Pod 处于 Pending、ImagePullBackOff、CrashLoopBackOff、Error 等状态。
排查流程:
plaintext
┌─────────────────────────────────────────────────────────────────────────────┐
│ Pod 启动失败排查流程 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ kubectl get pods -l app=my-app │
│ │
│ │ │
│ ├─→ ContainerCreating │
│ │ │ │
│ │ ├─→ 原因: 镜像拉取中 │
│ │ │ 解决: 等待或检查镜像仓库 │
│ │ │ │
│ │ ├─→ 原因: CNI 网络插件问题 │
│ │ │ 解决: 检查 CNI 配置和节点网络 │
│ │ │ │
│ │ └─→ 原因: 资源不足无法调度 │
│ │ 解决: 检查节点资源或调整资源请求 │
│ │ │
│ ├─→ ImagePullBackOff │
│ │ │ │
│ │ ├─→ 原因: 镜像不存在 │
│ │ │ 解决: 检查镜像名称和 tag │
│ │ │ │
│ │ ├─→ 原因: 镜像仓库认证失败 │
│ │ │ 解决: 配置 imagePullSecrets │
│ │ │ │
│ │ └─→ 原因: 网络问题无法访问镜像仓库 │
│ │ 解决: 检查节点网络配置 │
│ │ │
│ ├─→ CrashLoopBackOff │
│ │ │ │
│ │ ├─→ 原因: 应用启动失败 │
│ │ │ 解决: kubectl logs <pod-name> 查看日志 │
│ │ │ │
│ │ ├─→ 原因: 健康检查过于严格 │
│ │ │ 解决: 调整 liveness/readinessProbe │
│ │ │ │
│ │ └─→ 原因: 依赖服务不可用 │
│ │ 解决: 检查应用依赖配置 │
│ │ │
│ ├─→ Error │
│ │ │ │
│ │ └─→ 原因: OOMKilled、资源限制、致命错误 │
│ │ 解决: kubectl describe pod 查看事件 │
│ │ │
│ └─→ Pending │
│ │ │
│ ├─→ 原因: 调度失败(无满足条件的节点) │
│ │ 解决: 检查 affinity/taint/nodeSelector │
│ │ │
│ └─→ 原因: PVC 绑定等待 │
│ 解决: 检查 PersistentVolumeClaim 状态 │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
详细排查命令:
bash
# 查看 Pod 详细状态
kubectl describe pod <pod-name>
# 查看 Pod 日志
kubectl logs <pod-name>
kubectl logs <pod-name> --previous # 前一个容器的日志
# 进入 Pod 调试
kubectl exec -it <pod-name> -- /bin/sh
# 查看资源配额
kubectl describe resourcequota
kubectl describe limitrange
# 检查调度原因
kubectl get events --field-selector involvedObject.name=<pod-name>
8.3 回滚失败
症状: 回滚命令执行后没有效果或报错。
排查步骤:
bash
# 1. 确认回滚命令执行结果
kubectl rollout undo deployment/my-app --to-revision=2
kubectl rollout status deployment/my-app
# 2. 查看回滚历史
kubectl rollout history deployment/my-app
# 3. 检查 ReplicaSet 状态
kubectl get rs -l app=my-app -o wide
# 4. 检查新 Pod 状态
kubectl get pods -l app=my-app
常见回滚失败原因:
| 原因 | 现象 | 解决方案 |
|---|---|---|
| 指定版本不存在 | error: unable to find revision 2 |
使用 kubectl rollout history 查看可用版本 |
| Deployment 暂停 | 回滚不生效 | kubectl rollout resume deployment/my-app |
| ReplicaSet 被删除 | 版本历史丢失 | 无法回滚,需手动重建 |
| 权限不足 | 权限错误 | 检查 RBAC 配置 |
手动回滚方法:
bash
# 如果自动回滚失败,可以手动执行:
# 1. 查看当前配置
kubectl get deployment my-app -o yaml > current.yaml
# 2. 找到历史版本的 ReplicaSet
kubectl get rs -l app=my-app
# 3. 从历史 ReplicaSet 获取配置
kubectl get rs <historical-replicaset> -o yaml > historical.yaml
# 4. 修改名称后应用
sed -i 's/name: my-app-xxx/name: my-app-rollback/' historical.yaml
kubectl apply -f historical.yaml
# 5. 修改 Deployment 指向新 ReplicaSet
kubectl scale deployment my-app --replicas=0
kubectl edit deployment my-app
# 修改 selector 中的 pod-template-hash 为新 ReplicaSet 的 hash
kubectl scale deployment my-app --replicas=3
8.4 其他常见问题
8.4.1 Selector 冲突
bash
# 错误: Deployment 与已有 ReplicaSet 冲突
# Error: Failed to create deployment: admission webhook "validationwebhook..." denied
解决方案: 使用唯一的 selector 标签
yaml
# 错误示例
spec:
selector:
matchLabels:
app: my-app # 可能与现有的 Deployment 冲突
# 正确示例
spec:
selector:
matchLabels:
app: my-app
version: v1 # 添加额外标签确保唯一
8.4.2 Pod 无法调度
bash
# 查看调度失败原因
kubectl describe pod <pod-name> | grep -A 5 "Events:"
# 常见原因
# - 资源不足: Insufficient memory/cpu
# - 污点不匹配: node(s) had taints that the pod didn't tolerate
# - 亲和性冲突: node(s) didn't match pod affinity/anti-affinity rules
8.4.3 版本历史丢失
bash
# 检查 revisionHistoryLimit 配置
kubectl get deployment my-app -o jsonpath='{.spec.revisionHistoryLimit}'
# 如果为 0,则不会保留历史版本
# 解决方案:设置合适的值
kubectl patch deployment my-app -p '{"spec":{"revisionHistoryLimit":10}}'
九、最佳实践
9.1 资源配置最佳实践
yaml
spec:
template:
spec:
containers:
- name: app
# ✅ 必须设置资源请求(调度依据)
resources:
requests:
memory: "128Mi"
cpu: "100m"
# ✅ 建议设置资源限制(防止异常)
limits:
memory: "512Mi"
cpu: "500m"
# ✅ 建议添加健康检查
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
# ✅ 生产环境建议使用 startupProbe
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
9.2 更新策略最佳实践
yaml
spec:
# ✅ 生产环境推荐使用滚动更新
strategy:
type: RollingUpdate
rollingUpdate:
# 保守策略:确保服务稳定
maxSurge: 1 # 最多超出 1 个 Pod
maxUnavailable: 0 # 保持所有 Pod 可用
# ✅ 设置合理的进度超时
progressDeadlineSeconds: 600 # 10 分钟内必须完成
# ✅ 设置就绪观察时间
minReadySeconds: 10 # Pod 稳定运行 10 秒后才认为就绪
# ✅ 保留历史版本用于回滚
revisionHistoryLimit: 10
9.3 高可用部署策略
yaml
spec:
# ✅ 生产环境至少 2 个副本
replicas: 3
# ✅ 使用 Pod 反亲和分散部署
template:
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: my-app
topologyKey: kubernetes.io/hostname
# ✅ 添加 Pod Disruption Budget
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: my-app-pdb
spec:
minAvailable: 2 # 或使用 maxUnavailable: 1
selector:
matchLabels:
app: my-app
9.4 版本管理最佳实践
bash
# ✅ 使用 labels 标记版本
kubectl label deployment my-app version=v1.2.3
# ✅ 使用 annotations 记录变更原因
kubectl annotate deployment my-app \
kubernetes.io/change-cause="Update base image to nginx:1.25-alpine"
# ✅ 避免频繁小版本更新,攒批更新减少滚动次数
# ✅ 发布前在 staging 环境充分测试
# ✅ 使用 pause/resume 进行批量修改
kubectl rollout pause deployment/my-app
# 执行多次配置变更
kubectl rollout resume deployment/my-app
9.5 安全最佳实践
yaml
spec:
template:
spec:
# ✅ 使用非 root 用户运行
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
containers:
- name: app
# ✅ 限制容器能力
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp
mountPath: /tmp
# ✅ 使用只读根文件系统 + tmp 目录
volumes:
- name: tmp
emptyDir: {}
# ✅ 分离应用和日志存储
- name: app-storage
emptyDir:
sizeLimit: "100Mi"
9.6 监控与日志
bash
# ✅ 部署时添加监控标签
kubectl label deployment my-app \
app=my-app \
environment=production \
team=backend
# ✅ 推荐配置
# - 使用 Prometheus + Grafana 监控 Deployment 状态
# - 配置 Pod 级别的 metrics 采集
# - 收集日志到集中式日志系统(ELK/Loki)
# - 配置告警规则监控 Deployment 状态异常
9.7 快速恢复脚本
bash
#!/bin/bash
# deployment-utils.sh
DEPLOYMENT=$1
NAMESPACE=${2:-default}
# 回滚 Deployment
rollback_deployment() {
echo "Rolling back $DEPLOYMENT in $NAMESPACE..."
kubectl rollout undo deployment/$DEPLOYMENT -n $NAMESPACE
kubectl rollout status deployment/$DEPLOYMENT -n $NAMESPACE
}
# 查看部署状态
status_deployment() {
echo "=== Deployment Status ==="
kubectl get deployment $DEPLOYMENT -n $NAMESPACE
echo -e "\n=== ReplicaSet Status ==="
kubectl get rs -l app=$DEPLOYMENT -n $NAMESPACE
echo -e "\n=== Pod Status ==="
kubectl get pods -l app=$DEPLOYMENT -n $NAMESPACE
echo -e "\n=== Recent Events ==="
kubectl get events -n $NAMESPACE --field-selector involvedObject.name=$DEPLOYMENT --sort-by='.lastTimestamp'
}
# 扩容 Deployment
scale_deployment() {
REPLICAS=$3
echo "Scaling $DEPLOYMENT to $REPLICAS replicas..."
kubectl scale deployment $DEPLOYMENT --replicas=$REPLICAS -n $NAMESPACE
}
# 强制重启
restart_deployment() {
echo "Force restarting $DEPLOYMENT..."
kubectl rollout restart deployment/$DEPLOYMENT -n $NAMESPACE
kubectl rollout status deployment/$DEPLOYMENT -n $NAMESPACE
}
case "$1" in
status)
status_deployment
;;
rollback)
rollback_deployment
;;
scale)
scale_deployment "$@"
;;
restart)
restart_deployment
;;
*)
echo "Usage: $0 {status|rollback|scale|restart} <deployment> [namespace] [replicas]"
;;
esac
十、总结
Deployment 是 Kubernetes 中最核心的工作负载资源之一,它通过声明式的配置实现了应用的自动化部署、更新和扩缩容。掌握 Deployment 的原理和最佳实践,对于构建可靠的云原生应用至关重要。
核心要点回顾:
- 声明式管理:通过 YAML 声明期望状态,控制器自动调谐
- 滚动更新:支持零宕机部署,可配置 maxSurge/maxUnavailable
- 版本回滚:自动保存历史版本,支持快速回退
- 弹性伸缩:支持手动扩缩容和 HPA/VPA 自动扩缩容
- 健康检查:通过 liveness/readiness/startupProbe 保证应用质量
- 高级策略:支持金丝雀发布、蓝绿部署等复杂场景
推荐实践:
- 生产环境使用
replicas ≥ 2+ Pod 反亲和 - 保守的滚动更新策略:
maxSurge=1, maxUnavailable=0 - 始终配置资源请求和健康检查
- 保留足够的
revisionHistoryLimit用于回滚 - 配合 PDB(PodDisruptionBudget) 保证高可用
更多推荐
所有评论(0)