想象你经营着一家“云上大酒店”。每一间客房(Pod)里住着一位住客(容器),酒店前台(API Server)在系统里记录着每间房的实时状态:房间还在清扫布置(Pending)、住客已刷卡入住(Running)、住客已正常退房(Succeeded)、房间被弄坏遭强制清退(Failed),或是前台彻底联系不上这间房(Unknown)。而每位客房管家(kubelet)手里都有一把“健康检测仪”——探针。管家会定期敲门确认住客还有没有呼吸(Liveness),有没有准备好接待访客(Readiness),以及新来的慢性子住客是否安顿妥当(Startup)。这篇文章,就带你从酒店前台和管家的视角,把 Pod 的一生和三种探针彻底看懂。

岗位关联

看懂 Pod 生命周期与探针机制,是云原生工程师排查微服务故障、设计高可用发布方案的必修课:你能快速定位服务重启原因、流量抖动来源、发布卡住的根因,并把“自动体检、自动自愈”真正落地到生产环境。

目录
  1. 可视化演示
  2. 生命周期阶段——前台面板上的状态灯
  3. 状态转换机制——管家手册里的规矩
  4. 存活探针Liveness——确认住客还有呼吸
  5. 就绪探针Readiness——是否准备好接待访客
  6. 启动探针Startup——给慢性子住客的缓冲期
  7. 探针配置参数——探测仪表的旋钮
  8. 探针实现方式——管家用哪种敲门法
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

展示Kubernetes Pod完整生命周期状态流转与三种健康探针(Liveness/Readiness/Startup)工作机制。切换模式查看各维度,拖动滑块调节探针检测间隔。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Pod生命周期状态流转 Pod生命周期:Pending(调度/拉镜像)→ContainerCreating(创建容器)→Running(运行中),正常终止进入Succeeded,异常终止进入Failed 状态转换由Kubelet驱动:API Server分配Node后进入Pending,容器运行时创建完成后转Running,退出码0为Succeeded,非0为Failed phase = Pending | Running | Succeeded | Failed | Unknown Pod状态是K8s调度的基础

生命周期阶段——前台面板上的状态灯

酒店前台(API Server)的系统屏幕上,每间客房都有一盏状态灯。房间正在打扫、住客还没进门,绿灯亮起标着 Pending;住客刷卡入住、房门关上,变成 Running;任务型住客(比如 Job 型 Pod)办完事正常退房,点亮 Succeeded;住客把房间弄得一塌糊涂必须强制清退,则亮起 Failed。还有一盏灰灯叫 Unknown——管家和前台彻底失联了,谁也不知道房间里发生了什么。

在 Kubernetes 中,Pod 的 phase 字段就是这盏状态灯。它属于 Pod 级别的“大状态摘要”,不关心容器内部细节,只告诉你住客整体处于哪个环节。Pending 意味着 Pod 已被 API Server 接受,但容器尚未全部创建完成(可能是调度中、镜像拉取中、初始化容器未跑完);Running 表示 Pod 已绑定节点、所有容器已创建且至少有一个仍在运行;Succeeded 与 Failed 都是终态,前者代表所有容器正常退出,后者代表至少一个容器以非零状态失败。

理解这五种阶段,就像看懂前台屏幕上的状态灯:你一眼就知道哪些房间住着人、哪些房间空出来了、哪些房间出了状况。排障的第一步,永远是先看 kubectl get pod 输出里的 STATUS 列——那是酒店前台最诚实的一句话。

Pod Phase∈{Pending,Running,Succeeded,Failed,Unknown}\text{Pod Phase} \in \{ \text{Pending}, \text{Running}, \text{Succeeded}, \text{Failed}, \text{Unknown} \}
phase 是 Pod 生命周期阶段的枚举值,就像酒店前台屏幕上“入住中 / 已退房”的粗粒度标签,精细节奏要看容器级别的状态。
  1. Pod PhasePod 的生命周期阶段字段,由 kubelet 与 API Server 协作维护。
    Pod Phase\text{Pod Phase}
  2. ∈(属于符号)表示 Pod 当前阶段一定取自右侧集合中的某一个枚举值,不存在集合外的状态。
    ∈\in
  3. Pending / Running / Failed分别对应等待调度、运行中、失败终止三种核心阶段。
    Pending, Running, Failed\text{Pending, Running, Failed}
  4. Succeeded / Unknown正常完成终态,以及管家失联时 API Server 给出的兜底标记。
    Succeeded, Unknown\text{Succeeded, Unknown}

