当前位置: 首页 > news >正文

【K8s-Day 22】深入解析 Kubernetes Deployment:现代应用部署的基石与滚动更新的艺术

Langchain系列文章目录

01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来

Python系列文章目录

PyTorch系列文章目录

机器学习系列文章目录

深度学习系列文章目录

Java系列文章目录

JavaScript系列文章目录

Python系列文章目录

Go语言系列文章目录

Docker系列文章目录

01-【Docker-Day 1】告别部署噩梦:为什么说 Docker 是每个开发者的必备技能?
02-【Docker-Day 2】从零开始:手把手教你在 Windows、macOS 和 Linux 上安装 Docker
03-【Docker-Day 3】深入浅出:彻底搞懂 Docker 的三大核心基石——镜像、容器与仓库
04-【Docker-Day 4】从创建到删除:一文精通 Docker 容器核心操作命令
05-【Docker-Day 5】玩转 Docker 镜像:search, pull, tag, rmi 四大金刚命令详解
06-【Docker-Day 6】从零到一:精通 Dockerfile 核心指令 (FROM, WORKDIR, COPY, RUN)
07-【Docker-Day 7】揭秘 Dockerfile 启动指令:CMD、ENTRYPOINT、ENV、ARG 与 EXPOSE 详解
08-【Docker-Day 8】高手进阶:构建更小、更快、更安全的 Docker 镜像
09-【Docker-Day 9】实战终极指南:手把手教你将 Node.js 应用容器化
10-【Docker-Day 10】容器的“持久化”记忆:深入解析 Docker 数据卷 (Volume)
11-【Docker-Day 11】Docker 绑定挂载 (Bind Mount) 实战:本地代码如何与容器实时同步?
12-【Docker-Day 12】揭秘容器网络:深入理解 Docker Bridge 模式与端口映射
13-【Docker-Day 13】超越默认Bridge:精通Docker Host、None与自定义网络模式
14-【Docker-Day 14】Docker Compose深度解析
15-【Docker-Day 15】一键部署 WordPress!Docker Compose 实战终极指南
16-【Docker-Day 16】告别单机时代:为什么 Docker Compose 不够用,而你需要 Kubernetes?
17-【Docker-Day 17】K8s 架构全解析:深入理解 Kubernetes 的大脑 (Master) 与四肢 (Node)
18-【Docker-Day 18】告别选择困难症:一文掌握 Minikube、kind、k3d,轻松搭建你的第一个 K8s 集群
19-【Docker-Day 19】万物皆 YAML:掌握 Kubernetes 声明式 API 的艺术
20-【Docker-Day 20】揭秘 Kubernetes 的原子单位:深入理解 Pod
21-【Docker-Day 21】Pod的守护神:ReplicaSet与ReplicationController,轻松实现应用高可用
22-【K8s-Day 22】深入解析 Kubernetes Deployment:现代应用部署的基石与滚动更新的艺术


文章目录

  • Langchain系列文章目录
  • Python系列文章目录
  • PyTorch系列文章目录
  • 机器学习系列文章目录
  • 深度学习系列文章目录
  • Java系列文章目录
  • JavaScript系列文章目录
  • Python系列文章目录
  • Go语言系列文章目录
  • Docker系列文章目录
  • 摘要
  • 一、从 ReplicaSet 到 Deployment:为什么需要 Deployment?
    • 1.1 回顾 ReplicaSet 的局限性
    • 1.2 Deployment 的诞生:声明式应用管理的王者
    • 1.3 Deployment、ReplicaSet 与 Pod 的关系
  • 二、Deployment 核心实践:创建与管理
    • 2.1 编写第一个 Deployment YAML 文件
      • 2.1.1 YAML 文件关键字段解析
    • 2.2 部署与验证
        • (1)查看 Deployment 状态
        • (2)查看 ReplicaSet
        • (3)查看 Pod
  • 三、应用生命周期的核心:滚动更新 (Rolling Update)
    • 3.1 什么是滚动更新?
    • 3.2 触发一次滚动更新
    • 3.3 监控更新过程
    • 3.4 控制滚动更新的速度:`maxSurge` 与 `maxUnavailable`
  • 四、救命稻草:应用回滚
    • 4.1 为什么要回滚?
    • 4.2 查看更新历史
    • 4.3 执行回滚操作
        • (1)回滚到上一个版本
        • (2)回滚到指定版本
    • 4.4 回滚的背后原理
  • 五、总结


