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

K8s 实战:Pod 版本更新回滚 + 生命周期管控

一、版本更新与回滚

实验背景

本实验通过 Kubernetes 的 Deployment 资源演示应用的版本更新与回滚流程。Deployment 是 Kubernetes 中用于管理 Pod 和 ReplicaSet 的核心资源,支持滚动更新(避免服务中断)和版本回滚(应对更新故障),是生产环境中部署无状态应用的标准方式。

1.1.版本更新

kubectl create deployment web --image myapp:v1 --replicas 4
  • create deployment web:创建一个名为web的 Deployment 资源,用于定义应用的部署规则。

  • --image myapp:v1:指定应用初始镜像为myapp:v1(假设这是应用的第一个稳定版本)。

  • --replicas 4:设置副本数为 4,通过多副本实现高可用—— 即使个别 Pod 故障,其他副本仍能提供服务,避免单点失效。

kubectl expose deployment web --port 80 --target-port 80 
  • expose deployment web:为web这个 Deployment 创建一个 Service 资源,用于将 Pod 暴露给集群内 / 外的访问者。

  • --port 80:Service 的端口(集群内其他服务通过此端口访问)。

  • --target-port 80:Pod 内应用实际监听的端口(需与容器内应用的端口一致,此处假设myapp镜像的应用监听 80 端口)。

  • Pod 的 IP 是动态变化的(重建后会改变),而 Service 会分配一个固定的 ClusterIP,并通过标签选择器关联 Pod,实现 “IP 固定化” 和 “自动负载均衡”—— 访问 Service 的 ClusterIP 时,请求会自动转发到后端健康的 Pod。

kubectl get service

作用与意义:查看刚创建的 Service 信息,重点获取CLUSTER-IP(示例中为10.106.16.15),这是集群内访问该服务的入口地址。

curl 10.106.16.15

作用与意义:通过curl访问 Service 的 ClusterIP,验证应用是否正常响应(示例中返回myapp:v1的页面内容)。

kubectl rollout history deployment web

作用与意义:查看web这个 Deployment 的版本更新历史。初始状态下,只有 1 个版本(revision 1),记录了初始部署的配置(如镜像myapp:v1)。

实际价值:Kubernetes 会自动记录 Deployment 的每一次更新(如镜像变更、副本数调整等),形成 “版本快照”,为后续回滚提供依据。在生产环境中,这是追溯变更、排查问题的关键。

kubectl set image deployments/web myapp=myapp:v2
​
kubectl rollout history deployment web

作用与意义:

  • set image:修改 Deployment 中容器的镜像,将web Deployment 下的myapp容器镜像从v1更新为v2(假设v2是新开发的版本)。

  • 底层逻辑:Kubernetes 会触发 “滚动更新”—— 先创建使用myapp:v2的新 Pod,待新 Pod 就绪后,再逐步删除旧的v1 Pod,整个过程中服务不中断。

  • 再次查看历史,会发现新增一个版本(revision 2),记录了 “镜像从 v1 变为 v2” 的变更。

curl 10.106.16.15
  • 访问 Service 验证更新结果,此时应返回 myapp:v2 的页面内容,确认新版本已生效。

实际价值:滚动更新是生产环境中发布新版本的标准方式,通过 “先增后删” 的策略避免服务中断,平衡了更新效率与业务连续性。

1.2.版本回滚

版本回滚(v2→v1)

kubectl rollout undo deployment web --to-revision 1

作用与意义:

  • rollout undo:将 Deployment 回滚到指定版本(--to-revision 1即回滚到初始的 v1 版本)。

  • 底层逻辑:类似更新流程,Kubernetes 会创建v1版本的 Pod,就绪后删除v2版本的 Pod,实现 “无感知回滚”。

kubectl rollout history deployment web
  • 查看历史会发现,回滚操作会生成一个新的版本记录(如 revision 3),但实际配置与 revision 1 一致,便于追溯回滚动作。

curl 10.106.16.15

再次访问 Service,确认返回内容恢复为 myapp:v1,验证回滚成功。

实验总结

本实验通过 Deployment 的 “创建→暴露→更新→回滚” 流程,展示了 Kubernetes 对应用生命周期的精细化管理:

  1. 多副本部署保障高可用;

  2. Service 实现 Pod 的稳定访问与负载均衡;

  3. 滚动更新实现新版本的无中断发布;

  4. 版本历史与回滚机制提供了故障快速恢复能力。