状态转换机制——管家手册里的规矩

客房管家(kubelet)手里有一本《服务手册》,规定了住客在房间内发生各种情况时该如何处置。住客在等电梯、在洗澡、还是已经退房,对应容器状态的 Waiting、Running、Terminated 三态;住客突然跑路了怎么办,对应重启策略(restartPolicy);住客要退房时给多少时间收拾行李,对应优雅终止(graceful termination)。这些规矩共同驱动着前台面板上状态灯的切换。

重启策略是这本手册里最重要的一条:Always 表示住客无论什么原因离开都立刻安排新住客;OnFailure 表示只有住客自己作妖出事(异常退出)才安排新人,正常退房就不再安排;Never 表示这间房一旦空出来就永久关闭。而优雅终止则像退房流程:管家先敲门说“请收拾行李”(发送 SIGTERM 信号),给你默认 30 秒宽限期去保存数据、关闭连接,时间一到还没出来,保安就会用备用钥匙强行清房(发送 SIGKILL 强制杀死进程)。

这套“先礼后兵”的机制,保证了线上服务在缩容或发布时不会瞬间断连。住客优雅退房,留下的房间干干净净;强闯进来硬拖走,下一批住客(新 Pod)接手时可能面对一堆半写坏的文件——这也是为什么优雅终止宽限期要按业务启动耗时和清理耗时来调优。

Termination=SIGTERM→等待⏟gracePeriodSeconds→SIGKILL\text{Termination} = \text{SIGTERM} \rightarrow \underbrace{\text{等待}}_{\text{gracePeriodSeconds}} \rightarrow \text{SIGKILL}
Pod 终止不是一瞬间完成的:先优雅通知(SIGTERM),给足宽限期,逾期才动用暴力手段(SIGKILL)。
  1. TerminationPod 从 Running 走向结束的完整终止过程,包含信号发送与等待两个阶段。
    Termination\text{Termination}
  2. SIGTERMkubelet 首先向容器主进程发送优雅终止信号,允许应用自行清理现场。
    SIGTERM\text{SIGTERM}
  3. gracePeriodSeconds默认 30 秒的缓冲期,应用在此窗口内保存状态、关闭连接并退出。
    gracePeriodSeconds\text{gracePeriodSeconds}
  4. SIGKILL宽限期耗尽仍存活的进程会被强制杀死,保证 Pod 不会永远卡在终止中。
    SIGKILL\text{SIGKILL}

存活探针Liveness——确认住客还有呼吸

管家每天定时到客房门口听动静:里面还有没有呼吸声?叫两声有没有回应?如果连续几次敲门都没反应,管家就会联系保安破门而入——发现住客已经“假死”在房间里(进程还在,但逻辑死锁、goroutine 泄漏、事件循环卡死),赶紧把房间清理干净,安排一位新住客入住(重启容器)。

Liveness 探针(存活探针)干的就是这活儿。它周期性探测容器是否“活着”,注意这里“活着”的定义是进程本身状态良好,而不是业务对外可用。经典的死锁场景是:Java 应用进程没有退出,但所有工作线程都阻塞在抢锁上,HTTP 接口永远不返回。此时进程存在但已丧失服务能力,Liveness 探针失败累计到阈值后,kubelet 会杀掉容器并按 restartPolicy 重建,让服务恢复元气。

在云上大酒店里,Liveness 就是那个“每分钟确认住客还有没有气”的尽职管家。它不是用来判断“住客是否愿意开门见客”的——那太严厉了,会误伤正在午休的好住客。它只管一件事:这间房里还有没有活人。

failCount≥failureThreshold⇒Restart Container\text{failCount} \ge \text{failureThreshold} \Rightarrow \text{Restart Container}
存活探针的哲学是“宁可错杀不可放过”:连续失败次数一旦积累到阈值,就判定容器已死并对它进行重启。
  1. failCountLiveness 探针连续失败的次数计数器,成功一次就会清零。
    failCount\text{failCount}
  2. ≥ failureThreshold连续失败次数达到或超过阈值(默认 3 次)时触发后续动作。
    ≥failureThreshold\ge \text{failureThreshold}
  3. ⇒(推出符号)逻辑蕴含,表示条件满足后必然执行右侧动作。
    ⇒\Rightarrow
  4. Restart Containerkubelet 执行容器重启,实现“自动体检、自动恢复”的自愈闭环。
    Restart Container\text{Restart Container}

