怎么使用Pod的liveness和readiness与startupProbe

本文详细介绍了如何配置Kubernetes Pod的liveness、readiness和startup探针,以确保Pod的健康运行。livenessProbe用于在容器卡顿时重启,readinessProbe确保Pod准备好接收流量,而startupProbe则适用于处理慢启动的容器。正确配置这三种探针可以避免级联故障,提高服务的稳定性和可用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


怎么配置Pod的liveness和readiness与startup探针


当你使用kubernetes的时候,有没有遇到过Pod在启动后一会就挂掉然后又重新启动这样的恶性循环?你有没有想过kubernetes是如何检测pod是否还存活?虽然容器已经启动,但是kubernetes如何知道容器的进程是否准备好对外提供服务了呢?让我们通过kubernetes官网的这篇文章Configure Liveness and Readiness Probes,来一探究竟。

本文将展示如何配置容器的存活和可读性探针。

Kubelet使用liveness probe(存活探针)来确定何时重启容器。例如,当应用程序处于运行状态但无法做进一步操作,liveness探针将捕获到deadlock,重启处于该状态下的容器,使应用程序在存在bug的情况下依然能够继续运行下去(谁的程序还没几个bug呢)。

Kubelet使用readiness probe(就绪探针)来确定容器是否已经就绪可以接受流量。只有当Pod中的容器都处于就绪状态时kubelet才会认定该Pod处于就绪状态。该信号的作用是控制哪些Pod应该作为service的后端。如果Pod处于非就绪状态,那么它们将会被从service的load balancer中移除。

Kubelet使用startup probe(启动探针)来确定容器是否已经启动。有时候,会有一些现有的应用程序在启动时需要较多的初始化时间。要不影响对引起探测死锁的快速响应,在这种情况下,设置存活探测参数是要技巧的。技巧就是使用一个命令来设置启动探测,针对HTTP 或者 TCP 检测,可以通过设置 failureThreshold * periodSeconds 参数来保证有足够长的时间应对糟糕情况下的启动时间。

定义 liveness命令


许多长时间运行的应用程序最终会转换到broken状态,除非重新启动,否则无法恢复。Kubernetes提供了liveness probe来检测和补救这种情况。在本次练习将基于 gcr.io/google_containers/busybox镜像创建运行一个容器的Pod。以下是Pod的配置文件exec-liveness.yaml:

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-exec
spec:
  containers:
  - name: liveness
    args:
    - /bin/sh
    - -c
    - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
    image: gcr.io/google_containers/busybox
    livenessProbe:
      exec:
        command:
        - cat
        - /tmp/healthy
      initialDelaySeconds: 5
      periodSeconds: 5

该配置文件给Pod配置了一个容器。periodSeconds 规定kubelet要每隔5秒执行一次liveness probe。initialDelaySeconds 告诉kubelet在第一次执行probe之前要的等待5秒钟。探针检测命令是在容器中执行 cat /tmp/healthy 命令。如果命令执行成功,将返回0,kubelet就会认为该容器是活着的并且很健康。如果返回非0值,kubelet就会杀掉这个容器并重启它。容器启动时,执行该命令:

/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"

在容器生命的最初30秒内有一个 /tmp/healthy 文件,在这30秒内 cat /tmp/healthy命令会返回一个成功的返回码。30秒后, cat /tmp/healthy 将返回失败的返回码。创建Pod:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/exec-liveness.yaml

在30秒内,查看Pod的event:

kubectl describe pod liveness-exec

结果显示没有失败的liveness probe:

FirstSeen    LastSeen    Count   From            SubobjectPath           Type        Reason      Message
--------- --------    -----   ----            -------------           --------    ------      -------
24s       24s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "gcr.io/google_containers/busybox"
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "gcr.io/google_containers/busybox"
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s       23s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e

启动35秒后,再次查看pod的event:

kubectl describe pod liveness-exec

在最下面有一条信息显示liveness probe失败,容器被删掉并重新创建。

FirstSeen LastSeen    Count   From            SubobjectPath           Type        Reason      Message
--------- --------    -----   ----            -------------           --------    ------      -------
37s       37s     1   {default-scheduler }                    Normal      Scheduled   Successfully assigned liveness-exec to worker0
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulling     pulling image "gcr.io/google_containers/busybox"
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Pulled      Successfully pulled image "gcr.io/google_containers/busybox"
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Created     Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s       36s     1   {kubelet worker0}   spec.containers{liveness}   Normal      Started     Started container with docker id 86849c15382e
2s        2s      1   {kubelet worker0}   spec.containers{liveness}   Warning     Unhealthy   Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory

再等30秒,确认容器已经重启:

kubectl get pod liveness-exec

从输出结果来RESTARTS值加1了

NAME            READY     STATUS    RESTARTS   AGE
liveness-exec   1/1       Running   1          1m

定义一个liveness HTTP请求


我们还可以使用HTTP GET请求作为liveness probe。下面是一个基于gcr.io/google_containers/liveness镜像运行了一个容器的Pod的例子http-liveness.yaml:该配置文件只定义了一个容器,livenessProbe 指定kubelet需要每隔3秒执行一次liveness probe。initialDelaySeconds 指定kubelet在该执行第一次探测之前需要等待3秒钟。该探针将向容器中的server的8080端口发送一个HTTP GET请求。如果server的/healthz路径的handler返回一个成功的返回码,kubelet就会认定该容器是活着的并且很健康。如果返回失败的返回码,kubelet将杀掉该容器并重启它。任何大于200小于400的返回码都会认定是成功的返回码。其他返回码都会被认为是失败的返回码。最开始的10秒该容器是活着的, /healthz handler返回200的状态码。这之后将返回500的返回码。

http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
    duration := time.Now().Sub(started)
    if duration.Seconds() > 10 {
        w.WriteHeader(500)
        w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
    } else {
        w.WriteHeader(200)
        w.Write([]byte("ok"))
    }
})

容器启动3秒后,kubelet开始执行健康检查。第一次健康监测会成功,但是10秒后,健康检查将失败,kubelet将杀掉和重启容器。创建一个Pod来测试一下HTTP liveness检测:

kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/http-liveness.yaml

After 10 seconds, view Pod events to verify that liveness probes have failed and the Container has been restarted: 10秒后,查看Pod的event,确认liveness probe失败并重启了容器。

kubectl describe pod liveness-http

定义TCP liveness探针
第三种liveness probe使用TCP Socket。使用此配置,kubelet将尝试在指定端口上打开容器的套接字。如果可以建立连接,容器被认为是健康的,如果不能就认为是失败的。

apiVersion: v1
kind: Pod
metadata:
  name: goproxy
  labels:
    app: goproxy
spec:
  containers:
  - name: goproxy
    image: gcr.io/google_containers/goproxy:0.1
    ports:
    - containerPort: 8080
    readinessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 10
    livenessProbe:
      tcpSocket:
        port: 8080
      initialDelaySeconds: 15
      periodSeconds: 20

TCP检查的配置与HTTP检查非常相似。此示例同时使用了readiness和liveness probe。容器启动后5秒钟,kubelet将发送第一个readiness probe。这将尝试连接到端口8080上的goproxy容器。如果探测成功,则该pod将被标记为就绪。Kubelet将每隔10秒钟执行一次该检查。除了readiness probe之外,该配置还包括liveness probe。容器启动15秒后,kubelet将运行第一个liveness probe。就像readiness probe一样,这将尝试连接到goproxy容器上的8080端口。如果liveness probe失败,容器将重新启动。使用命名的端口,可以使用命名的ContainerPort作为HTTP或TCP liveness检查:

ports:
- name: liveness-port
  containerPort: 8080
  hostPort: 8080

livenessProbe:
  httpGet:
  path: /healthz
  port: 8080

定义readiness探针


有时,应用程序暂时无法对外部流量提供服务。例如,应用程序可能需要在启动期间加载大量数据或配置文件。在这种情况下,你不想杀死应用程序,但你也不想发送请求。Kubernetes提供了readiness probe来检测和减轻这些情况。Pod中的容器可以报告自己还没有准备,不能处理Kubernetes服务发送过来的流量。

Readiness probe的配置跟liveness probe很像。唯一的不同是使用 readinessProbe而不是livenessProbe。

readinessProbe:
  exec:
    command:
    - cat
    - /tmp/healthy
  initialDelaySeconds: 5
  periodSeconds: 5

Readinessprobe的HTTP和TCP的探测器配置跟liveness probe一样。Readiness和livenssprobe可以并行用于同一容器。使用两者可以确保流量无法到达未准备好的容器,并且容器在失败时重新启动。