摘要

在 Kubernetes 的世界里,如果说 Pod 是构建应用的“砖块”,那么 Deployment 就是指挥工匠如何砌墙并进行翻新维护的“总工程师”。作为 Kubernetes 中最核心、最常用的资源对象之一,Deployment 为我们提供了管理无状态应用(Stateless Application)的强大能力。它不仅能确保应用实例的高可用性,更重要的是,它引入了声明式的更新和回滚机制,彻底改变了我们对应用生命周期管理的认知。本文将从 ReplicaSet 的局限性出发,深入剖析 Deployment 的核心概念、工作原理,并通过详尽的实战示例,带你掌握如何使用 Deployment 实现应用的平滑滚动更新与一键回滚,为你的应用穿上“不死”与“不老”的铠甲。

一、从 ReplicaSet 到 Deployment:为什么需要 Deployment?

在上一篇文章中,我们学习了 ReplicaSet,它能够像一个忠诚的管家,时刻确保集群中运行着指定数量的 Pod 副本,实现了应用的高可用。但这位管家也有其力所不及之处,尤其是在面对应用“升级”这一核心运维场景时。

1.1 回顾 ReplicaSet 的局限性

ReplicaSet 的核心职责是“维稳”,即维持 Pod 副本数量的稳定。假设我们有一个运行着 app:v1 版本的 ReplicaSet,现在需要将其升级到 app:v2。使用 ReplicaSet 我们该怎么做呢?

通常,我们需要手动执行以下步骤:

  1. 创建一个新的 ReplicaSet,其 Pod 模板使用 app:v2 镜像。
  2. 手动将新的 ReplicaSet 的副本数从 0 逐渐增加。
  3. 同时,手动将旧的 ReplicaSet 的副本数逐渐减少。
  4. 等待所有 v2 版本的 Pod 启动并运行正常后,将旧的 ReplicaSet 副本数减为 0,并最终删除它。

这个过程不仅繁琐、易出错,而且在更新过程中,我们需要小心翼翼地管理流量,以避免服务中断。这是一种典型的命令式操作,我们告诉 Kubernetes “如何做”,而不是“我们想要什么”。

1.2 Deployment 的诞生:声明式应用管理的王者

为了解决上述痛点,Deployment 应运而生。Deployment 是一个更高层次的抽象,它站在 ReplicaSet 的“肩膀”上,为其赋予了应用更新历史版本管理的超能力。

使用 Deployment,我们不再需要关心底层的 ReplicaSet 是如何创建、扩容或缩容的。我们只需向 Deployment 声明(Declare) 我们期望的最终状态(Desired State),例如:“我需要 3 个副本,并且它们的应用版本是 app:v2”。

Deployment 控制器会持续监控当前状态与我们声明的期望状态,一旦发现不一致,它会自动采取行动,智能地编排底层 ReplicaSet 和 Pod,使系统最终达到我们声明的状态。这正是 Kubernetes 声明式 API 的精髓所在。

一个生动的类比:

  • ReplicaSet:像一位工头,他的任务就是确保工地上始终有 10 个工人在干活。如果有人累倒了,他会立刻找个新工人替上。但他不知道如何让工人们学习新技能(版本升级)。
  • Deployment:像一位项目经理,他不仅告诉工头需要保持 10 个工人,还负责制定培训和轮换计划。当需要升级工人技能时,他会带一批掌握新技能的工人(v2),然后有条不紊地替换掉旧工人(v1),整个过程对项目(服务)的进展影响最小。如果发现新技能有问题,他还能迅速让旧工人们回来返工(回滚)。

