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

pod声明周期

Pod 对象自从其创建开始至其终止退出的时间范围称为其生命周期。在这段时间中,Pod 会处于多种不同的状态,并执行一些操作;其中,创建主容器(main container)为必须的操作,其他可选的操作还包括进行初始化容器(init container)、容器启动后钩子(post start hook)、容器的存活性探测(liveness probe)、就绪型探测(readiness probe)以及容器终止前钩子(pre stop hook)等,这些操作是否执行则取决于 Pod 的定义。

image-20250507170654213

初始化容器

运行主容器和启动后钩子函数

启动探针(只检测一次)

存活探针和就绪探针(周期性检测)

终止前钩子函数

一、Pod phase

无论是用户手动创建,还是通过 Deployment 等控制器创建,Pod 对象总是应该处于其生命进程中以下几个相位(phase)之一

  • pending:API Server 创建了 Pod 资源对象并已存入 etcd 中,但是它尚未被调度完成,或者仍处于从仓库下载镜像的过程中。
  • Running:Pod 已经被调度至某节点,并且所有容器都已经被 kubelet 创建完成。
  • Succeeded:Pod 中的所有容器都已经成功终止并且不会被重启。
  • Failed:所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非 0 值的退出状态或已经被系统终止。
  • Unkown:API Server 无法正常获取到 Pod 对象的状态信息,通常是由于其无法与所在工作节点的 kubelet 通信所致。

故障排查速查表

现象优先检查点关键命令
Pod卡在Pending节点资源/污点检查kubectl describe node
CrashLoopBackOff容器启动日志kubectl logs --previous
服务间歇性不可用Readiness探针配置kubectl get endpoints
终止耗时过长PreStop钩子执行情况kubectl get events -w
存储卷挂载失败PVC绑定状态kubectl get pvc -o wide

二、pod创建流程

在这里插入图片描述

  • 当执行apply命令时会加载证书文件($HOME/.kube/config)连接Api-server(假设是rc资源创建Pod副本数量为5);
  • Api-server对客户端请求进行验证,权限校验及资源清单配置文件解析;
  • 若权限校验没问题,就会将请求记录写入到etcd数据库中进行存储;
  • Control Manager组件查询api-server当前集群是否有任务需要维护(发现有一个rc资源有需要创建5个副本数,目前为0,于是会watch事件,监督其副本数量升为5个);
  • scheduler查询api-server是否有Pod需要处于调度状态,api-server返回需要调度的列表,及集群的状态信息供给scheduler调度;
  • scheduler调度完成后将结果返回给api-sever,api-sever将结果存储到etcd中;
  • kubelet将Pod状态及worker节点资源状态周期性上报给api-server;
  • api-server会验证kubelet的证书文件,验证通过后将数据写入到etcd中,与此同时,会将etcd中调度到该节点的Pod任务下发给kubelet;
  • kubelet开始创建Pod,并周期性上报该Pod状态及节点状态给api-server;

三、声明周期钩子

钩子函数能够感知自身生命周期中的事件,并在相应的时刻到来时运行用户指定的程序代码

k8s 在主容器的启动之后和停止之前提供了两个钩子函数

  • postStart:容器创建之后立刻执行,用于资源部署、环境准备等。
  • preStop:在容器被终止前执行,用于优雅关闭应用程序、通知其他系统等
钩子函数定义方式

钩子的回调函数支持两种方式定义动作,下面以 postStart 为例讲解,preStop 定义方式与其一致:

exec模式

在容器中执行指定的命令。如果命令退出时返回码为0,判定为执行成功。

lifecycle:postStart:exec:command:- cat- /var/lib/redis.conf

HTTP GET模式

对容器中的指定端点执行HTTP GET请求,如果响应的状态码大于等于200且小于400,判定为执行成功。

httpGet模式支持以下配置参数:

  • Host:HTTP请求主机地址,不设置时默认为Pod的IP地址。
  • Path:HTTP请求路径,默认值是/。
  • Port:HTTP请求端口号。
  • Scheme:协议类型,支持HTTP和HTTPS协议,默认是HTTP。
  • HttpHeaders:自定义HTTP请求头。

示例:访问 http://192.168.2.150:80/users

lifecycle:postStart:httpGet:path: /usersport: 80host: 192.168.2.150scheme: HTTP  # 或者HTTPS

四、容器探测