就绪探针Readiness——是否准备好接待访客

有些住客入住后要先打扫房间、布置客厅、打开空调,才方便接待访客。管家会在门口挂上“请勿打扰”的牌子,访客(流量)看到牌子就绕道去别的房间;等住客一切安排妥当,管家摘掉牌子,访客才会敲他的门。

Readiness 探针(就绪探针)就是这个“请勿打扰”牌子。它周期性检查容器是否“就绪”——注意,就绪不代表进程活着,而是代表当前是否能够接收外部请求。探测失败时,Kubernetes 将 Pod 从 Service 的 Endpoints 列表(后端地址簿)中摘除,流量不再转发过来;探测恢复后,Pod 自动加回列表。整个过程不会重启容器,纯粹是“流量开关”。

滚动更新就是靠这个牌子实现的:新房间的住客还没收拾好,牌子挂着,访客全去老房间;新住客陆续准备好、牌子逐个摘下,访客才慢慢分流过去。没有 Readiness 探针的滚动发布,如同让一群刚进门的住客手忙脚乱地同时见客——必然一地鸡毛。

failCount≥failureThreshold⇒Remove from Endpoints\text{failCount} \ge \text{failureThreshold} \Rightarrow \text{Remove from Endpoints}
就绪探针不是“生死判官”,而是“门童”:它只决定流量进不进门,却不会把住客赶出房间。
  1. failCountReadiness 探针连续失败的累计计数,成功一次立即清零。
    failCount\text{failCount}
  2. ≥ failureThreshold连续失败次数达到阈值(默认 3 次),触发摘除动作。
    ≥failureThreshold\ge \text{failureThreshold}
  3. Remove from Endpoints把 Pod IP 从 Service 端点的 IP 集合中移除,负载均衡器不再向它转发流量。
    Remove from Endpoints\text{Remove from Endpoints}

启动探针Startup——给慢性子住客的缓冲期

有些住客入住动作特别慢:行李几十个箱子要逐个搬(加载大模型权重)、房间要重新装修(初始化缓存与连接池)。如果管家按常规节奏敲门确认呼吸,很可能住客还在搬第一箱行李时就被误判为“没反应”,直接请保安清房,导致住客永远无法住下。

Startup 探针(启动探针)就是应对这种慢性子住客的专用机制。启动探针临时接管“确认住客状态”的职责,以它自己的节奏反复检查住客是否安顿完毕;只有 Startup 探针成功后,Liveness 和 Readiness 探针才会开始正常工作。也就是说,Startup 探针相当于一个“满血保护期”,保护慢启动容器不被 Liveness 误杀。

在云上大酒店里,Startup 探针是给“搬行李选手”的专属礼遇:先让客人从容进屋,安顿好了,管家才开始例行检查。大模型推理服务、JVM 应用、缓存预热型中间件,都是它的忠实受益者。

Startup Success⇒Start Liveness / Readiness\text{Startup Success} \Rightarrow \text{Start Liveness / Readiness}
配置了 Startup 探针后,Liveness 和 Readiness 都会“待命”,直到容器完成启动,这是时序上的强制依赖。
  1. Startup SuccessStartup 探针检测成功,表示应用已完成初始化、进入稳定运行状态。
    Startup Success\text{Startup Success}
  2. ⇒(推出符号)逻辑蕴含,表示成功是后续动作的前提条件。
    ⇒\Rightarrow
  3. Start Liveness / ReadinessLiveness 与 Readiness 探针此时才被激活,开始各自的周期性探测。
    Start Liveness / Readiness\text{Start Liveness / Readiness}

探针配置参数——探测仪表的旋钮

管家的健康检测仪上有四个旋钮,决定了“什么时候开始查、隔多久查一次、一次等多久、连续几次算出事”。这四个旋钮对应探针配置里的四个字段,它们是探针灵敏度的全部秘密。