1.3 Deployment、ReplicaSet 与 Pod 的关系

Deployment 并不直接管理 Pod,而是通过管理 ReplicaSet 来间接控制 Pod。它们之间形成了一个清晰的层级关系。

  • Deployment:定义应用的期望状态,包括副本数、Pod 模板(镜像版本、端口等)以及更新策略。
  • ReplicaSet:由 Deployment 创建和管理,负责根据自身的 Pod 模板确保指定数量的 Pod 正常运行。Deployment 的每一次更新,通常都会创建一个新的 ReplicaSet。
  • Pod:由 ReplicaSet 创建和管理,是应用运行的最终实体。

二、Deployment 核心实践:创建与管理

理论结合实践是最好的学习方式。现在,让我们动手创建一个 Deployment。

2.1 编写第一个 Deployment YAML 文件

我们将部署一个包含 3 个副本的 Nginx 服务。创建一个名为 nginx-deployment.yaml 的文件,内容如下:

# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:name: nginx-deploymentlabels:app: nginx
spec:replicas: 3selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginximage: nginx:1.14.2 # 指定了 nginx 镜像的版本ports:- containerPort: 80

2.1.1 YAML 文件关键字段解析

  • apiVersion: apps/v1:Deployment 资源对象当前稳定版本的 API 路径。
  • kind: Deployment:指明这是一个 Deployment 类型的资源。
  • metadata:元数据,包含 Deployment 的名称 nginx-deployment 和标签 labels
  • spec:定义了 Deployment 的期望状态,这是核心部分。
    • replicas: 3:声明我们期望有 3 个 Pod 副本。
    • selector:选择器,定义了此 Deployment 管理哪些 Pod。matchLabels 中的 app: nginx 意味着它会寻找并管理所有带有 app: nginx 标签的 Pod。
    • template:Pod 模板,这部分是 Deployment 创建新 Pod 的“蓝图”。
      • metadata.labels: Pod 模板中的标签。极其重要:这里的标签 app: nginx 必须与 spec.selector.matchLabels 中的标签匹配,否则 Deployment 会创建失败。
      • spec.containers: 定义了 Pod 中容器的配置,包括容器名 nginx、使用的镜像 nginx:1.14.2 和暴露的端口 80

2.2 部署与验证

现在,使用 kubectl 命令将这个 YAML 文件应用到集群中。

# 应用 YAML 文件创建 Deployment
$ kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment created

创建成功后,我们可以通过一系列命令来验证部署状态。

(1)查看 Deployment 状态
$ kubectl get deployments
# 或者简写 kubectl get deploy
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           20s

输出列解析表:

列名解释
NAMEDeployment 的名称。
READY当前可用的副本数 / 期望的副本数 (current/desired)。3/3 表示已就绪。
UP-TO-DATE已更新到最新模板的副本数。
AVAILABLE当前可用的副本数。
AGEDeployment 已创建的时间。
(2)查看 ReplicaSet

你会发现 Deployment 自动创建了一个 ReplicaSet。

$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-7686485989   3         3         3       1m

这个 ReplicaSet 的名字由 Deployment 名称 nginx-deployment 加上一个随机的哈希值构成。

(3)查看 Pod

最后,查看由 ReplicaSet 创建的 Pod。

$ kubectl get pods --show-labels
NAME                               READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-7686485989-5qjjp   1/1     Running   0          2m    app=nginx,pod-template-hash=7686485988
nginx-deployment-7686485989-j4k7l   1/1     Running   0          2m    app=nginx,pod-template-hash=7686485988
nginx-deployment-7686485989-q8zcl   1/1     Running   0          2m    app=nginx,pod-template-hash=7686485988