Kubernetes 存在 3 种类型的探针,当探针检测失败时容器会被重启,如果容器在多次 (次数通过配置参数决定) 重启后仍然无法通过探针检测,容器状态将会被设置为 CrashLoopBackOff, 这意味着容器处于崩溃循环状态,无法成功启动和运行

启动探针

Startup Probe (启动探针) 用于检测容器是否已经完成所有初始化操作。

对于starup探针是一次性检测,容器启动时进行检测,检测成功后,才会调用其他探针,且此探针不在生效。

如果提供了启动探针,则所有其他探针都会被禁用,直到此探针成功为止。
如果启动探测失败,kubelet将杀死容器,而容器依其重启策略进行重启。 
如果容器没有提供启动探测,则默认状态为 Success。
存活探针

【pod是否准备就绪】

Liveness Probe (存活探针) 用于检测容器内部应用是否在运行,可以为单个 Pod 中的所有容器单独设置,存活探针会监控容器的健康状态,如果容器发生故障或崩溃,存活探针会判断容器不再存活,容器会被重启或替换。

一旦启动探针成功返回一次,存活探针就开始接管对容器对监控。

健康状态检查,周期性检查服务是否存活,==检查结果失败,将"重启"容器(==删除源容器并重新创建新容器)。
如果容器没有提供健康状态检查,则默认状态为Success。
就绪探针

【pod服务是否能被外部访问】

Readiness Probe (就绪探针) 用于检测容器是否已经准备好接收流量,应用启动需要一系列初始化操作,就绪探针可以确保容器就绪前不会接收任何流量。 如果就绪检测失败,Pod 就不会再收到任何流量。

可用性检查,周期性检查服务是否可用,从而判断容器是否就绪。
若检测Pod服务不可用,则会将Pod从svc的ep列表中移除。
若检测Pod服务可用,则会将Pod重新添加到svc的ep列表中。
如果容器没有提供可用性检查,则默认状态为Success。
探针检测Pod服务方式

主要参数

initialDelaySeconds
表示容器启动后,等待多少时间之后再启动各类探针periodSeconds
表示探针执行检测的间隔时间timeoutSeconds
表示探针执行检测的超时后的等待时间successThreshold
表示探针执行检测失败之后,如果容器状态想再次被标记为健康,至少需要经过多少次连续成功检测failureThreshold
表示探针执行检测时,连续失败多少次,容器状态就会被确认不健康

HTTP GET

针对容器指定 URL 执行 HTTP 请求,如果响应码 Status Code 是 2xx 或者 3xx, 将应用标记为正常运行。否则将应用标记为不健康。

apiVersion: v1
kind: Pod
metadata:name: http-get-probe-example
spec:containers:- name: nginximage: nginx:latestports:- containerPort: 80livenessProbe:httpGet:path: /healthz  # 健康检查路径port: 80       # 容器端口scheme: HTTP   # 可选 HTTP/HTTPSinitialDelaySeconds: 5  # 容器启动后 5s 开始探测periodSeconds: 10       # 每 10s 探测一次timeoutSeconds: 2       # 超时时间 2sfailureThreshold: 3     # 连续失败 3 次后重启容器readinessProbe:httpGet:path: /port: 80initialDelaySeconds: 2periodSeconds: 5

TCP

针对容器指定端口号发起 TCP 连接,如果连接成功,将应用标记为正常运行。否则将应用标记为不健康。

该方法主要针对 HTTP 探针或命令探针无法运行的情况,例如 gRPC 或 FTP 等协议。

apiVersion: v1
kind: Pod
metadata:name: tcp-probe-example
spec:containers:- name: redisimage: redis:latestports:- containerPort: 6379livenessProbe:tcpSocket:port: 6379  # 检测 Redis 默认端口initialDelaySeconds: 15periodSeconds: 20readinessProbe:tcpSocket:port: 6379initialDelaySeconds: 5periodSeconds: 10

Exec

在容器内执行任意命令 (例如文件检查、网络检查),并检查命令的退出状态码,如果状态码为 0,将应用标记为正常运行。否则将应用标记为不健康。

适用场景

  • 检查文件是否存在(如 test -f /tmp/healthy)。
  • 运行脚本检测服务状态(如 curl localhost:8080)。
  • 数据库健康检查(如 mysqladmin ping)。