第一个旋钮 initialDelaySeconds:容器启动后先等多久再开始第一次探测,相当于管家站在门口先听半分钟动静再敲门。第二个旋钮 periodSeconds:两次探测的间隔时间,管家每隔 N 秒来敲一次门。第三个旋钮 timeoutSeconds:单次探测最多等多久,敲门后 5 秒内没有应门就算这一次失败。第四个旋钮 failureThreshold:连续失败多少次才触发决策(重启或摘除),管家连敲 3 次没回应才认定出事了。

旋钮调太紧(周期太短、阈值太小),管家会草木皆兵,住客打个喷嚏就被清房;旋钮调太松,住客真的昏倒在屋里也没人发现。生产环境的调优,就是在“反应速度”和“误伤概率”之间找到微妙的平衡。

Tdetect=initialDelaySeconds+failureThreshold×periodSecondsT_{\text{detect}} = \text{initialDelaySeconds} + \text{failureThreshold} \times \text{periodSeconds}
这个公式估算“从容器启动到发现故障”所需的最短时间:首次延迟加上连续失败累计的周期数,帮你评估故障恢复的响应速度。
  1. T_detect从容器启动到系统判定故障并采取动作所经历的总耗时。
    TdetectT_{\text{detect}}
  2. initialDelaySeconds容器启动后,探针进入“静默观察期”的时长。
    initialDelaySeconds\text{initialDelaySeconds}
  3. failureThreshold × periodSeconds连续失败 failureThreshold 次、每次间隔 periodSeconds,累计出的总失败时长。
    failureThreshold×periodSeconds\text{failureThreshold} \times \text{periodSeconds}
  4. 公式求和启动后先等首次延迟,再经历连续失败窗口,两者叠加得到最早可感知故障的时刻。
    Tdetect=initialDelaySeconds+failureThreshold×periodSecondsT_{\text{detect}} = \text{initialDelaySeconds} + \text{failureThreshold} \times \text{periodSeconds}

探针实现方式——管家用哪种敲门法

管家检查住客状态有三种手段:敲门问话(Exec)、按门铃听回应(TCP)、透过门缝看指示灯(HTTP)。三种手段对应三种探针 handler,各有各的适用场景。

HTTP 探针向容器暴露的 URL 发起 GET 请求,如果响应状态码落在 200 到 399 之间就判定健康——这是最常用也最贴近“业务感知”的方式,前提是应用必须实现健康检查端点。TCP 探针尝试与指定端口建立 TCP 连接,连接成功即视为健康,适合没有 HTTP 接口的服务器(数据库、消息队列)。Exec 探针在容器内执行一条命令,命令退出码为 0 则健康,适合无法开端口、只能在进程内部自检的场景。

选哪种敲门方式,取决于门上装了什么“应答器”。有 HTTP 服务就用 HTTP,只有端口就用 TCP,啥端口都没有就塞一条自检命令进容器。选对方式,管家的每一次敲门才有意义。

HTTP Success:200≤code<400;TCP Success:connect OK;Exec Success:exit=0\text{HTTP Success}: 200 \le \text{code} < 400; \quad \text{TCP Success}: \text{connect OK}; \quad \text{Exec Success}: \text{exit} = 0
三种探针的判健康标准各不相同:HTTP 看状态码区间、TCP 看连接成败、Exec 看命令行退出码,共同点是“成功条件必须明确而保守”。
  1. HTTP SuccessHTTP 探针判定成功的条件是响应状态码落在 200 到 399 区间,400 及以上视为失败。
    200≤code<400200 \le \text{code} < 400
  2. TCP SuccessTCP 探针只要成功完成连接建立(三次握手)即判定健康。
    TCP connect=OK\text{TCP connect} = \text{OK}
  3. Exec SuccessExec 探针在容器内执行命令,退出码为 0 视为健康,非零视为失败。
    exit code=0\text{exit code} = 0

AI 应用场景

滚动发布中的流量无损切换

阶段:模型服务部署与版本发布

解决的问题:传统发布方式先删旧 Pod 再建新 Pod,新服务尚未就绪就被 Service 转发流量,用户请求大面积 5xx。Readiness 探针让新 Pod“准备好才接客”,所有新 Pod 就绪后旧 Pod 才摘除,实现零流量损失的滚动发布。

具体案例:某 AI 推理服务由 10 个副本组成,发布新版本时,新 Pod 的 Readiness 探针持续请求 /healthz,只有模型加载完成且能正常推理时才返回 200。流量随就绪状态逐步切换,发布期间错误率保持为 0。