注意,Pod 的名称由 ReplicaSet 名称加上一个随机字符串构成,并且它们都带上了我们定义的 app: nginx 标签,以及一个由 Kubernetes 添加的 pod-template-hash 标签,用于区分不同版本的 ReplicaSet。

三、应用生命周期的核心:滚动更新 (Rolling Update)

Deployment 最强大的功能之一就是滚动更新,它能保证在应用升级过程中服务不中断。

3.1 什么是滚动更新?

滚动更新(Rolling Update)是一种逐个替换旧版本 Pod 为新版本 Pod 的策略。Kubernetes 会先创建一个新版本的 Pod,等它成功启动并准备好接收流量后,再销毁一个旧版本的 Pod。这个过程会一直持续,直到所有的旧 Pod 都被新 Pod 替换完毕。

这种方式的巨大优势在于,在整个更新过程中,始终有可用的 Pod 在提供服务,从而实现了**零停机时间(Zero Downtime)**的部署。

UserKubernetesOld ReplicaSet (v1)New ReplicaSet (v2)kubectl apply -f updated-deployment.yaml创建 New ReplicaSet (replicas=0)Scale up to 1 (创建 Pod v2-1)等待 Pod v2-1 变为 ReadyScale down to 2 (删除 Pod v1-1)Scale up to 2 (创建 Pod v2-2)等待 Pod v2-2 变为 ReadyScale down to 1 (删除 Pod v1-2)Scale up to 3 (创建 Pod v2-3)等待 Pod v2-3 变为 ReadyScale down to 0 (删除 Pod v1-3)更新完成UserKubernetesOld ReplicaSet (v1)New ReplicaSet (v2)

3.2 触发一次滚动更新

触发滚动更新最常见的方式就是修改 Deployment 的 Pod 模板 (spec.template)。最典型的场景是更新容器镜像的版本。

我们将 nginx 的镜像从 1.14.2 更新到 1.16.1

方法一:声明式(推荐)

修改 nginx-deployment.yaml 文件:

# ... (其他部分不变) ...spec:containers:- name: nginximage: nginx:1.16.1 # <--- 修改这里的版本号
# ... (其他部分不变) ...

然后再次执行 apply 命令:

$ kubectl apply -f nginx-deployment.yaml
deployment.apps/nginx-deployment configured

方法二:命令式

对于快速测试或紧急修复,也可以使用 kubectl set image 命令:

$ kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1
deployment.apps/nginx-deployment image updated

这种方式虽然快捷,但不易于版本控制和追踪,在生产环境中推荐使用声明式的方式(即将 YAML 文件纳入 Git 管理)。

3.3 监控更新过程

在更新触发后,我们可以使用 rollout status 命令来实时监控进度。

$ kubectl rollout status deployment/nginx-deployment
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 2 out of 3 new replicas have been updated...
Waiting for deployment "nginx-deployment" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-deployment" successfully rolled out

在更新过程中,新开一个终端查看 ReplicaSet 和 Pod,你会看到有趣的景象:

# 查看 ReplicaSet
$ kubectl get rs
NAME                          DESIRED   CURRENT   READY   AGE
nginx-deployment-7686485989   1         1         1       10m
nginx-deployment-559d575459   3         3         2       1m  # <--- 新的 RS 正在扩容# 查看 Pod
$ kubectl get pods
NAME                                READY   STATUS              RESTARTS   AGE
nginx-deployment-7686485989-j4k7l   1/1     Running             0          10m # <--- 旧 Pod
nginx-deployment-559d575459-abcde   1/1     Running             0          1m  # <--- 新 Pod
nginx-deployment-559d575459-fghij   1/1     Running             0          45s # <--- 新 Pod
nginx-deployment-559d575459-klmno   1/1     ContainerCreating   0          10s # <--- 新 Pod
nginx-deployment-7686485989-q8zcl   1/1     Terminating         0          10m # <--- 旧 Pod 正在被终止