apiVersion: v1
kind: Pod
metadata:name: exec-probe-example
spec:containers:- name: myappimage: busybox:latestcommand: ["/bin/sh", "-c", "touch /tmp/healthy && sleep 3600"]livenessProbe:exec:command:- cat- /tmp/healthy  # 如果文件存在,返回 0(健康)initialDelaySeconds: 5periodSeconds: 5readinessProbe:exec:command:- sh- -c- "nc -z localhost 8080 || exit 1"  # 检查本地 8080 端口是否可连接initialDelaySeconds: 2periodSeconds: 3
最佳实践

启动探针

如果应用的启动时间过长,应该设置一个启动探针,并且==将 initialDelaySeconds 参数的值设置为大于应用的启动时间,==应用启动时, 不应该因为数据库等依赖项尚未就绪而崩溃,例如应该在连接失败后继续尝试重新连接,直到连接成功或者重试次数超出最大限制。

initialDelaySeconds 参数的取值可以参考监控中的应用启动时间 P99 分位值。

启动探针常用业务场景:

  • 数据库连接池初始化完成
  • 缓存连接池初始化完成
  • 热点数据缓存在本地初始化完成

还有一种做法是,直接将 initialDelaySeconds 参数值设置为大于应用启动的估计时长,不使用启动探针

存活探针

如果应用在发生鼓掌时无法自动结束退出 (例如遇到了死锁),应该设置一个存活探针,并指定 restartPolicy 为 “Always” 或 “OnFailure”, 这样该应用会被重启。

就绪探针

如果需要应用在完成初始化工作之后才能开始接收流量,应该设置一个就绪探针,这样可以避免流量进入到错误到 Pod 中。

就绪探针可能与存活探针相同,但是 就绪探针表示 Pod 在初始化阶段不接收任何流量,并且只有就绪探针返回成功后再开始接收流量, 虽然使用启动探针也可以完成同样的功能,但是就绪探针可以区分应用位于 “正在启动中” 和 “已经完成启动,正在当前状态是正常|失败” 两个不同的阶段中的哪一个。

小结

就绪探针和存活探针可以同时用于同一 Pod,这样可以确保流量无法到达未准备好的 Pod,并且在探针检测失败时重启

五、容器的重启策略

容器程序发生崩溃或容器申请超过限制的资源等原因都可能会导致 Pod 对象的终止,此时是否应该重建该 Pod 对象则取决于其重启策略(restartPolicy)属性的定义。

  • Always:但凡 Pod 对象终止就将其重启,此为默认设定。

  • OnFailure:仅在 Pod 对象出现错误时方才能将其重启。

  • Nerver:从不重启

restartPolicy 适用于 Pod 对象中的所有容器,而且它仅用于控制在同一节点上重新启动 Pod 对象的相关容器。
首次需要重启的容器,将在其需要时立即进行重启,随后再次需要重启的操作由 kubelet 延迟一段时间后进行,且反复的重启操作的延迟时长依次为 10秒、20秒、40秒、80秒、160秒 和 300秒,300秒是最大延迟时长。
Pod 一旦绑定到一个节点,Pod对象将永远不会被重新绑定到另一个点,它要么被重启,要么终止,直到节点发生故障或被删除。

六、pod终止流程

image-20250507164852268

  • 用户发出删除 pod 命令:kubectl delete pods ,kubectl delete -f yaml
  • Pod 对象随着时间的推移更新,在宽限期(默认情况下30秒),pod 被视为“dead”状态
  • pod 标记为“Terminating”状态
  • 第三步同时运行,监控到 pod 对象为“Terminating”状态的同时启动 pod 关闭过程
  • 第三步同时进行,endpoints 控制器监控到 pod 对象关闭,将pod与service匹配的 endpoints 列表中删除
  • 如果 pod 中定义了 preStop 钩子处理程序,则 pod 被标记为“Terminating”状态时以同步的方式启动执行;若宽限期结束后,
  • preStop 仍未执行结束,第二步会重新执行并额外获得一个2秒的小宽限期
  • Pod 内对象的容器收到 TERM 信号
  • 宽限期结束之后,若存在任何一个运行的进程,pod 会收到 SIGKILL 信号
  • Kubelet 请求 API Server 将此 Pod 资源宽限期设置为0从而完成删除操作

七、优雅终止

Pod 优雅关闭就是在容器被停止时,确保容器内的进程有足够的时间完成当前的任务,并且做必要的清理工作。这样可以避免因强制停止容器而导致的数据丢失、资源泄漏等问题。

