Kubernetes 系列【11】控制器:Deployment(无状态部署控制器)
文章目录
- 1. 概述
- 2. 无状态应用
- 3. 工作原理
- 3.1 首次创建
- 3.2 滚动更新发布
- 3.3 故障自愈流程
- 3.4 水平扩缩容
- 3.5 版本回滚
- 4. 运行状态
- 4.1 发布中 Progressing
- 4.2 发布完成 Complete
- 4.3 发布失败 Failed
- 5. 资源清单编写规范
- 5.1 通用顶层基础规范
- 5.2 更新策略
- 5.2.1 Recreate 重建更新
- 5.2.2 RollingUpdate 滚动更新(默认)
- 5.3 扩展配置字段
- 5.4 历史版本清理策略
1. 概述
Deployment是K8s 最常用的控制器,专门管理无状态应用,比如,Nginx、SpringBoot后端、网关等。
Deployment不直接管理Pod,而是创建、管理多个ReplicaSet,由ReplicaSet真正管控Pod副本。ReplicaSet提供副本维持、标签筛选管控、缩容清理等能力。
核心能力:
- 故障自愈:持续比对
replicas期望副本数,Pod异常丢失时自动新建补齐,无需人工操作。 - 水平扩缩容:修改
spec.replicas手动调整实例,搭配HPA可基于指标自动弹性扩缩。 - 滚动更新:更新配置生成新
ReplicaSet,先启动新Pod就绪,再逐步销毁旧Pod,服务不中断。 - 版本回滚:自动留存历史
ReplicaSet,发布故障时一键切回稳定版本快速恢复业务。 - 多版本历史留存:持久保存各发布版本
ReplicaSet,用于发布记录追溯、故障复盘。布对应的ReplicaSet,支持查看历次发布配置、Pod版本,用于发布记录追溯、故障复盘。
✅ 适合:无状态应用,业务无本地持久化数据,数据存外部Redis/MySQL
❌ 不适合:有状态业务,MySQL、Redis集群、ZooKeeper等,这类业务使用StatefulSet
注意:请勿手动管理
Deployment所属的ReplicaSet。如果你的业务场景不在本文覆盖范围内,可以前往Kubernetes官方代码仓库提交issue。
2. 无状态应用
无状态应用(Stateless Application)指服务实例本身不保存用户会话、业务上下文与持久业务数据,单次请求不依赖上一次请求留存的信息,所有状态数据统一交由数据库、缓存等外部组件存储,各实例完全对等、可任意替换的应用程序。
关键特征:
- 无本地存储依赖:不在容器/服务器本地磁盘存业务数据、用户会话、缓存;本地磁盘仅放程序二进制、日志(日志可收集到外部)。
- 请求独立无上下文绑定:用户第一次请求到实例 A ,第二次调度到实例 B ,结果完全一致,不需要粘滞会话。
- 实例完全可替换:任意销毁、新增、重启实例,业务不受影响;扩容缩容简单。
- 水平扩展友好:直接多副本部署,负载均衡分发流量。
- 故障自愈成本低:实例挂了,调度器直接新建
Pod顶替,无需同步状态。
和有状态应用对比:
| 维度 | 无状态应用 | 有状态应用(StatefulSet) |
|---|---|---|
| 数据存储 | 数据外置(DB/Redis) | 本地持久卷、实例专属存储 |
| 实例标识 | 无固定身份,随机Pod名 | 稳定网络标识、有序域名 |
| 扩缩容 | 随时增减,无序 | 有序创建/删除,有启动顺序 |
| 典型组件 | Nginx、SpringBoot接口、微服务网关 | MySQL、Redis集群、Zookeeper、Elasticsearch |
无状态典型例子:
- 后端
API服务(SpringBoot、Node.js接口) - 静态资源服务器
Nginx - 网关、鉴权服务、定时任务
worker - 图片处理、文件转换临时服务
不属于无状态(有状态)典型例子:
- 单机
MySQL、Redis本地持久化集群 - 分布式注册中心
ZooKeeper、etcd - 需要本地持久卷存数据的中间件
云原生K8s无状态应用最佳实践:
- 配置、密钥外置:使用
ConfigMap、Secret,不打包进镜像 - 持久数据全部外置:会话存
Redis,业务数据存数据库 - 日志输出:由
EFK/Loki统一采集,不落地本地盘 - 不使用本地缓存做持久会话
- 使用
Deployment部署,多副本,随时滚动更新、重启 - 健康检查只校验服务端口/接口,不依赖本地数据
3. 工作原理
极简流程总结:
- 初次创建:
Deployment→ 生成ReplicaSet-v1→ReplicaSet创建指定数量Pod,维持副本稳定。 - 滚动更新:修改
Pod模板 → 新建ReplicaSet-v2→ 分批启动新Pod、销毁旧Pod,零停机切换。 - 故障自愈:
Pod异常消失 → 对应ReplicaSet自动新建Pod,补齐replicas数量。 - 水平扩缩容:调整
spec.replicas→ 活跃ReplicaSet增减Pod,实现弹性扩容缩容。 - 版本回滚:指定历史版本 → 切换至旧
ReplicaSet→ 逐步下线新版本Pod,恢复业务。
3.1 首次创建
- 用户提交
DeploymentYAML,声明期望状态:replicas副本数、Pod模板、更新策略等; APIServer存储资源对象至etcd,Deployment控制器持续监听资源变更;Deployment控制器检测到无对应ReplicaSet,自动创建第一个副本集ReplicaSet-v1;ReplicaSet-v1执行调谐循环,根据标签匹配创建对应数量Pod;- 持续循环校验:
ReplicaSet保证Pod数量等于配置副本数,完成初始部署。
3.2 滚动更新发布
- 修改
Deployment内Pod模板(镜像、环境变量、资源限制等)并提交; Deployment控制器感知配置变更,生成全新副本集ReplicaSet-v2;- 控制器按更新策略(
maxSurge/maxUnavailable)执行分步调度:- 先扩容新版本
ReplicaSet-v2,启动新Pod,等待就绪探针就绪; - 逐步缩容旧版本
ReplicaSet-v1,删除旧Pod;
- 先扩容新版本
- 交替完成新旧实例切换,全过程新旧
Pod并行,业务不中断; - 更新完成后保留历史
ReplicaSet-v1,用于后续版本回滚。
3.3 故障自愈流程
Node节点故障、Pod OOM、Pod被驱逐,导致运行Pod数量少于replicas;- 对应
ReplicaSet实时比对期望副本数与实际Pod数量,发现差值; ReplicaSet自动新建同规格Pod,补齐至目标副本数;Deployment无需干预,由底层ReplicaSet完成自愈动作。
3.4 水平扩缩容
- 修改
Deployment的spec.replicas数值; Deployment将副本数同步给所有关联ReplicaSet;- 当前活跃版本的
ReplicaSet根据差值新增/删除Pod,完成扩容/缩容; - 搭配
HPA时可自动触发该流程,基于监控指标动态调整副本。
3.5 版本回滚
- 执行回滚命令,指定历史稳定版本;
Deployment控制器切换活跃副本集为历史ReplicaSet-v1;- 逐步缩容新版本
ReplicaSet-v2,扩容旧版本ReplicaSet-v1; - 完成新旧
Pod切换,业务快速恢复至发布前状态。
HPA全称Horizontal Pod Autoscaler,中文:Pod水平自动扩缩控制器,它会根据指定指标,自动管理所有实现了scale子资源的资源对象的副本数量。是扩缩控制器,只负责自动修改副本数,不运行任何业务容器、不产生Pod,因此不属于工作负载。
4. 运行状态
Deployment发布生命周期分为三种核心状态:
- 发布中
Progressing - 发布完成
Complete - 发布停滞
Failed
4.1 发布中 Progressing
触发场景(任意一种即进入该状态):
- 创建全新
ReplicaSet(首次部署/镜像更新) - 扩容当前最新
ReplicaSet - 缩容历史旧
ReplicaSet - 新
Pod就绪,且稳定运行满足minReadySeconds
控制器在status.conditions写入状态标识:type: Progressing, status: True
4.2 发布完成 Complete
全部条件同时满足才判定发布完成:
- 所有
Pod已更新至最新Pod模板 - 全部副本标记为可用
Available - 集群无旧版本
Pod运行
状态标识:Progressing: True,reason: NewReplicaSetAvailable,该状态会持续保留,直到下一次更新触发。
4.3 发布失败 Failed
发布超时无法完成,进入停滞失败状态。
常见故障诱因:镜像拉取失败、就绪探针故障、资源配额不足、权限缺失、容器参数异常、镜像名称错误。
超时控制:
spec.progressDeadlineSeconds发布超时阈值,默认600秒(10分钟);- 超时后:
Progressing: False,reason: ProgressDeadlineExceeded。
关键说明:
Kubernetes仅标记失败状态,不会自动回滚,需上层CI/CD工具监听状态实现自动回滚;Deployment处于paused: true暂停状态时,不计算发布超时;- 临时故障修复后,控制器自动继续发布,状态恢复正常;
- 命令执行失败返回非
0退出码1。
发布失败不限制操作,支持:扩缩容、版本回滚、暂停发布、修改Pod模板。
5. 资源清单编写规范
Nginx Deployment模板(覆盖全部规约字段)示例:
# Deployment API 稳定版本apiVersion:apps/v1# 资源类型固定Deploymentkind:Deploymentmetadata:name:nginx-deploymentlabels:app:nginxspec:# 期望运行副本数,可选,默认1replicas:3# 标签选择器,创建后不可修改,必须匹配template标签selector:matchLabels:app:nginx# Pod模板,spec内必填项template:metadata:labels:app:nginx# 与selector标签严格一致spec:# 重启策略仅允许AlwaysrestartPolicy:Alwayscontainers:-name:nginximage:nginx:1.24-alpineports:-containerPort:80# 滚动更新策略配置strategy:type:RollingUpdaterollingUpdate:maxUnavailable:1maxSurge:1# Pod就绪后稳定5秒才算可用minReadySeconds:5# 发布超时10分钟progressDeadlineSeconds:600# 保留5个历史版本用于回滚revisionHistoryLimit:5# 不暂停发布,修改模板自动触发更新paused:false5.1 通用顶层基础规范
所有K8s资源通用三要素:apiVersion、kind、metadata。
核心配置段spec不可省略:
spec内两个强制字段:spec.templatePod模板、spec.selector标签筛选器;Pod模板语法与独立Pod完全一致,无需填写apiVersion/kind;Pod模板强制配置标签、重启策略;restartPolicy仅允许Always(默认);spec.replicas可选,期望副本数,默认1;selector约束:必须与Pod模板标签完全匹配;创建后不可修改;禁止多控制器共用同一selector,避免争抢Pod。
5.2 更新策略
spec.strategy.type二选一:Recreate/RollingUpdate(默认滚动更新)
5.2.1 Recreate 重建更新
逻辑:先销毁全部旧Pod,再创建新版本Pod;
缺点:发布期间服务完全中断;
补充:手动删除Pod时,ReplicaSet会立刻重建,不会等待旧Pod终止;若需要严格限制最大实例数,选用StatefulSet。
5.2.2 RollingUpdate 滚动更新(默认)
两个核心参数控制发布节奏:
maxUnavailable:更新期间最大不可用副本;支持数值/百分比,百分比向下取整,默认25%;maxSurge:发布峰值可额外扩容的副本;支持数值/百分比,百分比向上取整,默认25%。
5.3 扩展配置字段
扩展配置字段说明:
progressDeadlineSeconds:发布超时秒数,数值必须大于minReadySeconds;minReadySeconds:Pod就绪后稳定运行时长,达标才判定可用,默认0;terminatingReplicas(v1.35 Beta,默认开启)- 开启特性门控
DeploymentReplicaSetTerminatingReplicas; - 缩容删除
Pod进入Terminating销毁阶段,短期总Pod数会临时超过replicas; - 在
Deploymentstatus中查看正在销毁的实例数量。
- 开启特性门控
paused:布尔值,true=暂停发布,修改Pod模板不会触发滚动更新;false=正常发布。
5.4 历史版本清理策略
spec.revisionHistoryLimit:控制保留可回滚的旧 ReplicaSet 数量,超出自动 GC 回收,默认10。
- 设为
0:全部清理历史副本集,无法执行回滚; - 长期卡住的发布,历史
ReplicaSet数量可能临时超出该阈值。
查看历史版本命令:
kubectl rollouthistorydeployment/nginx-deployment# 回滚到指定版本kubectl rollout undo deployment/nginx-deployment --to-revision=2