这清晰地展示了新旧 ReplicaSet 的交替过程。

3.4 控制滚动更新的速度:maxSurgemaxUnavailable

Deployment 允许我们通过 spec.strategy.rollingUpdate 字段来精细控制滚动更新的行为。

  • maxSurge:更新过程中,允许的超出期望副本数的最大 Pod 数量。可以是绝对数字(如 1)或百分比(如 25%)。默认值为 25%
  • maxUnavailable:更新过程中,允许的最大不可用 Pod 数量。可以是绝对数字或百分比。默认值为 25%

示例解析:
假设 replicas: 10,并采用默认策略 (maxSurge: 25%, maxUnavailable: 25%)。

  • maxSurge 计算结果为 ceil(10 * 0.25) = 3。这意味着在更新过程中,集群中最多可以有 10 + 3 = 13 个 Pod。Kubernetes 会先创建新的 Pod,再销毁旧的。
  • maxUnavailable 计算结果为 floor(10 * 0.25) = 2。这意味着在更新过程中,必须保证至少有 10 - 2 = 8 个 Pod 处于可用状态。

通过调整这两个参数,你可以在更新速度资源消耗/服务稳定性之间做出权衡。

  • 追求快速更新:可以适当调高 maxSurge
  • 资源紧张或对服务稳定性要求极高:可以调低 maxSurge 并将 maxUnavailable 设置为 0(这意味着必须先启动新 Pod 并就绪后,才能销毁旧 Pod)。
# ...
spec:replicas: 10strategy:type: RollingUpdaterollingUpdate:maxSurge: 1        # 每次最多只增加1个PodmaxUnavailable: 0  # 保证更新过程中可用Pod数量不低于10个
# ...

四、救命稻草:应用回滚

如果新发布的版本存在严重 Bug,Deployment 提供的回滚功能可以让你迅速恢复到上一个稳定版本,堪称“救命稻草”。

4.1 为什么要回滚?

回滚是应对发布失败的标准操作。常见的回滚场景包括:

  • 新版本应用引入了严重的 Bug,导致程序崩溃 (CrashLoopBackOff)。
  • 新版本存在性能问题,导致延迟升高或资源消耗激增。
  • 配置错误,导致应用无法正常启动或连接到依赖服务。

4.2 查看更新历史

Deployment 会为每一次成功的更新(即 Pod 模板的变更)保存一个修订版本(Revision)。我们可以查看这些历史记录。

$ kubectl rollout history deployment/nginx-deployment
deployment.apps/nginx-deployment
REVISION  CHANGE-CAUSE
1         <none>  # 对应 nginx:1.14.2 版本
2         <none>  # 对应 nginx:1.16.1 版本

专业提示:默认情况下 CHANGE-CAUSE 列是 <none>。你可以在执行 kubectl apply 时加上 --record 标志(已废弃但部分版本仍可用),或者在 Deployment 的 metadata.annotations 中添加 kubernetes.io/change-cause 来说明本次变更的原因,这对于追踪历史非常有帮助。

4.3 执行回滚操作

回滚操作非常简单。

(1)回滚到上一个版本

这是最常用的回滚命令。

$ kubectl rollout undo deployment/nginx-deployment
deployment.apps/nginx-deployment rolled back

执行后,Deployment 会将 Pod 模板恢复到 REVISION 1 的状态,并再次触发一次“滚动更新”,将 nginx:1.16.1 的 Pod 替换回 nginx:1.14.2

(2)回滚到指定版本

如果你想跳过某个版本,直接回滚到更早的版本,可以指定 --to-revision

$ kubectl rollout undo deployment/nginx-deployment --to-revision=1
deployment.apps/nginx-deployment rolled back

4.4 回滚的背后原理

