使用Deployment运行无状态应用
使用Deployment运行无状态应用
文章目录
- 使用Deployment运行无状态应用
- @[toc]
- 一、工作负载资源与控制器
- 二、ReplicationController、ReplicaSet和Deployment
- 1. ReplicationController(已淘汰)
- 2. ReplicaSet(ReplicationController 的增强版)
- 3. Deployment(管理 ReplicaSet 的高级抽象)
- 三、Deployment的应用场景
- 1.无状态服务的标准化部署
- 2.持续交付与滚动更新
- 3.弹性伸缩与负载均衡
- 4.多版本发布策略
- 5.临时任务与测试环境管理
- 四、Deployment的基本用法
- 五、创建Deployment
- 1.编写Deployment配置文件
- 2.基于配置文件创建Deployment
- 3.测试Deployment及其部署的应用程序
- 六、测试Deployment的自我修复功能
- 七、更新Deployment
- 八、回滚Deployment
- 九、暂停、恢复Deployment的更新
- 十、扩缩容Deployment
文章目录
- 使用Deployment运行无状态应用
- @[toc]
- 一、工作负载资源与控制器
- 二、ReplicationController、ReplicaSet和Deployment
- 1. ReplicationController(已淘汰)
- 2. ReplicaSet(ReplicationController 的增强版)
- 3. Deployment(管理 ReplicaSet 的高级抽象)
- 三、Deployment的应用场景
- 1.无状态服务的标准化部署
- 2.持续交付与滚动更新
- 3.弹性伸缩与负载均衡
- 4.多版本发布策略
- 5.临时任务与测试环境管理
- 四、Deployment的基本用法
- 五、创建Deployment
- 1.编写Deployment配置文件
- 2.基于配置文件创建Deployment
- 3.测试Deployment及其部署的应用程序
- 六、测试Deployment的自我修复功能
- 七、更新Deployment
- 八、回滚Deployment
- 九、暂停、恢复Deployment的更新
- 十、扩缩容Deployment
Pod本身并不能自愈,一个Pod所在的节点发生故障,Pod将被删除;节点资源不够或需要进行维护时,Pod也会从节点上被驱逐,从而被删除。为此,Kubernetes引入控制器来管理Pod副本。管理员很少会直接创建一个Pod,大多数情况下会通过控制器完成对一组Pod的创建、调度及全生命周期的自动管控任务。Deployment时常用的控制器,适合用来管理集群中的无状态应用程序。
一、工作负载资源与控制器
Pod只能管理自身,直接创建的Pod是一种自主式Pod,一旦删除就不会自动重建,没有自我修复功能。Pod具有确定的生命周期,如果运行Pod的节点发生致命错误,则该节点上的所有Pod的状态都会失效,即使该节点后来恢复正常运行,也需要管理员重新创建新的Pod以恢复应用程序。当集群中有大量Pod时,或者同一个Pod有多个副本时,人工监控和管理每个Pod会变得极其困难。为此,Kubernetes在Pod的基础之上,引入工作负载资源来帮助用户统一管理一组Pod。
工作负载资源自动实时监控和管理指派给它的Pod,并确保处于运行状态的Pod的数量是正确的,Pod的状态与用户所期望的保持一致,如果出现异常,则会自动修复。
考虑到不同的应用程序具有不同的特征,为满足不同业务场景需求,Kubernetes提供多种类型的内置工作负载资源
资源类型 | 功能 |
---|---|
Deployment | 管理集群中的无状态应用程序,如Web服务 |
StatefulSet | 管理集群中的有状态应用程序,如MongoDB |
DaemonSet | 管理集群中的守护进程集,确保所有节点运行同一个Pod,如日志收集组件 |
Job | 运行一次性任务 |
CronJob | 运行周期性任务 |
除了Kubernetes内置的工作负载资源类型,管理员还可以通过使用定制资源定义,添加第三方工作负载资源。
这些工作负载资源具体是通过配置控制器来实现的。控制器用于工作负载资源的部署和管理,在更高层次上部署和管理Pod,因此又称为Pod控制器。Kubernetes的许多重要特性都是依靠控制器来实现的。
控制器功能
- 管理Pod对象。
- 使用标签与Pod关联。
- 实现Pod的运维。
二、ReplicationController、ReplicaSet和Deployment
在 Kubernetes 中,ReplicationController、ReplicaSet 和 Deployment 是用于管理 Pod 副本的控制器,它们通过不同层级的抽象实现应用的高可用性和更新管理。以下是三者的核心关系和区别:
1. ReplicationController(已淘汰)
- 核心作用:确保指定数量的 Pod 副本始终运行(如保证 3 个副本)。
- 工作原理
- 持续监控 Pod 数量,若实际副本数少于期望值(如 Pod 崩溃),自动创建新 Pod。
- 仅支持简单的等值标签选择器(例如
app=nginx
),无法匹配复杂标签规则。
- 缺点
- 更新机制笨拙:直接替换所有旧 Pod,导致服务中断。
- 无法实现滚动更新、版本回滚等高级操作。
- 现状:已被 ReplicaSet 取代,仅用于旧版本兼容。
2. ReplicaSet(ReplicationController 的增强版)
- 核心改进
- 支持集合标签选择器(
matchExpressions
),例如app in (nginx, web)
或env notin (prod)
。 - 可配合 Deployment 实现滚动更新,但仍需手动管理更新过程。
- 支持集合标签选择器(
- 典型用途
- 作为 Deployment 的底层实现,一般不直接操作。
- 直接使用时适用于需要精细控制 Pod 标签的场景。
- 局限性
- 无法自动管理更新历史,需手动维护新旧 ReplicaSet。
- 缺少版本回滚等高级功能。
3. Deployment(管理 ReplicaSet 的高级抽象)
- 核心功能
- 通过声明式配置(如定义副本数、镜像版本)管理应用。
- 滚动更新:逐步替换旧 Pod(例如先启动新 Pod,再终止旧 Pod),确保服务不中断。
- 版本回滚:保留历史 ReplicaSet,随时回退到任意旧版本。
- 自动扩缩容:结合 Horizontal Pod Autoscaler(HPA)动态调整副本数。
- 工作原理
- 每次更新(如修改镜像版本)会创建新的 ReplicaSet,并逐步迁移 Pod。
- 旧 ReplicaSet 保留以便快速回滚。
- 典型用途:管理无状态应用(如 Web 服务、API 服务),是 Kubernetes 中最常用的工作负载资源。
三者的层级关系
Deployment (管理者)
│
└─ ReplicaSet 1 (管理 v1 版本的 Pod)└─ Pod 1, Pod 2, Pod 3
│
└─ ReplicaSet 2 (管理 v2 版本的 Pod)└─ Pod 4, Pod 5, Pod 6
- Deployment 控制多个 ReplicaSet(每个对应一个应用版本)。
- ReplicaSet 控制多个 Pod(确保副本数符合期望)。
关键区别总结
特性 | ReplicationController | ReplicaSet | Deployment |
---|---|---|---|
标签选择器 | 等值匹配(= ) | 集合匹配(In/NotIn ) | 继承 ReplicaSet 的选择器 |
更新策略 | 全量替换 | 手动滚动更新 | 自动滚动更新 |
版本回滚 | 不支持 | 不支持 | 支持 |
使用场景 | 旧系统兼容 | 直接控制 Pod 标签 | 无状态应用管理 |
推荐程度 | 已淘汰 | 间接使用 | 首选方案 |
- ReplicationController 是过时的副本控制器,ReplicaSet 是其升级版,而 Deployment 通过封装 ReplicaSet 提供了声明式更新、版本控制等高级功能,是管理无状态应用的终极工具。
直接使用 Deployment 即可,无需手动操作 ReplicaSet 或 ReplicationController。
三、Deployment的应用场景
在 Kubernetes 中,Deployment 是管理无状态应用的核心工作负载资源,其设计目标是通过声明式配置实现应用的自动化部署、更新和扩展。以下是 Deployment 的典型应用场景及技术细节,结合多个来源的搜索结果整理:
1.无状态服务的标准化部署
核心场景:
Deployment 适用于运行无状态应用,这类应用的特点是每个实例(Pod)功能相同、无持久化数据依赖,且实例可随时被替换或重建。
典型用例:
- Web 服务器:如 Nginx、Apache 等,通过 Deployment 快速部署多个副本以应对高并发请求。
- API 服务:微服务架构中的后端服务(如 RESTful API),通过副本扩展提升吞吐量。
- 数据处理管道:如批处理任务的前置服务,利用 Deployment 动态调整资源。
技术优势:
- 副本一致性:通过 ReplicaSet 确保指定数量的 Pod 始终运行。
- 轻量级替换:Pod 故障时自动重建,无需手动干预。
2.持续交付与滚动更新
核心场景:
在持续集成/持续交付(CI/CD)流程中,Deployment 支持零停机更新和版本回滚,适用于频繁迭代的敏捷开发环境。
典型用例:
- 镜像版本升级:例如从
nginx:1.14
升级到nginx:1.20
,Deployment 逐步替换旧 Pod,确保服务不中断。 - 配置热更新:修改环境变量或资源限制后,自动触发滚动更新。
技术优势:
- 滚动更新策略:分批次创建新 Pod 并终止旧 Pod,默认更新速率为 25% 的 Pod 同时替换。
- 版本历史记录:保留旧 ReplicaSet 的配置,支持快速回退到任意历史版本(通过
kubectl rollout undo
)。
3.弹性伸缩与负载均衡
核心场景:
结合 Horizontal Pod Autoscaler (HPA),Deployment 可根据 CPU、内存等指标自动扩缩容,应对流量波动。
典型用例:
- 流量高峰应对:电商大促期间自动扩展 Web 服务副本数。
- 资源优化:低峰期减少副本数量以节省计算资源。
技术实现:
- 动态调整副本数:通过
kubectl scale
或 YAML 定义replicas
字段手动调整。 - HPA 集成:定义自动扩缩规则(如 CPU 使用率超过 80% 时扩容)。
4.多版本发布策略
核心场景:
Deployment 支持蓝绿部署和金丝雀发布,降低新版本上线风险。
典型用例:
- 蓝绿部署:创建两个独立的 Deployment(旧版本和新版本),通过 Service 切换流量。
- 金丝雀发布:逐步将少量流量导向新版本 Pod,验证稳定性后再全量切换。
技术实现:
- 多 Deployment 共存:通过标签选择器区分不同版本的应用。
- 流量权重控制:结合 Istio 或 Kubernetes Service 的流量分配策略实现精细化控制。
5.临时任务与测试环境管理
核心场景:
快速创建和销毁临时环境,用于测试、预发布或实验性功能验证。
典型用例:
- 开发测试环境:为每个开发分支创建独立的 Deployment,模拟生产环境。
- A/B 测试:同时运行不同版本的 Deployment,收集用户行为数据。
技术优势:
- 快速部署:通过 YAML 模板一键创建完整应用栈。
- 环境隔离:利用命名空间(Namespace)隔离不同环境的资源。
总结与选型建议
Deployment 是 Kubernetes 中无状态应用管理的黄金标准,其核心价值在于通过声明式配置实现自动化运维。
适用条件:
- 应用无状态(无持久化数据依赖)
- 需要高可用性、弹性伸缩或频繁更新
- 需支持版本回退或多版本发布
不适用场景:
- 有状态应用(如数据库):需改用 StatefulSet。
- 节点级守护进程(如日志收集):需使用 DaemonSet。
通过合理选择 Deployment 的配置策略(如滚动更新速率、HPA 规则),可以显著提升应用的可靠性和运维效率。
四、Deployment的基本用法
直接使用命令,这种方式一般只用于测试,实际应用中主要使用配置文件来创建Deployment。
kubectl create deployment 名称 --image=镜像 [选项]
创建一个YAML格式的Deployment资源定义文件。
使用kubectl create或kubectl apply命令基于该文件创建资源。
kubectl create deployment webserver --image=nginx --dry-run=client -o yaml
可以使用“干跑”(dry-run)模式生成一个Deployment的YAML格式的原始配置,然后在此配置上进行定制修改参数
五、创建Deployment
nginx是一个高性能的HTTP和反向代理Web服务器,属于无状态应用程序。
1.编写Deployment配置文件
与其他Kubernetes对象的定义一样,Deployment配置文件中需要apiVersion、kind、metadata和spec字段。spec字段中只有template和selector这两个子字段是必需的。template字段定义Pod模板,与Pod定义的语法规则完全相同,由于它是嵌套的,其中不需要再定义apiVersion或kind字段。selector字段定义Deployment资源如何查找要管理的Pod,可以选择在Pod模板中定义的标签,还可以定义更复杂的选择规则,前提是Pod模板本身能够满足所定义的规则。注意,不要直接创建与此规则匹配的Pod。
spec字段中常用的可选子字段有replicas和strategy。replicas指定期望的Pod副本数,默认值是1。strategy指定新旧Pod替换的策略。
[root@master ~]# vim nginx-deploy.yaml
[root@master ~]# cat nginx-deploy.yaml
apiVersion: apps/v1 # 版本号
kind: Deployment # 类型为Deployment
metadata: # 元数据name: nginx-deploy labels: # 标签app: nginx
spec: # 详细信息replicas: 3 # 副本数量strategy: # 策略type: RollingUpdate # 滚动更新策略rollingUpdate: # 滚动更新设置maxSurge: 25% # 更新过程中允许超出期望Pod副本数的Pod数量,用百分比或整数表示maxUnavailable: 25% # 更新过程中不可用的Pod数量上限,用百分比或整数表示selector: # 选择器,指定该控制器管理哪些PodmatchLabels: # 匹配规则app: nginxtemplate: # 定义模板,当副本数量不足时会根据模板定义创建Pod副本metadata:labels:app: nginx # Pod的标签spec:containers: # 容器列表(本例仅定义一个容器)- name: nginx # 容器的名称image: nginx:1.14.2 # 容器所用的镜像ports:- containerPort: 80 # 容器需要暴露的端口
本例创建名为nginx-deploy(由.metadata.name字段指定)的Deployment,需要运行3个Pod副本(由.spec.replicas字段定义)。
2.基于配置文件创建Deployment
创建Kubernetes对象时可以使用kubectl create命令,也可以使用kubectl apply命令。使用kubectl create命令创建新的资源时,如果再次运行该命令则会出现错误,因为资源名称在名称空间中应该是唯一的。kubectl apply命令将配置文件应用于资源,如果资源不存在,那么它将被创建,否则该命令将配置文件应用于现有资源。如果基于单个文件创建资源,两者基本相同。但是,kubectl apply命令还可以用于基于多个文件同时创建和修复资源。
本例使用kubectl apply命令创建Deployment。
[root@master ~]# kubectl apply -f nginx-deploy.yaml
deployment.apps/nginx-deploy created
结果显示Deployment已成功创建,应用程序成功上线。
3.测试Deployment及其部署的应用程序
(1)执行以下命令检查该Deployment的状态。
[root@master ~]# kubectl get deployments -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deploy 3/3 3 3 93s nginx nginx:1.14.2 app=nginx
这里使用-o wide选项以输出额外的信息。Deployment各字段的说明如下:
- NAME:集群中Deployment的名称。
- READY:应用程序的可用副本数。显示模式是“可用副本数/期望副本数”。期望副本数由.spec.replicas字段设置。虽然Deployment已成功创建,但是部署Pod副本有一个过程,刚开始时还没有一个成功部署的副本。
- UP-TO-DATE:为达期望状态已经更新的副本数。
- AVAILABLE:可供用户使用的应用程序副本数。
- AGE:应用程序运行的时间。
- CONTAINERS:应用程序运行的容器。
- IMAGES:容器所用的镜像。
- SELECTOR:Deployment的选择规则。
(2)执行以下命令检查该Deployment的当前部署状态,也就是上线状态。
[root@master ~]# kubectl rollout status deployment/nginx-deploy
deployment "nginx-deploy" successfully rolled out
结果表明应用程序已成功部署。
(3)再次检查该Deployment的状态。
[root@master ~]# kubectl get deployment -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
nginx-deploy 3/3 3 3 12m nginx nginx:1.14.2 app=nginx
结果表明已经创建3个副本,并且所有副本都是最新且可用的。
(4)执行以下命令查看Deployment创建的ReplicaSet。
[root@master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-86dcfdf4c6 3 3 3 14m
Deployment控制器并不直接管理Pod,而是通过管理ReplicaSet来间接管理Pod。
此处显示的ReplicaSet各字段的说明如下:
- NAME:ReplicaSet的名称。
- DESIRED:显示期望的应用程序副本数,即在创建Deployment时所定义的值。
- CURRENT:显示当前运行状态中的应用程序副本数。
- READY:显示有多少个应用程序副本可以为用户提供服务。
- AGE:显示应用程序已经运行的时间。
本例创建3个ReplicaSet,ReplicaSet的名称是自动生成的,格式为“Deployment名称-哈希值”。其中的哈希(Hash)值是根据Pod模板标签(pod-template-hash)生成的,该标签会被添加到Deployment所创建的每个ReplicaSet中,可确保Deployment的ReplicaSet不重叠。
(5)查看Deployment创建的Pod。
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-86dcfdf4c6-4729k 1/1 Running 0 21m 10.244.166.154 node1 <none> <none>
nginx-deploy-86dcfdf4c6-66dcp 1/1 Running 0 21m 10.244.166.155 node1 <none> <none>
nginx-deploy-86dcfdf4c6-mxvwx 1/1 Running 0 21m 10.244.104.8 node2 <none> <none>
可以发现,本例创建了3个Pod,分别在node01和node02两个节点上运行。Pod名称也是自动生成的,由ReplicaSet名称和自动产生的哈希值组成。
(6)访问nginx应用程序进行实际测试。
每个Pod都分配了IP地址,可以通过其发布的端口来访问。本例部署的是HTTP服务,发布的是默认的端口80,可以使用每个Pod的IP地址来访问。
[root@master ~]# curl http://10.244.166.154
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>body {width: 35em;margin: 0 auto;font-family: Tahoma, Verdana, Arial, sans-serif;}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p><p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p><p><em>Thank you for using nginx.</em></p>
</body>
</html>
还可以根据需要执行以下命令查看该Deployment的详细信息。
[root@master ~]# kubectl describe deployment nginx-deploy
Name: nginx-deploy
Namespace: default
CreationTimestamp: Thu, 03 Apr 2025 21:01:24 +0800
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision: 1
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:Labels: app=nginxContainers:nginx:Image: nginx:1.14.2Port: 80/TCPHost Port: 0/TCPEnvironment: <none>Mounts: <none>Volumes: <none>
Conditions:Type Status Reason---- ------ ------Available True MinimumReplicasAvailableProgressing True NewReplicaSetAvailable
OldReplicaSets: <none>
NewReplicaSet: nginx-deploy-86dcfdf4c6 (3/3 replicas created)
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal ScalingReplicaSet 26m deployment-controller Scaled up replica set nginx-deploy-86dcfdf4c6 to 3
如果Deployment创建不成功,可以通过查看事件信息来查找原因。
六、测试Deployment的自我修复功能
Deployment具有自我修复功能,下面在上述实验的基础上测试该功能。
(1)将node01主机关机以模拟故障。
[root@node1 ~]# poweroff
(2)稍等片刻,查看Deployment部署的ReplicaSet,可以发现只有1个ReplicaSet正常运行(READY值为1),node01节点上的ReplicaSet暂时不能提供服务。
[root@master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-86dcfdf4c6 3 3 1 30m
(3)稍等一会,再次查看ReplicaSet,可以发现已经恢复为3个ReplicaSet正常运行(READY值为3)。
[root@master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-86dcfdf4c6 3 3 3 35m
(4)进一步查看Deployment部署的Pod。
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-86dcfdf4c6-4729k 1/1 Terminating 0 35m 10.244.166.154 node1 <none> <none>
nginx-deploy-86dcfdf4c6-66dcp 1/1 Terminating 0 35m 10.244.166.155 node1 <none> <none>
nginx-deploy-86dcfdf4c6-hbsfc 1/1 Running 0 17s 10.244.104.10 node2 <none> <none>
nginx-deploy-86dcfdf4c6-kms6l 1/1 Running 0 17s 10.244.104.9 node2 <none> <none>
nginx-deploy-86dcfdf4c6-mxvwx 1/1 Running 0 35m 10.244.104.8 node2 <none> <none>
可以发现,node01节点上的Pod副本正常被终止运行,而node02节点上自动增加了新的Pod副本。
(5)启动node01主机以模拟故障恢复。稍等片刻,再次查看Pod副本,会发现3个副本仍然都在node02节点上运行,这表明Deployment完成了资源的自动修复,始终保持Pod副本数符合期望值,但是并不会将Pod恢复到原有节点上。
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-86dcfdf4c6-hbsfc 1/1 Running 0 4m16s 10.244.104.10 node2 <none> <none>
nginx-deploy-86dcfdf4c6-kms6l 1/1 Running 0 4m16s 10.244.104.9 node2 <none> <none>
nginx-deploy-86dcfdf4c6-mxvwx 1/1 Running 0 39m 10.244.104.8 node2 <none> <none>
七、更新Deployment
通过Deployment部署应用程序后,拖过Deployment配置文件被更改,或者镜像版本发送更迭,则可以更新或升级Deployment。注意,仅当Deployment的Pod模板定义(.spec.template字段)发生改变时,如模板的标签或容器镜像被更改,才会触发Deployment的更新,其他修改(如增减副本数)并不会触发更新。
Deployment定义的.spec.strategy.type字段值决定两种更新方式:
一种是Recreate,表示重新创建,即在创建新的pod之前,终止所有现有的pod,待这些pod被重新移除之后,才会创建新版本的Pod;
另一种是RollingUpdate,即滚动更新,这是默认设置。采用滚动更新方式时,可以定义maxUnavaiable和maxSurge字段来控制滚动更新过程。maxUnavailable指定滚动更新时允许不可用的Pod数量上限,可以用绝对数表示;也可以用百分比表示,指不可用的Pod副本数与所期望的Pod副本数的比例,值越小,越能保证服务稳定,更新越平滑。maxSurge指定滚动更新时可以创建的超出期望的Pod数量,可以用绝对数表示;也可以用百分比表示,指允许可用的Pod副本数与所期望的Pod副本数的比例,值越大,更新速度越快。这两者的默认值均为25%。
下面在前面例子的基础上示范升级容器镜像的更新操作。
(1)执行以下命令将运行nginx的Pod所使用的镜像升级为nginx:1.16.1。
[root@master ~]# kubectl set image deployment.v1.apps/nginx-deploy nginx=nginx:1.16.1
deployment.apps/nginx-deploy image updated
结果表明改Deployment的镜像已被更新。上述命令也可改用以下用法(采用Deployment的另一种标识)。
kubectl set image deployment/nginx-deploy nginx=nginx:1.16.1
我们还可以使用kubectl edit命令打开Deployment配置文件的编辑界面(如kubectl edit deployment/nginx-deploy),完成Pod模板定义的修改后,自动触发Deployment更新。
[root@master ~]# kubectl edit deployment/nginx-deploy
(2)执行以下命令查看改Deployment的更新状态(过程)。
[root@master ~]# kubectl rollout status deployment/nginx-deploy
deployment "nginx-deploy" successfully rolled out
更新过程中会发生新旧交替,创建新的副本,终止旧的副本。
(3)执行以下命令查看Deployment创建的ReplicaSet。
[root@master ~]# kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-deploy-848dd6cfb5 3 3 3 12m
nginx-deploy-86dcfdf4c6 0 0 0 73m
可以发现,更新Deployment的过程中,创建新的ReplicaSet并将其扩容到3个副本,并将旧的ReplicaSet缩容到0个副本。
(4)执行以下命令查看Deployment资源更新之后新创建的Pod。
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-848dd6cfb5-6hsxz 1/1 Running 0 9m53s 10.244.104.11 node2 <none> <none>
nginx-deploy-848dd6cfb5-6v49j 1/1 Running 0 8m40s 10.244.166.157 node1 <none> <none>
nginx-deploy-848dd6cfb5-86ktn 1/1 Running 0 14m 10.244.166.156 node1 <none> <none>
可以发现,原有的Pod被终止并被删除了,新的Pod重新部署到node01和node02节点上。
(5)执行命令查看该Deployment的详细信息。
[root@master ~]# kubectl describe deployment nginx-deploy
kubectl describe deployment nginx-deploy
Name: nginx-deploy
Namespace: default
CreationTimestamp: Thu, 03 Apr 2025 21:01:24 +0800
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision: 2
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:Labels: app=nginxContainers:nginx:Image: nginx:1.16.1Port: 80/TCPHost Port: 0/TCPEnvironment: <none>Mounts: <none>Volumes: <none>
Conditions:Type Status Reason---- ------ ------Available True MinimumReplicasAvailableProgressing True NewReplicaSetAvailable
OldReplicaSets: nginx-deploy-86dcfdf4c6 (0/0 replicas created)
NewReplicaSet: nginx-deploy-848dd6cfb5 (3/3 replicas created)
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal ScalingReplicaSet 17m deployment-controller Scaled up replica set nginx-deploy-848dd6cfb5 to 1Normal ScalingReplicaSet 12m deployment-controller Scaled down replica set nginx-deploy-86dcfdf4c6 to 2 from 3Normal ScalingReplicaSet 12m deployment-controller Scaled up replica set nginx-deploy-848dd6cfb5 to 2 from 1Normal ScalingReplicaSet 10m deployment-controller Scaled down replica set nginx-deploy-86dcfdf4c6 to 1 from 2Normal ScalingReplicaSet 10m deployment-controller Scaled up replica set nginx-deploy-848dd6cfb5 to 3 from 2Normal ScalingReplicaSet 10m deployment-controller Scaled down replica set nginx-deploy-86dcfdf4c6 to 0 from 1
滚动更新过程详解
启动新版本 Pod(nginx-deploy-848dd6cfb5):
17 分钟前:
新的副本集(ReplicaSet,即 nginx-deploy-848dd6cfb5)被创建,并启动 1 个新版本的 Pod。这是更新的初始阶段。
逐步替换旧版本 Pod:
12 分钟前:
缩减旧版本:旧的副本集(nginx-deploy-86dcfdf4c6)从 3 个 Pod 缩容到 2 个 Pod。
扩展新版本:新副本集的 Pod 数量从 1 个扩容到 2 个。
此时新旧版本共存,总 Pod 数保持为 4(2 旧 + 2 新),确保服务不中断。
继续替换直至完成:
10 分钟前:
再次缩减旧版本:旧副本集从 2 个 Pod 缩容到 1 个 Pod。
扩展新版本:新副本集的 Pod 数量从 2 个扩容到 3 个。
此时新旧版本共存,总 Pod 数保持为 4(1 旧 + 3 新)。
彻底淘汰旧版本:
10 分钟前(与上一步同一时间):
旧副本集最后一个 Pod 被终止(从 1 个缩容到 0 个)。
新副本集的 Pod 数量保持为 3 个,完全接管流量。
八、回滚Deployment
如果发现更新后的版本运行不稳定,或配置不合理,则可以回滚Deployment。默认情况下,Deployment的所有更新记录都保留在系统中,以便可以随时回滚。下面在前面的例子的基础上示范回滚操作。
用户可以在Deployment配置文件中使用.spec.revisionHistoryLimit字段指定可保留的ReplicaSet的个数,默认为10,多余的ReplicaSet将被清理。这是实现回滚的基础。如果将此字段值设置为0,将导致Deployment的所有历史记录被清空,Deployment也就无法实现回滚。
(1)执行以下命令检查Deployment的修订版本历史。
[root@master ~]# kubectl rollout history deployment/nginx-deploy
deployment.apps/nginx-deploy
REVISION CHANGE-CAUSE
1 <none>
2 <none>
此命令用于显示每次部署的版本号。CHANGE-CAUSE字段值是从Deployment的kubernetes.io/change-cause注解中复制过来的,创建修订版本时会自动记录。例如,用户可以通过以下方式设置CHANGE-CAUSE消息,以便为Deployment添加注解。
[root@master ~]# kubectl annotate deployment/nginx-deploy kubernetes.io/change-cause="image updated to 1.16.1"
deployment.apps/nginx-deploy annotated
(2)执行以下命令查看指定版本的详细信息(–revision选项指定版本号)。
[root@master ~]# kubectl rollout history deployment/nginx-deploy --revision=2
deployment.apps/nginx-deploy with revision #2
Pod Template:Labels: app=nginxpod-template-hash=848dd6cfb5Annotations: kubernetes.io/change-cause: image updated to 1.16.1Containers:nginx:Image: nginx:1.16.1Port: 80/TCPHost Port: 0/TCPEnvironment: <none>Mounts: <none>Volumes: <none>[root@master ~]#
(3)执行以下命令回滚到以前的版本,这里是版本1。
[root@master ~]# kubectl rollout undo deployment/nginx-deploy --to-revision=1
deployment.apps/nginx-deploy rolled back
如果要回滚到当前版本的上一版本,也可以使用kubectl rollout undo命令,例如
kubectl rollout undo deployment/nginx-deploy
(4)执行以下命令检查回滚是否成功以及Deployment是否正在运行
[root@master ~]# kubectl get deployment nginx-deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 3/3 3 3 111m
(5)执行命令查看该Deployment的详细信息。
[root@master ~]# kubectl describe deployment nginx-deploy
Name: nginx-deploy
Namespace: default
CreationTimestamp: Thu, 03 Apr 2025 21:01:24 +0800
Labels: app=nginx
Annotations: deployment.kubernetes.io/revision: 4kubernetes.io/change-cause: image updated to 1.16.1
Selector: app=nginx
Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:Labels: app=nginxContainers:nginx:Image: nginx:1.16.1Port: 80/TCPHost Port: 0/TCPEnvironment: <none>Mounts: <none>Volumes: <none>
Conditions:Type Status Reason---- ------ ------Available True MinimumReplicasAvailableProgressing True NewReplicaSetAvailable
OldReplicaSets: nginx-deploy-86dcfdf4c6 (0/0 replicas created)
NewReplicaSet: nginx-deploy-848dd6cfb5 (3/3 replicas created)
Events:Type Reason Age From Message---- ------ ---- ---- -------Normal ScalingReplicaSet 51m deployment-controller Scaled up replica set nginx-deploy-848dd6cfb5 to 1Normal ScalingReplicaSet 45m deployment-controller Scaled up replica set nginx-deploy-848dd6cfb5 to 3 from 2Normal ScalingReplicaSet 45m deployment-controller Scaled down replica set nginx-deploy-86dcfdf4c6 to 1 from 2Normal ScalingReplicaSet 45m deployment-controller Scaled down replica set nginx-deploy-86dcfdf4c6 to 0 from 1Normal ScalingReplicaSet 3m28s deployment-controller Scaled up replica set nginx-deploy-86dcfdf4c6 to 1 from 0Normal ScalingReplicaSet 3m26s deployment-controller Scaled down replica set nginx-deploy-848dd6cfb5 to 2 from 3Normal ScalingReplicaSet 3m26s deployment-controller Scaled up replica set nginx-deploy-86dcfdf4c6 to 2 from 1Normal ScalingReplicaSet 3m25s deployment-controller Scaled down replica set nginx-deploy-848dd6cfb5 to 1 from 2Normal ScalingReplicaSet 3m25s deployment-controller Scaled up replica set nginx-deploy-86dcfdf4c6 to 3 from 2Normal ScalingReplicaSet 3m24s deployment-controller Scaled down replica set nginx-deploy-848dd6cfb5 to 0 from 1Normal ScalingReplicaSet 52s deployment-controller Scaled up replica set nginx-deploy-848dd6cfb5 to 1 from 0Normal ScalingReplicaSet 50s (x2 over 46m) deployment-controller Scaled up replica set nginx-deploy-848dd6cfb5 to 2 from 1Normal ScalingReplicaSet 50s (x2 over 46m) deployment-controller Scaled down replica set nginx-deploy-86dcfdf4c6 to 2 from 3Normal ScalingReplicaSet 47s (x3 over 48s) deployment-controller (combined from similar events): Scaled down replica set nginx-deploy-86dcfdf4c6 to 0 from 1
(6)执行以下命令检查Deployment回滚之后的Pod。
[root@master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deploy-848dd6cfb5-cs82c 1/1 Running 0 112s
nginx-deploy-848dd6cfb5-dxt4m 1/1 Running 0 110s
nginx-deploy-848dd6cfb5-nj2mt 1/1 Running 0 108s
可以发现,Pod的名称改变了,回滚之后又重新创建了Pod,不过ReplicaSet恢复原来的名称。
九、暂停、恢复Deployment的更新
前面的更新都是立即触发更新,实际应用中可能涉及多个修改,为避免触发不必要的更新操作,可以在触发一个或多个更新之前先暂停Deployment的更新(上线),也就是临时禁用的更新功能,完成修改之后再重新恢复Deployment的更新。注意,暂停更新的Deployment并不影响用户的访问,仅是对Pod模板做的任何修改都不会触发更新的部署。下面在前面例子的基础上进行相应的操作。
(1)执行kubectl rollout pause命令暂停Deployment的更新。
[root@master ~]# kubectl rollout pause deployment/nginx-deploy
deployment.apps/nginx-deploy paused
(2)查看Deployment的ReplicaSet。
[root@master ~]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
nginx-deploy-848dd6cfb5 0 0 0 60m nginx nginx:1.16.1 app=nginx,pod-template-hash=848dd6cfb5
nginx-deploy-86dcfdf4c6 3 3 3 121m nginx nginx:1.14.2 app=nginx,pod-template-hash=86dcfdf4c6
可以发现,当前Deployment使用的是nginx:1.14.2镜像。
(3)执行以下命令更新Deployment的镜像。
[root@master ~]# kubectl set image deployment/nginx-deploy nginx=nginx:1.17.1
deployment.apps/nginx-deploy image updated
(4)再次查看Deployment的ReplicaSet。
[root@master ~]# kubectl get rs -o wide
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
nginx-deploy-848dd6cfb5 0 0 0 62m nginx nginx:1.16.1 app=nginx,pod-template-hash=848dd6cfb5
nginx-deploy-86dcfdf4c6 3 3 3 123m nginx nginx:1.14.2 app=nginx,pod-template-hash=86dcfdf4c6
可以发现,没有创建新的ReplicaSet,镜像都是原来的,说明没有更新部署被触发。
(5)继续执行其他更新操作,执行以下命令修改配额限制。
[root@master ~]# kubectl set resources deployment/nginx-deploy -c=nginx --limits=cpu=200m,memory=512Mi
deployment.apps/nginx-deploy resource requirements updated
这里将该Deployment的nginx容器的CPU限制为“200m”,内存设置为“512Mi”。
目前Deployment的更新处于暂停状态,所有的更新都不会产生任何效果。
(6)执行以下命令恢复Deployment的更新(上线)。
[root@master ~]# kubectl rollout resume deployment/nginx-deploy
deployment.apps/nginx-deploy resumed
(7)执行以下命令观察新的ReplicaSet的创建过程,其中包含应用程序的所有更新。
[root@master ~]# kubectl get rs -o wide -w
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
nginx-deploy-5877f89444 1 1 0 48s nginx nginx:1.17.1 app=nginx,pod-template-hash=5877f89444
nginx-deploy-848dd6cfb5 0 0 0 67m nginx nginx:1.16.1 app=nginx,pod-template-hash=848dd6cfb5
nginx-deploy-86dcfdf4c6 3 3 3 128m nginx nginx:1.14.2 app=nginx,pod-template-hash=86dcfdf4c6
观察完毕,使用Ctrl+C组合键退出监视状态。
十、扩缩容Deployment
随着业务量的变化,通常需要对应用程序进行扩容或缩容,也就是增减Pod副本数。扩缩容Deployment主要有两种方法。一种方法是修改YAML配置文件中的.spec.replicas字段的值,再执行kubectl apply命令实现Pod副本数的动态调整。
另一种方法是使用kubectl scale命令直接扩缩容,使用–replicas选项指定要达到的Pod副本数。这里在前面例子的基础上进行操作,执行以下命令将Pod副本数扩容到5。
[root@master ~]# kubectl scale deployment/nginx-deploy --replicas=5
deployment.apps/nginx-deploy scaled
检查Deploymnet状态,可以发现目前已有5个副本。
[root@master ~]# kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 5/5 5 5 136m
进一步检查Pod,可以发现有两个Pod副本是被添加到ReplicaSet中的。
[root@master ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deploy-5877f89444-7lcjb 1/1 Running 0 2m1s 10.244.166.163 node1 <none> <none>
nginx-deploy-5877f89444-js9cm 1/1 Running 0 92s 10.244.166.164 node1 <none> <none>
nginx-deploy-5877f89444-n4qkd 1/1 Running 0 9m28s 10.244.104.16 node2 <none> <none>
nginx-deploy-5877f89444-pgs8j 1/1 Running 0 2m1s 10.244.104.18 node2 <none> <none>
nginx-deploy-5877f89444-q5vm5 1/1 Running 0 90s 10.244.104.19 node2 <none> <none>
Deployment部署的应用程序的声明周期中的主要状态包括Progressing(进行中), Complete(已完成)和Failed(失败)。失败的Deployment无法继续运行,但是也可以对其执行扩缩容、回滚到以前的修订版本等操作;或者在需要对Deployment的Pod模板做多项调整时,将Deployment暂停更新。
完成以上实验后,执行以下命令删除该Deployment,以清理实验环境。
[root@master ~]# kubectl delete deployment nginx-deploy
deployment.apps "nginx-deploy" deleted
删除Deployment会清除它创建的所有ReplicaSet和Pod。