定义startup探针


这是kubernetes1.16带来的新功能。Probes 允许 Kubernetes 监控应用程序的状态。可以使用livenessProbe定期检查应用程序是否还活着。一个示例容器定义了这个探测器:

  livenessProbe : httpGet: 
    path: /healthz 
    port: 8080
  failureThreshold: 3
  periodSeconds: 10

如果在 30 秒内失败 3 次,容器将重新启动。但是由于这个容器很慢,需要30多秒才能启动,所以探针会失败,容器会再次重启。这个新特性让你可以定义一个startupProbe在 pod 完成启动之前阻止所有其他探测的方法:

startupProbe: 
  httpGet: 
    path: /healthz 
    port: 8080
  failureThreshold: 30
  periodSeconds: 10

现在我们的慢速容器最多有 5 分钟(30 个检查 * 10 秒 = 300 秒)来完成它的启动。

配置Probe


Probe 中有很多精确和详细的配置,通过它们你能准确的控制liveness和readiness检查:

  • initialDelaySeconds:容器启动后第一次执行探测是需要等待多少秒。
  • periodSeconds:执行探测的频率。默认是10秒,最小1秒。
  • timeoutSeconds:探测超时时间。默认1秒,最小1秒。
  • successThreshold:探测失败后,最少连续探测成功多少次才被认定为成功。默认是1。对于liveness必须是1。最小值是1。
  • failureThreshold:探测成功后,最少连续探测失败多少次才被认定为失败。默认是3。最小值是1。

HTTP probe 可以给 httpGet设置其他配置项:

  • host:连接的主机名,默认连接到pod的IP。你可能想在http header中设置"Host"而不是使用IP。
  • scheme:连接使用的schema,默认HTTP。
  • path: 访问的HTTP server的path。
  • httpHeaders:自定义请求的header。HTTP运行重复的header。
  • port:访问的容器的端口名字或者端口号。端口号必须介于1和65535之间。
    对于HTTP探测器,kubelet向指定的路径和端口发送HTTP请求以执行检查。Kubelet将probe发送到容器的IP地址,除非地址被httpGet中的可选host字段覆盖。在大多数情况下,你不想设置主机字段。有一种情况下你可以设置它。假设容器在127.0.0.1上侦听,并且Pod的hostNetwork字段为true。然后,在httpGet下的host应该设置为127.0.0.1。如果你的pod依赖于虚拟主机,这可能是更常见的情况,你不应该用host,而是应该在httpHeaders中设置Host头。

我们应该怎么做?


  • 对于提供 HTTP 协议(REST 服务等)的微服务, 始终定义一个ReadinessProbe,用于检查的应用程序(Pod)是否已准备好接收流量。
  • 对于慢启动的应用,我们应该使用StartupProbe,来防止容器没有启动,就被LivenessProbe杀死了。
  • 如果服务是多端口的,请确保ReadinessProbe覆盖了所以的端口。例如:为readinessProbe使用“admin”或“management”端口(例如 9090)时,请确保端点仅在主要 HTTP 端口(例如 8080)准备好接受流量时才返回 success.
  • 使用httpGet对服务端口与路径(例如 /health)进行就绪探测。

我们不应该怎么做?


  • 不要依赖外部依赖项(如数据存储)进行就绪/探活检查,因为这可能会导致级联故障

    1. 假如10 个pod的服务,数据库使用Postgres,缓存使用redis:当你的探针的路径依赖于工作的redis连接时,如果出现redis/网络故障,则所有 10 个 Pod 都将“重启”——这通常会产生影响比它应该的更糟。因为服务还能到Postgres拿去数据。
    2. 服务最好不要与数据库做强依赖。
    3. 只探测自己内部的端口,不要去探测外部pod的端口。探测器不应依赖于同一集群中其他 Pod 的状态,以防止级联故障。
  • 需要明确知道使用 Liveness Probe 的原因,否则不要为 Pod 使用 Liveness Probe。

    • Liveness Probe 可以帮助恢复“卡住”的容器,但是当我们能控制我们的应用程序,出现意料之外的“卡住”进程和死锁之类的故障,更好的选择是从应用内部故意崩溃以恢复到已知良好状态。
    • 失败的 Liveness Probe 将导致容器重启,从而可能使与负载相关的错误的影响变得更糟:容器重启将导致停机(至少的应用程序的启动时间,例如 30s+),从而导致更多错误并为其他容器提供更多流量负载,导致更多失败的容器,等等
    • Liveness Probes 与外部依赖相结合是导致级联故障的最坏情况:单个环境的小问题将重新启动所有容器。
  • 如果使用 LivenessProbe,请不要为LivenessProbe和ReadinessProbe设置相同的规范

    • 可以使用具有相同运行状况检查但具有更高failureThreshold的 Liveness Probe (例如,在 3 次尝试后标记为未就绪,在 10 次尝试后将 Liveness Probe 标记为失败)
  • 不要使用“exec”探测器,它们存在导致僵尸进程的。因为我们写的应用进程很大一部分不会解决依附在主进程上的进程的