AI 推理服务冷启动保护

阶段:模型加载与进程初始化

解决的问题:大模型加载权重需要 2-5 分钟,若只配置 Liveness 探针,启动阶段就会因探测超时被反复重启,容器永远无法进入 Running 就绪态。Startup 探针为“慢性子”应用提供了启动缓冲期。

具体案例:一个 GPU 推理服务加载 7B 参数模型平均耗时 180 秒,工程师配置了 Startup 探针(periodSeconds=10,failureThreshold=30),启动期间由它单独守护;模型加载完成后 Liveness 自动接管,服务稳定运行数月无重启。

长连接服务死锁自愈

阶段:长时间运行的在线推理与训练服务

解决的问题:进程不退出但不再响应请求(死锁、协程泄漏、内存压力下的假死),人工介入成本高、恢复慢。Liveness 探针周期性探测,连续失败自动重启容器,把故障恢复时间从“人发现”缩短到“机器发现”。

具体案例:在线推荐系统的一个 worker 节点在内存压力下进入死锁,Liveness 探针请求 /live 超时 5 秒无响应,连续 3 次失败后触发容器重启,服务在 1 分钟内自动恢复,避免了整夜的人工值班排查。

Python 演示

python71 行
"""Simulate how startup/liveness/readiness probes collaborate in a Pod.""" import randomimport time  class Probe:    """A simplified probe: runs every period ticks, counts consecutive failures."""     def __init__(self, name, period, threshold):        self.name = name        self.period = period        self.threshold = threshold        self.failed_count = 0        self.tick = 0     def run_check(self):        """Return 'success', 'failure', 'pending' or 'idle'."""        self.tick += 1        if self.tick % self.period != 0:            return "idle"        time.sleep(0.01)        ok = random.random() > 0.3        if ok:            self.failed_count = 0            return "success"        self.failed_count += 1        if self.failed_count >= self.threshold:            self.failed_count = 0            return "failure"        return "pending"  def simulate():    startup = Probe("startup", 1, 3)    liveness = Probe("liveness", 2, 3)    readiness = Probe("readiness", 2, 2)    started = False    ready = False     for t in range(1, 41):        if not started:            result = startup.run_check()            if result == "failure":                print("t={}: startup failed, container restarted".format(t))                return            if result == "success":                started = True                print("t={}: startup ok, liveness/readiness begin".format(t))            continue         if liveness.run_check() == "failure":            print("t={}: liveness failed, container restarted".format(t))            started = False            ready = False            continue         result = readiness.run_check()        if result == "success" and not ready:            ready = True            print("t={}: readiness ok, joined endpoints".format(t))        elif result == "failure" and ready:            ready = False            print("t={}: readiness lost, removed from endpoints".format(t))     print("done: started={}, ready={}".format(started, ready))  if __name__ == "__main__":    random.seed(2024)    simulate()
目的:用 Python 模拟 Kubernetes 中 Startup、Liveness、Readiness 三种探针的协作调度,展示“启动探针先行、存活保命、就绪控流量”的完整逻辑。
  1. class Probe:定义探针类,把三种探针的公共行为(周期、失败计数、阈值)统一封装。
  2. self.failed_count = 0记录连续失败次数,对应 failureThreshold 的累计机制。
  3. if self.tick % self.period != 0: return "idle"按 periodSeconds 节流探测频率,不到周期不探测。
  4. if self.failed_count >= self.threshold: return "failure"达到阈值才返回失败,模拟“连续失败才触发动作”。
  5. if not started: result = startup.run_check()Startup 探针优先运行,成功前 Liveness/Readiness 一律不启动。
  6. if liveness.run_check() == "failure":存活探测失败后模拟容器重启,重新回到启动阶段。
  7. readiness.run_check()就绪探针控制 Pod 是否加入端点列表,失败时摘除、恢复时加回。

常见误区

误区我让 Readiness 探针连着失败了好几次,以为 Pod 会像 Liveness 一样被自动重启,结果发现容器根本没重启,只是 Service 里暂时没有它了。

正解Readiness 只管“流量开关”,连续失败只把 Pod 从 Endpoints 中摘除,容器进程依旧运行;只有 Liveness 探针失败达到阈值才会触发重启。两者职责不同:一个管“要不要把访客带来”,一个管“住客还活不活着”。