二、pod生命周期

Pod 是 Kubernetes 中最小的部署单元,其生命周期包含 “启动初始化→运行中监控→就绪接收请求” 三个核心阶段。本实验通过Init 容器(初始化阶段)存活探针(运行监控阶段)就绪探针(请求准入阶段) 的配置与验证,完整演示 Pod 生命周期的管控逻辑,理解 K8s 如何保障应用从启动到服务的稳定性。

2.1.INIT 容器

实验背景

Init 容器是 Pod 启动过程中先于主容器执行的 “初始化容器”,核心作用是完成主容器启动前的前置依赖任务(如等待其他服务就绪、下载配置文件、初始化数据库等)。其特点是:必须执行成功后,主容器才会启动;且仅在 Pod 首次启动时执行一次,退出后不再重启。

kubectl run initpod --image myapp:v1 --dry-run=client -o yaml > init.yml
​
vim init.yml 
############
apiVersion: v1
kind: Pod
metadata:labels:run: initpodname: initpod
spec:containers:- image: myapp:v1name: initpod   initContainers:           # Init 容器:主容器启动前执行的初始化容器- name: init-myservice    # Init 容器名称image: busyboxcommand: ["sh","-c","until test -e /testfile; do echo wating for myservice; sleep 2; done"]                   # 核心逻辑:循环检查 /testfile 是否存在,不存在则输出等待信息,每 2 秒重试一次
###########
​
kubectl apply -f init.yml 
​
kubectl get pods        # 查看 pod 状态
  • od 状态显示为 Init:0/1,含义是 “需要执行 1 个 Init 容器,当前完成 0 个”。

  • 核心逻辑:K8s 会优先启动 Init 容器,只有 Init 容器执行成功(退出码为 0),主容器才会启动。此时 Init 容器卡在 “等待 /testfile” 的循环中,未成功退出,因此主容器处于 “阻塞未启动” 状态。

kubectl logs pods/initpod init-myservice    # 查看名为 init-myservice 的 Init 容器日志
  • 日志持续输出 waiting for myservice,验证 Init 容器正在按 command 逻辑循环等待 —— 证明初始化任务正在执行,未满足 “/testfile 存在” 的条件。

  • 实际价值:通过日志可定位 Init 容器的阻塞原因(如依赖服务未就绪、文件未挂载等),是排查 Pod 启动卡壳的关键手段。

kubectl exec pods/initpod -c init-myservice -- /bin/sh -c "touch /testfile" # 进入 Init 容器,手动创建 /testfile
​
kubectl get pods     # 再次查看 Pod 状态

  • 执行 touch /testfile 后,Init 容器的 until 循环条件满足(/testfile 存在),循环退出,Init 容器执行成功(退出码为 0)。

  • Pod 状态从 Init:0/1 变为 Running,说明主容器已启动 —— 验证 Init 容器的 “前置阻塞 + 一次性执行” 特性。

  • 实际意义:此过程模拟了 “依赖就绪后启动主服务” 的生产场景,例如:只有数据库初始化完成,后端应用容器才启动,避免主容器因依赖缺失报错。

2.2.存活探针

实验背景

存活探针(Liveness Probe)是 Kubernetes 用于检测容器是否 “存活” 的核心机制。当探针判定容器不健康时,Kubernetes 会自动重启容器,实现 “故障自愈”,这是保障应用高可用性的关键特性。本实验通过配置 TCP 类型的存活探针,模拟容器故障时的自动恢复过程。

存活探针是 K8s 对 “运行中容器是否健康” 的持续监控机制 ——若探针判定容器不健康(如进程无响应、端口不可用),K8s 会自动重启容器,实现 “故障自愈”,避免服务长期不可用。与 Init 容器不同,存活探针在容器整个运行周期中持续执行。

