探究kubernetes 探针参数 periodSecondstimeoutSeconds

问题起源

kubernetes probes的配置中有两个容易混淆的参数,periodSecondstimeoutSeconds,其配置方式如下:

apiVersion: v1
kind: Pod
metadata:
name: darwin-app
spec:
containers:
- name: darwin-container
image: darwin-image
livenessProbe:
httpGet:
path: /darwin-path
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3

官方对这两个参数的解释如下:

  • periodSeconds: How often (in seconds) to perform the probe. Default to 10 seconds. The minimum value is 1.
  • timeoutSeconds: Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1.

意思是说periodSeconds表示执行探针的周期,而timeoutSeconds表示执行探针的超时时间。

网上有不少针对这两个参数的讨论(如下),其中涉及到一个问题,如果timeoutSeconds > periodSeconds 会怎么样?

  1. What is the role of timeoutSeconds in kubernetes liveness/readiness probes?
  2. Kubernetes Health Check: timeoutSeconds exceeds periodSeconds
  3. Does periodSeconds in Kubernetes probe configuration count from the last probe time or the last response/failure time?

其中在上面的第3篇中对timeoutSeconds>periodSeconds的情况有如下描述,即在这种情况下,如果探针超时,则探针周期等于timeoutSeconds。那么这种说法是否正确呢?

If you had the opposite (timeoutSeconds=10, periodSeconds=5), then the probes would look as follows:

0s: liveness probe initiated
10s: liveness probe times out
10s: liveness probe initiated again

源码探究

鉴于网上众说纷纭,我们通过源码来一探究竟。

kubernetes的探针机制是由kubelet执行的,目前支持execgrpchttpGettcpSocket这4种探针方式。

探针的代码逻辑并不复杂,以v1.30.2的代码为例,其入口函数如下,可以看到它会启动一个周期为w.spec.PeriodSeconds(即探针中定义的periodSeconds)定时器,周期性地执行探针。

// run periodically probes the container.
func (w *worker) run() {
ctx := context.Background()
probeTickerPeriod := time.Duration(w.spec.PeriodSeconds) * time.Second
... probeTicker := time.NewTicker(probeTickerPeriod)
...
probeLoop:
for w.doProbe(ctx) {
// Wait for next probe tick.
select {
case <-w.stopCh:
break probeLoop
case <-probeTicker.C:
case <-w.manualTriggerCh:
// continue
}
}
}

现在已经找到periodSeconds的用途,下一步需要找到timeoutSeconds

  1. 首先进入doProbe函数,它调用了w.probeManager.prober.probe

    // doProbe probes the container once and records the result.
    // Returns whether the worker should continue.
    func (w *worker) doProbe(ctx context.Context) (keepGoing bool) {
    ...
    // Note, exec probe does NOT have access to pod environment variables or downward API
    result, err := w.probeManager.prober.probe(ctx, w.probeType, w.pod, status, w.container, w.containerID)
    if err != nil {
    // Prober error, throw away the result.
    return true
    }
    ...
    }
  2. 下面的probe函数用于执行一个特定的探针。需要注意的是,它调用了pb.runProbeWithRetries,其中maxProbeRetries值为3,说明在一个周期(periodSeconds)中最多可以执行3次探针命令

    // probe probes the container.
    func (pb *prober) probe(ctx context.Context, probeType probeType, pod *v1.Pod, status v1.PodStatus, container v1.Container, containerID kubecontainer.ContainerID) (results.Result, error) {
    var probeSpec *v1.Probe
    switch probeType {
    case readiness:
    probeSpec = container.ReadinessProbe
    case liveness:
    probeSpec = container.LivenessProbe
    case startup:
    probeSpec = container.StartupProbe
    default:
    return results.Failure, fmt.Errorf("unknown probe type: %q", probeType)
    }
    ...
    result, output, err := pb.runProbeWithRetries(ctx, probeType, probeSpec, pod, status, container, containerID, maxProbeRetries)
    ...
    }
  3. runProbeWithRetries的注释说明,可能会执行多次探针,直到探针返回成功或全部尝试失败:

    // runProbeWithRetries tries to probe the container in a finite loop, it returns the last result
    // if it never succeeds.
    func (pb *prober) runProbeWithRetries(ctx context.Context, probeType probeType, p *v1.Probe, pod *v1.Pod, status v1.PodStatus, container v1.Container, containerID kubecontainer.ContainerID, retries int) (probe.Result, string, error) {
    ...
    for i := 0; i < retries; i++ {
    result, output, err = pb.runProbe(ctx, probeType, p, pod, status, container, containerID)
    ...
    }
    ...
    }
  4. runProbe函数中,最终找到了timeoutSeconds对应的参数p.TimeoutSeconds,其作为各个探针命令的超时参数,如在httpGet类型的探针中,它作为了httpClient的请求超时时间:


    func (pb *prober) runProbe(ctx context.Context, probeType probeType, p *v1.Probe, pod *v1.Pod, status v1.PodStatus, container v1.Container, containerID kubecontainer.ContainerID) (probe.Result, string, error) { timeout := time.Duration(p.TimeoutSeconds) * time.Second if p.Exec != nil {
    command := kubecontainer.ExpandContainerCommandOnlyStatic(p.Exec.Command, container.Env)
    return pb.exec.Probe(pb.newExecInContainer(ctx, container, containerID, command, timeout))
    } if p.HTTPGet != nil {
    req, err := httpprobe.NewRequestForHTTPGetAction(p.HTTPGet, &container, status.PodIP, "probe")
    ...
    return pb.http.Probe(req, timeout)
    } if p.TCPSocket != nil {
    port, err := probe.ResolveContainerPort(p.TCPSocket.Port, &container)
    ...
    host := p.TCPSocket.Host
    if host == "" {
    host = status.PodIP
    }
    return pb.tcp.Probe(host, port, timeout)
    } if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.GRPCContainerProbe) && p.GRPC != nil {
    host := status.PodIP
    service := ""
    if p.GRPC.Service != nil {
    service = *p.GRPC.Service
    }
    return pb.grpc.Probe(host, service, int(p.GRPC.Port), timeout)
    }
    ...
    }