为何常见:初学者看到两种探针配置结构相似、失败行为都带 threshold,容易把“摘除流量”和“重启容器”混为一谈。

误区我觉得探针检查越频繁越能早发现问题,于是把 periodSeconds 设成 1 秒,甚至同时配三个探针每秒各查一次,结果服务 CPU 升高、请求变慢。

正解探测本身会消耗应用资源(HTTP 请求、TCP 连接、命令执行),过高的探测频率会给应用带来额外压力,还可能在 GC 暂停、突发流量时造成瞬时超时误判。合理做法是 periodSeconds 取 5-15 秒区间,用 threshold 容忍瞬时抖动。

为何常见:直觉认为“检查越勤越可靠”,却忽略了探针是外部侵入式操作,不是一个零成本的传感器。

误区我认为 Liveness 探针只要有一次探测失败,kubelet 就会立刻把容器杀掉重启,所以配置里连 threshold 都不看。

正解探针采用“连续失败计数”设计,默认要连续失败 3 次(failureThreshold=3)才会重启容器。单次失败只会让计数加一,下一次成功立即清零。这个缓冲机制是为了抵抗网络抖动、GC 暂停、瞬时高延迟等“假死”干扰。

为何常见:把探针想象成“单次体检”,忽略了它本质上是一个带阈值的“滑窗计数器”。

误区我觉得配置了 Startup 探针只是多一道检查,Liveness 和 Readiness 照常从容器启动那一刻就开始探测。

正解Kubernetes 规定只要配置了 Startup 探针,Liveness 与 Readiness 会进入“待命”状态,直到 Startup 探测成功才被激活。这是防止慢启动容器在初始化期间被 Liveness 误杀的关键机制,时序上是强依赖。

为何常见:不了解探针之间存在时序依赖,以为它们是从容器启动起就并行工作的“三兄弟”。

误区我为了让服务“更健康”,把 Liveness 探测路径写成访问数据库和下游接口,认为只要依赖不通就重启容器,服务就能恢复。

正解Liveness 只应反映容器自身是否死锁或失活,外部依赖(数据库、下游服务)的抖动会让 Liveness 频繁失败,导致容器被反复误杀。更糟的是,依赖恢复后又会触发“雪崩式重启”。外部依赖的健康检查应该交给 Readiness 探针,让流量暂时摘除而不是杀掉容器。

为何常见:把“业务是否健康”和“容器是否存活”两个层面混淆,以为重启能解决一切问题,忽略了重启的代价和连锁风险。

面试题

Q1. Pod 生命周期阶段中,容器已成功创建并正在运行、但尚未就绪时,Pod 处于哪个阶段?

单选题 · easy

  • A.Running 容器运行中阶段← 正确答案
  • B.Pending 等待调度阶段
  • C.Succeeded 成功结束阶段
  • D.Failed 失败终止阶段

答案:A。Running 阶段表示 Pod 已绑定节点、容器已创建且至少一个仍在运行,但不要求容器已经 Ready(就绪)。Pending 是容器尚未全部创建的等待期;Succeeded 和 Failed 都是终态,分别代表正常退出和异常失败。

Q2. 下列哪种探针决定 Pod 是否被添加到 Service 的端点列表中?

单选题 · easy

  • A.Liveness 存活探针检查
  • B.Startup 启动探针检查
  • C.Readiness 就绪探针检查← 正确答案
  • D.Init 初始化探针检查

答案:C。Readiness 探针负责“流量开关”——探测失败时立即把 Pod 从 Endpoints 摘除,恢复后自动加回。Liveness 只管容器是否存活、是否重启;Startup 管慢启动应用的保护期;Init 容器不是探针类型。

Q3. 探针要满足什么条件才会触发容器重启或端点摘除?

单选题 · mid

  • A.只要失败一次就触发
  • B.随机延迟后自动触发
  • C.无论失败多少次都不触发
  • D.连续失败达到阈值触发← 正确答案

答案:D。探针使用“连续失败累计”机制,只有失败次数达到 failureThreshold(默认 3)才触发后续动作。单次失败只是计数加一,成功后清零,这样的缓冲设计是为了抵抗 GC 暂停、网络抖动等瞬时干扰,避免误判。