具体来说,Kubernetes 会发送一个 SIGTERM 信号给容器,让容器进行自定义的清理工作。如果容器在指定时间内没有正常退出,Kubernetes 会发出 SIGKILL 强制终止容器。
优雅关闭的步骤:

  • 收到 SIGTERM 信号:容器收到停止信号,应该开始优雅关闭。
  • 等待 terminationGracePeriodSeconds 时间:容器会有一段时间来进行清理工作,这个时间段可以自定义。
  • 执行 preStop 钩子:如果配置了 preStop 钩子,它会在 SIGTERM 信号发送后立刻执行。
  • 完成清理并退出:容器完成清理工作后退出。
  • 超时后发送 SIGKILL:如果容器在规定时间内没有正常退出,Kubernetes 会强制终止它。

如何配置 Pod 的优雅关闭?

关键点:

terminationGracePeriodSeconds:控制容器关闭时的最大等待时间。
preStop钩子:容器关闭前执行的命令,帮助我们在容器退出前完成清理工作。

1.配置 terminationGracePeriodSeconds

控制容器关闭时的最大等待时间。

这是控制 Pod 在关闭时等待的时间。默认情况下是 30 秒,即容器会在收到 SIGTERM 信号后有 30 秒的时间来优雅退出。你可以通过 terminationGracePeriodSeconds 来修改这个时间。

示例:设置优雅关闭时间为 60 秒

apiVersion: v1
kind: Pod
metadata:name: mypod
spec:terminationGracePeriodSeconds: 60  # 设置优雅关闭时间为 60 秒containers:- name: my-containerimage: my-image
  1. 使用 preStop 钩子

preStop 钩子是一个非常有用的特性,它允许你在容器关闭前执行自定义的脚本或命令,帮助你完成一些清理工作。比如,可以在容器关闭前断开数据库连接、保存临时文件等。

示例:配置 preStop 钩子

apiVersion: v1
kind: Pod
metadata:name: mypod
spec:terminationGracePeriodSeconds: 60containers:- name: my-containerimage: my-imagelifecycle:preStop:exec:command: ["/bin/sh", "-c", "echo 'Stopping container...'; sleep 10"]

自定义的脚本或命令,帮助你完成一些清理工作。比如,可以在容器关闭前断开数据库连接、保存临时文件等。

示例:配置 preStop 钩子

apiVersion: v1
kind: Pod
metadata:name: mypod
spec:terminationGracePeriodSeconds: 60containers:- name: my-containerimage: my-imagelifecycle:preStop:exec:command: ["/bin/sh", "-c", "echo 'Stopping container...'; sleep 10"]
http://www.xdnf.cn/news/4569.html

相关文章:

  • 行业先锋:六款产品的实战表现
  • PageRank和TextRank
  • 源码分析之Leaflet中的LayerGroup
  • LLM :Function Call、MCP协议与A2A协议
  • 基于神经网络的 YOLOv8、MobileNet、HigherHRNet 姿态检测比较研究
  • uniapp-商城-43-shop 后台管理 页面
  • 音频相关基础知识
  • JavaScript ES6+ 最佳实践
  • 将Dify平台开发的工作流集成到Open WebUI中
  • 金融小知识
  • 【实战教程】零基础搭建DeepSeek大模型聊天系统 - Spring Boot+React完整开发指南
  • ChromaDB调用BGE模型的两种实践方式
  • 学习基本开锁知识
  • 【一篇详解】深入浅出RabbtiMQ消息队列
  • 阿里云平台与STM32的物联网设计
  • Python训练营打卡DAY18
  • 电气工程中漏源电压Vds的平台电压是什么?
  • 芳草集精油怎么样?佰草集精油的功效与用法一览
  • 利用相场法来求解任意脆性断裂问题
  • Notepad++中XML格式化插件介绍
  • Ubuntu安装pgsql
  • Golang 接口 vs Rust Trait:一场关于抽象的哲学对话
  • Qt 中信号与槽(signal-slot)机制支持 多种连接方式(ConnectionType)
  • Web 架构之负载均衡全解析
  • vue+vite难点和优化,及seo优化
  • 品质领航家装时代,亚新丽以匠心雕琢每一寸美好
  • GPT与LLaMA:两大语言模型架构的深度解析与对比
  • Kafka的消息保留策略是怎样的? (基于时间log.retention.hours或大小log.retention.bytes,可配置删除或压缩策略)
  • 强缓存与协商缓存的实现机制
  • AKS 网络深入探究:Kubenet、Azure-CNI 和 Azure-CNI(overlay)