至此我们可以拼接出periodSecondstimeoutSeconds的关系,其逻辑关系与如下代码类似。

probeTicker := time.NewTicker(periodSeconds)

for {
select {
case <-probeTicker.C:
for i := 0; i < 3; i++ {
if ok:=probe(timeoutSeconds);ok{
return
}
}
}

总结

  • periodSeconds用于启动一个周期性调用探针命令的定时器,而timeoutSeconds作为探针命令的超时参数
  • timeoutSecondsperiodSeconds之间并没有明确的关系。如果timeoutSeconds=10s,periodSeconds=5s,则本次探针周期可能为[5s, 30s)之内的任意值,并不是该文中说的periodSeconds=timeoutSeconds(由于本文写于3年前,经查阅v1.19.10版本代码,逻辑上与现有版本代码相同。)
  • 由于健康检查的逻辑大部分都不会很复杂,如检查某个文件是否存在,检查服务的/hleathz http endpoint是否可以访问等,因此建议将timeoutSeconds设置为一个小于periodSeconds的合理的值。

failureThreshold/successThresholdmaxProbeRetries的关系

  • maxProbeRetries用于定义一次探针周期内探针命令执行的最大尝试次数;
  • 如果在一个探针周期内,探针命令返回成功,则successThreshold 加1,反之failureThreshold加1;

探究kubernetes 探针参数periodSeconds和timeoutSeconds的更多相关文章

  1. Kubernetes探针原理详解

    前言: 分布式系统和微服务体系结构的挑战之一是自动检测不正常的应用程序,并将请求(request)重新路由到其他可用系统,恢复损坏的组件.健康检查是应对该挑战的一种可靠方法.使用 Kubernetes ...

  2. Python装饰器探究——装饰器参数

    Table of Contents 1. 探究装饰器参数 1.1. 编写传参的装饰器 1.2. 理解传参的装饰器 1.3. 传参和不传参的兼容 2. 参考资料 探究装饰器参数 编写传参的装饰器 通常我 ...

  3. Kubernetes探针踩坑记

    1. 荒腔走板 最近一两个月生产K8s集群频繁出现短时503 Service Temporarily Unavailable,还不能主动复现,相当郁闷,压力山大. HTTP 5xx响应状态码用于定义服 ...

  4. 【七】Kubernetes 探针介绍 - 存活、就绪探针案例测试

    一.探针概述 探针是有 kubelet 对容器执行的定期诊断,并不是由 Master 节点发起的探测,而是由每一个 Node 所在的 kubelet 进行探测,这样可以减轻 Master 节点系统负载 ...

  5. kubernetes容器探针检测

    系列目录 kubernetes提供了livenessProbe(可用性探针)和readinessProbe(就绪性探针)对容器的健康性进行检测,当然这仅仅简单的关于可用性方面的探测,实际上我们不仅仅要 ...

  6. Kubernetes 存活、就绪探针

    在设计关键任务.高可用应用程序时,弹性是要考虑的最重要因素之一. 当应用程序可以快速从故障中恢复时,它便具有弹性. 云原生应用程序通常设计为使用微服务架构,其中每个组件都位于容器中.为了确保Kuber ...

  7. 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器?

    探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 探针配置失误,线上容器应用异常死锁后,kubernetes集群未及时响应自愈重启容器? 线上多个服务应用陷入了死 ...

  8. Kubernetes YAML 文件全字段详解

    Kubernetes YAML 文件全字段详解 Deployment yaml 其中主要参数都在podTemplate 中,DaemonSet StatefulSet 中的pod部分一样. apiVe ...

  9. Kubernetes学习笔记_尚硅谷

    https://www.bilibili.com/video/BV1w4411y7Go?p=1 一.K8s介绍 k8s是一个编排容器的工具,其实也是管理应用的全生命周期的一个工具,从创建应用,应用的部 ...

  10. Kubernetes Deployment 最佳实践

    零.示例 首先给出一个 Deployment+HPA+ PodDisruptionBudget 的完整 demo,后面再详细介绍其中的每一个部分: apiVersion: apps/v1 kind: ...

随机推荐

  1. 使用自定义lua解析管理器调用lua脚本中的table

    [5] 使用自定义lua解析管理器调用table 访问数组类型的table CallLuaEntrance测试脚本中内容: //------------------------------------ ...

  2. 智能勘探 | AIRIOT智慧油田管理解决方案

      石油勘探和开采地处偏远地区,涉及面广且生产规模大.特殊的作业环境下,使得工作人员作业条件艰苦,仅靠人工值守难度很大,不可避免的遇到一系列硬核挑战: 1.设备维护难度较高: 2.采油厂分布地域广.分 ...

  3. 基于FPGA的数字钟设计---第三版

    欢迎各位朋友关注"郝旭帅电子设计团队",本篇为各位朋友介绍基于FPGA的数字钟设计---第三版. 功能说明: 1. 在数码管上面显示时分秒(共计六个数码管,前两个显示小时:中间两个 ...

  4. 分布式任务调度内的 MySQL 分页查询优化

    作者:vivo 互联网数据库团队- Qiu Xinbo 本文主要通过图示介绍了用主键进行分片查询的过程,介绍了主键分页查询存在SQL性能问题,如何去创建高效的索引去优化主键分页查询的SQL性能问题.对 ...

  5. 三元运算符 JAVA12

    Java 提供了一个特别的三元运算符(也叫三目运算符) 表示:条件运算符的符号表示为"? :",使用该运算符时需要有三个操作数,因此称其为三目运算符. 举例一 int x,y,z; ...

  6. 论elasticsearch在Windows环境的安装

    前置需求 一台电脑(我用的是Windows),有网 第一步:下载并安装 去java官网下载开发版java(考虑到可能有小白,我暂且这么说) java官网下载链接:https://www.oracle. ...

  7. OpenTelemetry agent 对 Spring Boot 应用的影响:一次 SPI 失效的案例

    背景 前段时间公司领导让我排查一个关于在 JDK21 环境中使用 Spring Boot 配合一个 JDK18 新增的一个 SPI(java.net.spi.InetAddressResolverPr ...

  8. scala的基本语法

    区分常量和变量 常量 变量 写一行代码,写多行代码,终端代码 数据类型 byte char short int long float double boolean  数据类型与java相似,但与jav ...

  9. windows报错

    如果说你dns没有权威的话1.先去long.com上面右键属性把"区域传送给所有服务器打勾"2.右键属性,在名称分析器中,输入要添加为辅助dns的服务器的ip显示解析成功就可以了

  10. Mysql 使用 group by 不对 null 做分组

    在项目开发查询数据需要将相同的数据做合并处理,但是字段为null,不做合并. 创建表以及添加数据 create table t_student( `id` int not null primary k ...