总结

为 Web 应用程序使用ReadinessProbe来决定 Pod 何时应接收流量
不正确使用Readiness/LivenessProbes可能导致可用性降低和级联故障
对于慢启动的应用,我们应该使用StartupProbe

参考:

https://jimmysong.io/kubernetes-handbook/guide/configure-liveness-readiness-probes.html
https://srcco.de/posts/kubernetes-liveness-probes-are-dangerous.html#id

<think>好的,我现在需要详细解释Kubernetes中的livenessProbereadinessProbe。首先,我得确认自己是否完全理解这两个概念,以及它们的区别用途。可能用户是刚开始接触Kubernetes的人,所以需要用简单明了的语言,同时结构清晰,逐步解释。 首先,我应该回忆一下Kubernetes中的探针(Probe)是什么。探针用于检测容器的状态,确保应用按预期运行。Kubernetes有三种探针:livenessProbe、readinessProbestartupProbe。不过用户只问了前两个,所以重点在它们。 接下来,我需要分别定义livenessProbereadinessProbe。LivenessProbe用于判断容器是否在运行,如果探测失败,k8s会重启容器。而readinessProbe检查容器是否准备好接收流量,失败的话,服务不会将请求转发到该容器。这是它们的核心区别。 然后,我需要详细说明两者的作用场景。比如,livenessProbe适用于检测死锁或长时间无响应的情况,而readinessProbe用于启动时需要较长时间准备,或者暂时无法处理请求的情况。比如,应用启动时要加载大量数据,这时readinessProbe可以延迟流量进入,直到准备就绪。 接下来是配置参数。两种探针的配置参数类似,比如initialDelaySeconds、periodSeconds、timeoutSeconds等。需要逐一解释这些参数的作用,以及如何影响探针的行为。 然后要介绍探测方式,即ExecAction、HTTPGetActionTCPSocketAction。比如,Exec执行命令,检查退出码;HTTPGet检查状态码;TCP检查端口是否开放。需要举例说明每种方式的适用场景。 还需要对比两者的区别,可能用户容易混淆它们。比如,livenessProbe失败会导致重启,而readinessProbe失败只是停止流量,但容器仍在运行。这部分需要明确强调,避免误解。 此外,应该提供配置示例,帮助用户理解如何在YAML文件中定义这两个探针。比如,给出一个Pod的配置片段,展示livenessProbe使用HTTP检查,readinessProbe使用Exec检查命令。 注意事项部分需要考虑,比如设置合理的initialDelay,避免过早开始探测;调整超时周期,防止误判;以及区分使用场景,避免混淆两者的用途。同时,可能提到过于频繁的探测会增加负载,或者不合理的阈值导致容器频繁重启或无法接收流量。 最后,总结两者的重要性,强调正确配置可以提升应用的可靠性稳定性。可能还要提到,在实际使用中需要根据应用特点调整参数,确保探针有效工作。 现在需要检查是否有遗漏点,比如startupProbe是否需要提及?用户没问,可能暂时不提。另外,是否需要提到探针失败后的具体行为,比如livenessProbe失败会重启容器,而readinessProbe只是从Service的Endpoints中移除?这点应该包括在内,以明确后果。 语法方面,确保行内公式用$...$,独立公式用$$...$$,但这个问题中可能数学公式较少,但如果有用到变量或参数,可能需要用格式。不过当前内容可能不需要数学公式,但用户给的示例中有提到变量等,所以需要留意。不过这里的问题是关于Kubernetes配置,可能不涉及数学表达式,但需要确认是否在回答中会有需要用到的地方。比如,参数名称如initialDelaySeconds等,不需要用LaTeX,但可能需要用代码块或引号标注。 不过根据用户的系统级指令,所有行内数学表达式必须用$...$,但这里可能更多是技术术语参数,所以可能需要用反引号包裹,比如`initialDelaySeconds`。但用户的中文回答里可能不需要LaTeX,除非涉及数学内容。可能用户只是希望正确使用代码格式,但根据用户的指令,可能需要检查是否有数学相关内容需要处理。不过当前问题可能不涉及,所以可能不需要使用LaTeX,但需要确保其他格式正确。 综上,我需要组织一个结构清晰的回答,分点解释livenessProbereadinessProbe,包括定义、作用、配置参数、探测方式、区别对比、配置示例注意事项。使用中文,确保步骤明确,帮助用户逐步理解。</think>### livenessProbe readinessProbe 详解 在 Kubernetes 中,`livenessProbe` `readinessProbe` 是两种**健康检查机制**,用于确保容器化应用按预期运行。它们的功能适用场景不同,但均通过周期性探测容器的状态来实现目标。 --- #### 一、核心概念区别 1. **`livenessProbe`(存活探针)** - **作用**:判断容器是否**正常运行**。若探测失败,Kubernetes 会**重启容器**。 - **适用场景**:检测应用死锁、长时间无响应等异常状态。 2. **`readinessProbe`(就绪探针)** - **作用**:判断容器是否**准备好接收流量**。若探测失败,容器会从 Service 的负载均衡池中**临时移除**(但不会重启)。 - **适用场景**:应用启动时需要初始化配置、加载数据,或临时过载无法处理请求时。 | 特性 | livenessProbe | readinessProbe | |---------------------|------------------------------|------------------------------| | **探测失败后果** | 重启容器 | 停止流量转发 | | **主要目标** | 确保容器存活 | 确保容器就绪 | | **典型使用场景** | 处理死锁、崩溃 | 启动延迟、临时不可用 | --- #### 二、配置参数详解 两种探针的配置参数相同,常用参数如下: ```yaml livenessProbe: httpGet: # 探测方式(HTTP/Exec/TCP) path: /healthz port: 8080 initialDelaySeconds: 10 # 容器启动后首次探测的延迟时间 periodSeconds: 5 # 探测间隔 timeoutSeconds: 1 # 单次探测超时时间 successThreshold: 1 # 连续成功次数标记为“成功” failureThreshold: 3 # 连续失败次数标记为“失败” ``` --- #### 三、探测方式 1. **HTTP GET 请求** 向容器内指定端口路径发送 HTTP 请求,若状态码为 `2xx` 或 `3xx` 则成功。 ```yaml httpGet: path: /health port: 80 ``` 2. **Exec 命令** 在容器内执行命令,若退出码为 `0` 则成功。 ```yaml exec: command: - sh - -c - "curl -f http://localhost/ready || exit 1" ``` 3. **TCP Socket 检测** 尝试容器的指定端口建立 TCP 连接,若连接成功则标记为就绪。 ```yaml tcpSocket: port: 3306 ``` --- #### 四、配置示例 ```yaml apiVersion: v1 kind: Pod metadata: name: my-app spec: containers: - name: web image: nginx ports: - containerPort: 80 livenessProbe: httpGet: path: /healthz port: 80 initialDelaySeconds: 15 periodSeconds: 20 readinessProbe: httpGet: path: /ready port: 80 initialDelaySeconds: 5 periodSeconds: 10 ``` --- #### 五、注意事项 1. **合理设置初始延迟(`initialDelaySeconds`)** 避免容器尚未启动完成就开始探测,导致误判。 2. **调整探测频率超时** - `periodSeconds` 过小会增加容器负载。 - `timeoutSeconds` 需根据应用响应时间调整。 3. **区分使用场景** - **`livenessProbe`** 应保守配置(避免频繁重启)。 - **`readinessProbe`** 需确保能真实反映服务能力。 --- #### 六、总结 - **`livenessProbe`** 是“保活机制”,确保异常容器自动恢复。 - **`readinessProbe`** 是“流量开关”,保证请求仅转发到就绪的容器。 - 正确配置两者可显著提升应用可靠性,避免因部分实例异常导致整体服务中断。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值