vim live.yml 
#############
apiVersion: v1
kind: Pod
metadata:labels:run: livenessname: liveness
spec:containers:- image: myapp:v1name: livenesslivenessProbe:tcpSocket:port: 8080            # 检查容器的 8080 端口是否可连接initialDelaySeconds: 3  # 容器启动后延迟 3 秒再开始第一次探测periodSeconds: 1        # 每 1 秒执行一次探测timeoutSeconds: 1       # 探测超时时间(1 秒内未响应则判定失败)
#############
​
kubectl apply -f live.yml 
​
kubectl get pods                # 查看 pod 状态,pod 没启动
kubectl describe pods/liveness  # 查看 pod 详细信息
  • Pod 状态显示为 CrashLoopBackOff:含义是 “容器反复启动后崩溃”。

  • kubectl describe 输出 Liveness probe failed: dial tcp 10.244.0.xx:8080: connect: connection refused):

    • 原因:myapp:v1 容器默认未启动监听 8080 端口的服务(如未启动 nginx、Java 应用等),存活探针 TCP 连接失败,K8s 判定容器 “不健康”,触发重启。

    • 核心逻辑:存活探针的核心是 “持续监控 + 失败重启”—— 只要容器运行,探针就会周期性执行,失败次数达到阈值(默认 3 次)后,容器会被重启,直到探针成功。

kubectl exec -it pods/liveness -- /bin/sh   # 进入容器内部# 在容器内执行命令,开启8080端口
​
kubectl get pods            # 查看 pod 状态,pod 启动成功

实验总结

本实验通过 TCP 类型的存活探针,验证了 Kubernetes 的 “故障自愈” 能力,核心价值体现在:

  1. 自动检测故障:通过定期探测容器端口,及时发现应用无响应的问题(如进程崩溃、端口阻塞)。

  2. 自动恢复服务:一旦探测失败,立即重启容器,将服务恢复到正常状态,减少人工干预成本。

  3. 参数适配性:initialDelaySeconds 避免启动阶段误判,periodSeconds 和 timeoutSeconds 平衡探测灵敏度与资源消耗。

2.3.就绪探针

实验背景

就绪探针与存活探针的核心区别:

  • 存活探针:判断 “容器是否存活→是否需要重启”;

  • 就绪探针:判断 “容器是否就绪→是否可以接收请求”。 即使容器进程在运行,若就绪探针失败,K8s 也会将其从 Service 的负载均衡列表中移除,不转发请求,避免用户访问到 “未准备好” 的服务(如应用启动后仍在加载数据、初始化配置)。

vim read.yml 
############
apiVersion: v1
kind: Pod
metadata:labels:run: readinessname: readiness
spec:containers:- image: myapp:v1name: readinessreadinessProbe:           # 就绪探针配置httpGet:                # 探测方式:发送HTTP GET请求,检查应用层是否正常path: /test.html      # 探测路径port: 80              # 探测端口initialDelaySeconds: 1  # 容器启动后1秒开始第一次探测periodSeconds: 3        # 每3秒探测一次timeoutSeconds: 1       # 1秒内无响应则判定失败
############

探测方式选择(httpGet):

  • 适用于 Web 应用,通过检查 “指定 URL 的 HTTP 响应状态码” 判定就绪状态(默认返回 200-399 视为成功)。

  • 本实验中,path: /test.html 是模拟 “应用需加载特定页面 / 配置文件才就绪” 的场景(如实际环境中探测 /health 健康检查接口)。

kubectl apply -f read.yml 
​
kubectl get pods        # # 查看 Pod 状态,未就绪
kubectl describe pods/readiness 
  • Pod 状态显示为 Running 但 READY 列为 0/1:含义是 “容器进程在运行,但未就绪,无法接收请求”。

  • kubectl describe 输出 Readiness probe failed: HTTP probe failed with statuscode: 404:

    • 原因:/test.html 文件不存在,HTTP 请求返回 404,就绪探针判定 “未就绪”。

    • 核心逻辑:即使容器进程(如 nginx)在运行,只要就绪探针失败,K8s 就会将该 Pod 从 Service 的后端列表中排除,避免请求被转发到 “能访问但返回错误” 的容器。

kubectl exec pods/readiness -- /bin/sh -c "touch /usr/share/nginx/html/test.html"   # 进入容器,手动创建/test.html
kubectl get pods    # 再次查看Pod状态
  • 创建 /test.html 后,就绪探针发送 HTTP GET 请求到 /test.html,返回 200 状态码,探针成功,Pod 的READY列从 0/1 变为 1/1。

  • 实际价值:此时若该 Pod 关联了 Service,K8s 会自动将其加入负载均衡列表,开始转发请求 —— 避免了 “应用启动但未就绪时接收请求导致失败” 的问题(如用户访问返回 404、503)。

  • 示例场景:若 myapp:v1 启动后需要 10 秒加载数据库数据,可通过就绪探针循环探测 /health 接口,直到数据加载完成(接口返回 200),才允许接收请求,提升用户体验。

2.4.实验总结

Pod 生命周期三大核心机制的价值