回滚的实现机制非常巧妙。它本质上是利用 Deployment 的更新机制来完成的。当你执行 rollout undo 时,Kubernetes 做了以下事情:

  1. 从历史版本中找到你指定的回滚目标版本(如 REVISION 1)的 Pod 模板。
  2. 将 Deployment 的 spec.template 修改为这个旧的 Pod 模板。
  3. 这个修改行为本身又触发了一次标准的滚动更新流程。
  4. 于是,Kubernetes 创建了一个新的 ReplicaSet(其模板是旧版本的),并逐步替换掉当前运行中的、有问题的 Pod。

理解了这一点,你就会明白,回滚并非什么“黑魔法”,而是对 Deployment 核心能力的复用,整个过程同样是平滑和受控的。

五、总结

经过本文的深入学习,我们掌握了 Kubernetes 中应用管理的基石——Deployment。现在,让我们回顾一下核心要点:

  1. Deployment 的核心价值:Deployment 是 Kubernetes 中管理无状态应用的标准方式,它建立在 ReplicaSet 之上,提供了声明式的应用生命周期管理能力,解决了 ReplicaSet 无法直接处理应用更新的痛点。
  2. 层级管理关系:Deployment 通过管理 ReplicaSet,再由 ReplicaSet 管理 Pod,形成了一个清晰、可靠的控制链。每一次应用更新,Deployment 都会创建一个新的 ReplicaSet 来管理新版 Pod。
  3. 滚动更新(Rolling Update):这是 Deployment 的标志性功能,通过逐个替换 Pod 的方式,实现了零停机时间的应用升级。其更新速度和策略可以通过 maxSurgemaxUnavailable 参数进行精细化控制。
  4. 版本历史与回滚(Rollback):Deployment 会记录每次更新的修订历史,当新版本出现问题时,可以通过 kubectl rollout undo 命令快速、安全地回滚到之前的稳定版本,为生产环境的稳定性提供了强有力的保障。

掌握 Deployment 是精通 Kubernetes 的必经之路。它将运维人员从繁琐、易错的手动更新流程中解放出来,让我们能够更加从容、自信地进行应用发布和迭代。在后续的文章中,我们将学习如何通过 Service 将我们部署的应用暴露给外界访问。


http://www.dtcms.com/a/360398.html

相关文章:

  • 服装管理软件与工厂计件系统精选
  • 【OpenGL】LearnOpenGL学习笔记18 - Uniform缓冲对象UBO
  • [每周一更]-(第158期):构建高性能数据库:MySQL 与 PostgreSQL 系统化问题管理与优化指南
  • XPlayer播放器APP:安卓平台上的全能视频播放器
  • 网络代理协议深度对比
  • Linux/UNIX系统编程手册笔记:系统和进程信息、文件I/O缓冲、系统编程概念以及文件属性
  • Multi-Head RAG: Solving Multi-Aspect Problems with LLMs
  • ST-2110概述
  • MySQL专题Day(1)————事务
  • postman 用于接口测试,举例
  • Linux shell 脚本基础 003
  • centos7安装jdk17
  • c++程序员日常超实用工具(长期记录更新)
  • PS自由变换
  • 【人工智能99问】LLaMA中的RoPE是什么?(35/99)
  • 学习Python中Selenium模块的基本用法(12:操作Cookie)
  • 【系统分析师】高分论文:论大数据架构的应用
  • 写一个 RTX 5080 上的 cuda gemm fp16
  • 使用yt-dlp下载网页视频
  • synchronized的锁对象 和 wait,notify的调用者之间的关系
  • Wi-Fi技术——初识
  • Flink NettyBufferPool
  • Docker中使用Compose配置现有网络
  • C语言————深入理解指针1(通俗易懂)
  • Linux 网络编程:深入理解套接字与通信机制
  • 【MySQL自学】SQL语法全解(上篇)
  • Matlab自学笔记六十六:求解带参数的不等式
  • MySQL服务启动命令手册(Linux+Windows+macOS)(下)
  • 盛最多水的容器:双指针法的巧妙运用(leetcode 11)
  • ARM裸机开发(基础汇编指令)Day02