详解k8s中的liveness和readiness的原理和区别

liveness与readiness的探针工作方式源码解析

liveness和readiness作为k8s的探针,可以对应用进行健康探测。
二者支持的探测方式相同。主要的探测方式支持http探测,执行命令探测,以及tcp探测。
探测均是由kubelet执行。

执行命令探测

func (pb *prober) runProbe(p *v1.Probe, pod *v1.Pod, status v1.PodStatus, container v1.Container, containerID kubecontainer.ContainerID) (probe.Result, string, error) {
.....
        command := kubecontainer.ExpandContainerCommandOnlyStatic(p.Exec.Command, container.Env)
        return pb.exec.Probe(pb.newExecInContainer(container, containerID, command, timeout))
......

func (pb *prober) newExecInContainer(container v1.Container, containerID kubecontainer.ContainerID, cmd []string, timeout time.Duration) exec.Cmd {
    return execInContainer{func() ([]byte, error) {
        return pb.runner.RunInContainer(containerID, cmd, timeout)
    }}
}

......
func (m *kubeGenericRuntimeManager) RunInContainer(id kubecontainer.ContainerID, cmd []string, timeout time.Duration) ([]byte, error) {
    stdout, stderr, err := m.runtimeService.ExecSync(id.ID, cmd, 0)
    return append(stdout, stderr...), err
}

由kubelet,通过CRI接口的ExecSync接口,在对应容器内执行拼装好的cmd命令。获取返回值。

func (pr execProber) Probe(e exec.Cmd) (probe.Result, string, error) {
    data, err := e.CombinedOutput()
    glog.V(4).Infof("Exec probe response: %q", string(data))
    if err != nil {
        exit, ok := err.(exec.ExitError)
        if ok {
            if exit.ExitStatus() == 0 {
                return probe.Success, string(data), nil
            } else {
                return probe.Failure, string(data), nil
            }
        }
        return probe.Unknown, "", err
    }
    return probe.Success, string(data), nil
}

kubelet是根据执行命令的退出码来决定是否探测成功。当执行命令的退出码为0时,认为执行成功,否则为执行失败。如果执行超时,则状态为Unknown。

http探测

func DoHTTPProbe(url *url.URL, headers http.Header, client HTTPGetInterface) (probe.Result, string, error) {
    req, err := http.NewRequest("GET", url.String(), nil)
    ......
    if res.StatusCode >= http.StatusOK && res.StatusCode < http.StatusBadRequest {
        glog.V(4).Infof("Probe succeeded for %s, Response: %v", url.String(), *res)
        return probe.Success, body, nil
    }
    ......

http探测是通过kubelet请求容器的指定url,并根据response来进行判断。
当返回的状态码在200到400(不含400)之间时,也就是状态码为2xx和3xx是,认为探测成功。否则认为失败。

tcp探测

func DoTCPProbe(addr string, timeout time.Duration) (probe.Result, string, error) {
    conn, err := net.DialTimeout("tcp", addr, timeout)
    if err != nil {
        // Convert errors to failures to handle timeouts.
        return probe.Failure, err.Error(), nil
    }
    err = conn.Close()
    if err != nil {
        glog.Errorf("Unexpected error closing TCP probe socket: %v (%#v)", err, err)
    }
    return probe.Success, "", nil
}

tcp探测是通过探测指定的端口。如果可以连接,则认为探测成功,否则认为失败。

探测失败的可能原因

执行命令探测失败的原因主要可能是容器未成功启动,或者执行命令失败。当然也可能docker或者docker-shim存在故障。

由于http和tcp都是从kubelet自node节点上发起的,向容器的ip进行探测。
所以探测失败的原因除了应用容器的问题外,还可能是从node到容器ip的网络不通

liveness与readiness的原理区别

探测方式相同,那么liveness与readiness有什么区别?首先,二者能够起到的作用不同。

func (m *kubeGenericRuntimeManager) computePodContainerChanges(pod *v1.Pod, podStatus *kubecontainer.PodStatus) podContainerSpecChanges {
        ......
        liveness, found := m.livenessManager.Get(containerStatus.ID)
        if !found || liveness == proberesults.Success {
            changes.ContainersToKeep[containerStatus.ID] = index
            continue
        }
        ......

liveness主要用来确定何时重启容器。liveness探测的结果会存储在livenessManager中。
kubelet在syncPod时,发现该容器的liveness探针检测失败时,会将其加入待启动的容器列表中,在之后的操作中会重新创建该容器。

readiness主要来确定容器是否已经就绪。只有当Pod中的容器都处于就绪状态,也就是pod的condition里的Ready为true时,kubelet才会认定该Pod处于就绪状态。而pod是否处于就绪状态的作用是控制哪些Pod应该作为service的后端。如果Pod处于非就绪状态,那么它们将会被从service的endpoint中移除。

func (m *manager) SetContainerReadiness(podUID types.UID, containerID kubecontainer.ContainerID, ready bool) {
        ......
        containerStatus.Ready = ready
        ......
        readyCondition := GeneratePodReadyCondition(&pod.Spec, status.ContainerStatuses, status.Phase)
        ......
        m.updateStatusInternal(pod, status, false)
}

readiness检查结果会通过SetContainerReadiness函数,设置到pod的status中,从而更新pod的ready condition。

liveness和readiness除了最终的作用不同,另外一个很大的区别是它们的初始值不同。

    switch probeType {
    case readiness:
        w.spec = container.ReadinessProbe
        w.resultsManager = m.readinessManager
        w.initialValue = results.Failure
    case liveness:
        w.spec = container.LivenessProbe
        w.resultsManager = m.livenessManager
        w.initialValue = results.Success
    }

liveness的初始值为成功。这样防止在应用还没有成功启动前,就被误杀。如果在规定时间内还未成功启动,才将其设置为失败,从而触发容器重建。

而readiness的初始值为失败。这样防止应用还没有成功启动前就向应用进行流量的导入。如果在规定时间内启动成功,才将其设置为成功,从而将流量向应用导入。

liveness与readiness二者作用不能相互替代。

例如只配置了liveness,那么在容器启动,应用还没有成功就绪之前,这个时候pod是ready的(因为容器成功启动了)。那么流量就会被引入到容器的应用中,可能会导致请求失败。虽然在liveness检查失败后,重启容器,此时pod的ready的condition会变为false。但是前面会有一些流量因为错误状态导入。

当然只配置了readiness是无法触发容器重启的。

因为二者的作用不同,在实际使用中,可以根据实际的需求将二者进行配合使用。

原文地址:https://www.cnblogs.com/xuxinkun/p/11785521.html

时间: 2024-11-08 18:39:05

详解k8s中的liveness和readiness的原理和区别的相关文章

详解Android中那些酷炫返回方式的实现

Android手机都会有返回键,不管是实体键,还是虚拟键.Android用户主要也都是通过这个返回键操控页面返回方式的,不比IOS逼格甚高的只保留一个操作键.这种方式是最普遍的返回方式,还有一种也是比较常见的,那就是页面内部自己响应.绝大多数APP每个页面的设计图顶部左侧都会有一个返回键图标,偶尔也有奇葩的设计放在底部左侧,点击这个图标即finish掉当前页面.简单的介绍完了最常见的两种方式,下面为大家介绍两种更友好的交互方式. 拿大家比较常用的三款社交软件的交互来说.腾讯微博的返回方式除去上述

CSS学习笔记(9)--详解CSS中:nth-child的用法

详解CSS中:nth-child的用法 前端的哥们想必都接触过css中一个神奇的玩意,可以轻松选取你想要的标签并给与修改添加样式,是不是很给力,它就是":nth-child". 下面我将用几个典型的实例来给大家讲解:nth-child的实际用途: Tips:还用低版本的IE浏览器的哥们请绕过! :nth-child(2)选取第几个标签,"2可以是你想要的数字" .demo01 li:nth-child(2){background:#090} :nth-child(n

详解HTTP中get和post的区别

1.详解HTTP中GET和POST的区别 http://www.jellythink.com/archives/806 2.HTTP 方法:GET 对比 POST http://www.cnblogs.com/liu-ke/p/4198815.html

详解mysql中的Using与On的用法

多用才可以体会各个关键字的用法啊... 原文来自[http://bbs.php100.com/read-htm-tid-148469.html] 在用Join进行多表联合查询时,我们通常使用On来建立两个表的关系.其实还有一个更方便的关键字,那就是Using.那么这两个关键字在使用上有啥区别呢?往下看.假设有如下两张表:    mysql> select * from pets; +---------+---------+--------+-----------+ | pets_id | ani

详解Webwork中Action 调用的方法

详解Webwork中Action 调用的方法 从三方面介绍webwork action调用相关知识: 1.Webwork 获取和包装 web 参数 2.这部分框架类关系 3.DefaultActionProxyFactory.DefaultActionProxy.DefaultActionInvocation 终于要开始 webwork 核心业务类的总结,webwork 通过对客户端传递的 web 参数重新包装,进行执行业务 Action 类,并反馈执行结果,本篇源码分析对应下图 WebWork

实例详解 EJB 中的六大事务传播属性--转

前言 事务 (Transaction) 是访问并可能更新数据库中各种数据项的一个程序执行单元 (unit).在关系数据库中,一个事务可以是一条或一组 SQL 语句,甚至整个程序.它有通常被称为 ACID 的原子性(Atomicity).一致性(Consistency).隔离性(Isolation).持续性(Durability)四大特性: 原子性(Atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做. 一致性(Consistency):事务必须是使数据库

一张图详解Linux中的top命令

一张图详解Linux中的top命令及每个参数的含义:

图文详解Unity3D中Material的Tiling和Offset是怎么回事

图文详解Unity3D中Material的Tiling和Offset是怎么回事 Tiling和Offset概述 Tiling表示UV坐标的缩放倍数,Offset表示UV坐标的起始位置. 这样说当然是隔靴搔痒. 下面用*.3ds文件作为模型,介绍Tiling和Offset到底是怎么回事. 3DS格式解析 比如我有这样一个tank_player.3ds模型.右侧的'select'处的图片就是贴图. *.3ds文件最基本的内容包括顶点列表Vertices.贴图坐标列表UVs.面列表Faces.其中Ve

详解Android中的屏幕方向

详解Android中的屏幕方向 屏幕方向 是对Activity而言的,所以你可以在AndroidManifest.xml 文件中,通过<activity> 标记的screenOrientation 属性进行设定,例如: <activity android:name=".SketchpadActivity" android:screenOrientation="landscape"/><!--让该Activity总是显示为横屏-->