机制作用阶段核心目标关键特性生产场景应用
Init 容器Pod 启动前完成主容器前置依赖阻塞主容器启动、一次性执行、成功后退出等待数据库就绪、下载配置文件、初始化权限
存活探针容器运行中故障自愈(不健康则重启)持续探测、失败重启、保障容器存活恢复端口无响应、进程死锁的应用
就绪探针容器运行中请求准入控制(就绪才接收)持续探测、未就绪则隔离、就绪后加入负载避免未加载完成的应用接收用户请求

三者协同作用,覆盖了 Pod 从 “启动→运行→服务” 的全生命周期稳定性需求:

  • Init 容器确保主容器 “有依赖才能启动”;

  • 存活探针确保运行中容器 “不健康能自愈”;

  • 就绪探针确保服务 “就绪后才接收请求”; 最终实现 K8s 应用的高可用、低故障运行。

存活探针和就绪探针的区别

1. 区别

  • 存活探针(Liveness Probe)
    核心是判断「容器是否还 “活着”(能正常运行)」,不是只看 “是否存在所选资源”。
    比如容器里的应用进程崩溃、端口阻塞、执行命令返回错误等,只要探针判定 “不健康”,Kubernetes 就会 直接重启容器(不是重启 Pod,Pod 里的容器重启),目的是修复 “死了” 的应用,实现 “故障自愈”。

  • 就绪探针(Readiness Probe)
    核心是判断「容器是否 “就绪”(能正常提供服务)」,未就绪时确实 “不重启”,但不只是 “等待”—— 更关键的是,Kubernetes 会 把这个 Pod 从服务负载均衡列表中移除,不让流量转发给它。
    比如应用启动了但还在加载配置 / 连接数据库,此时容器 “活着” 但不能服务,就绪探针会让它 “待命”,直到就绪后再重新接入流量,避免用户访问到 “能连但用不了” 的服务。

2. 一句话总结关键差异

维度存活探针(Liveness)就绪探针(Readiness)
目标保 “存活”(修复故障)保 “可用”(避免无效流量)
失败后行为重启容器(自愈)移除流量、等待就绪(不重启)
典型场景应用崩溃、端口无响应应用启动中、依赖未就绪(如 DB)
http://www.xdnf.cn/news/18543.html

相关文章:

  • 嵌入式学习日记(33)TCP
  • 【UnityAS】Unity Android Studio 联合开发快速入门:环境配置、AAR 集成与双向调用教程
  • CMake link_directories()详细介绍与使用指南
  • STM32F1 GPIO介绍及应用
  • C/C++三方库移植到HarmonyOS平台详细教程(补充版so库和头文件形式)
  • 凌霄飞控开发日志兼新手教程——基础篇:认识基本的文件内容和相关函数作用(25电赛备赛版)
  • 【序列晋升】12 Spring Boot 约定优于配置
  • Spring发布订阅模式详解
  • Python 调用 sora_image模型 API 实现图片生成与垫图
  • 【论文】Zotero文献管理
  • 为什么应用会突然耗尽所有数据库连接
  • 轮廓检测技术不仅能精确计算图像中的轮廓数量,还能完整记录每个轮廓包含的所有像素点坐标
  • 【0基础3ds Max】捕捉工具详解
  • 宋红康 JVM 笔记 Day06|虚拟机栈
  • [激光原理与应用-318]:结构设计 - Solidworks - 草图
  • 损耗源:导线电阻与趋肤效应
  • 深度学习②【优化算法(重点!)、数据获取与模型训练全解析】
  • 线上日志排查问题
  • MCP 与 Function Calling 打开真实世界的两种“母体”方式
  • Spring 框架深度解析:从核心原理到实战应用
  • GitLab CI :深入剖析 gl-sbom-report.cdx.json 解码“数字身份证”
  • linux下的网络编程
  • 快速入门Vue3——初体验
  • 6020角度双环控制一种用于电机控制的策略
  • 智能合约漏洞检测技术综述:守护区块链世界的“自动售货机”
  • 在通义灵码中配置MCP服务
  • uniapp使用map打包app后自定义气泡不显示解决方法customCallout
  • JavaWeb前端05(Vue工程化,Vue组件两种风格:组合式API 和 选项式API)及简单案例)
  • 豆包 + 蘑兔,破解写歌难题!
  • 知识蒸馏 Knowledge Distillation 论文 Generalized Knowledge Distillation (GKD) 目标函数的演化