Q4. 一个启动耗时 120 秒的应用,Liveness 配置 initialDelaySeconds=10、periodSeconds=10,会发生什么?

单选题 · mid

  • A.应用能够正常完成启动
  • B.启动期间被误杀并反复重启← 正确答案
  • C.探针自动跳过等待期
  • D.容器被标记为已终止

答案:B。Liveness 在启动 10 秒后就开始探测,而应用要 120 秒才有响应,期间探测全部超时、连续失败累计到阈值,kubelet 会反复重启容器,形成“永远起不来”的循环。正确做法是增大 initialDelay 或配置 Startup 探针提供启动保护期。

Q5. Startup 探针探测成功后,接下来会发生什么?

单选题 · mid

  • A.存活探针与就绪探针开始工作← 正确答案
  • B.仅存活探针开始工作
  • C.仅就绪探针开始工作
  • D.所有探针停止工作

答案:A。Kubernetes 规定配置了 Startup 探针后,Liveness 和 Readiness 都会待命,直到 Startup 成功才被激活。三者随后各自按周期工作,共同守护容器。如果 Startup 失败达到阈值,容器同样会被重启。

Q6. HTTP 探针判定健康成功的条件是什么?

单选题 · easy

  • A.只有响应码是 200 才成功
  • B.响应码 400 到 499 之间
  • C.响应码 200 到 399 之间← 正确答案
  • D.响应码 500 以上算成功

答案:C。HTTP 探针把状态码在 200 到 399 之间的响应视为成功,不需要严格等于 200。400 及以上会被视为失败。这个宽松区间是为了兼容 301/302 跳转、304 缓存等“虽非 200 但服务正常”的场景。

Q7. 容器收到 SIGTERM 后,在 gracePeriodSeconds 宽限期内没有退出,Kubernetes 会怎么做?

单选题 · hard

  • A.继续无限期等待容器退出
  • B.发送 SIGKILL 强制终止进程← 正确答案
  • C.立即将 Pod 标记为成功
  • D.自动重启该容器进程

答案:B。优雅终止的流程是“先礼后兵”:kubelet 先发 SIGTERM 让应用收拾现场(保存状态、关闭连接),默认宽限期 30 秒;超时未退出则发送 SIGKILL 强制杀死,防止 Pod 永远卡在 Terminating 状态。如果直接无限期等待,资源无法释放,集群会被卡死的 Pod 塞满。

Q8. 以下哪些是 Kubernetes Pod 生命周期中的阶段状态?

多选题 · mid

  • A.Pending 等待调度阶段← 正确答案
  • B.Running 容器正在运行← 正确答案
  • C.Succeeded 已经正常完成← 正确答案
  • D.Stopped 已经被停止

答案:ABC。Pod 的 phase 只有五种取值:Pending、Running、Succeeded、Failed、Unknown。Stopped 不是官方阶段;“已完成”在 Pod 层面对应 Succeeded,在容器层面对应 Terminated 状态,但不能称作 Stopped。

Q9. 以下哪些是 Kubernetes 探针支持的实现机制?

多选题 · mid

  • A.HTTP GET 请求探测← 正确答案
  • B.TCP Socket 连接探测← 正确答案
  • C.Exec 执行宿主机命令
  • D.Syslog 日志扫描探测

答案:AB。探针 handler 有三种:HTTP GET(状态码 200-399 判成功)、TCP Socket(连接成功判健康)、Exec 命令。注意 Exec 是在容器内执行命令,不是宿主机;Syslog 日志扫描不是探针机制。选择依据是应用是否暴露 HTTP 端口、是否有可连端口、是否需要内部自检。

Q10. 关于探针配置参数,以下说法哪些是正确的?

多选题 · hard

  • A.initialDelay 决定启动后延迟多久开始探测← 正确答案
  • B.periodSeconds 决定两次探测的时间间隔← 正确答案
  • C.timeoutSeconds 决定探测的总次数上限
  • D.failureThreshold 是成功所需的次数阈值

答案:AB。initialDelaySeconds 是容器启动后等待多久才开始首次探测;periodSeconds 是探测周期间隔;timeoutSeconds 是单次探测的超时上限,不是总次数;failureThreshold 是“连续失败多少次触发动作”的失败阈值,不是成功阈值。C 和 D 把超时和阈值的作用张冠李戴了。