K8s 之 ReadinessProbe(就绪探针)使用的迷惑

一、问题

当我们将某应用的新版本发布到 K8s 的时候,经常会出现这样一个场景:

Pod 已经运行起来了(READY=1/1,STATUS=Running),但是 Pod 中的应用(例如:springboot)还在处于启动中的阶段。此时,如果有客户端的请求被转发到了该 Pod 上,那最终的结果将会是客户端收到一个类似“连接被拒绝”的返回。

二、原因分析

默认情况下(在我们未在 Pod 中未设置 ReadinessProbe 相关信息的时候),Kubelet 会认为 Pod 的 ReadinessProbe 探针永远返回 Success,即 Pod 一直都处于可以对外提供服务的状态,该 Pod 会立刻成为一个服务端点接收客户端的请求。由于此时内部的服务正处于启动中,所以就很有可能会出现本文开头出现的那个问题。

三、解决方案

在原因分析当中其实已经提到了解决方案,就是利用 K8s 提供的 ReadinessProbe(就绪探针)。通过该探针是否返回 SUCCESS, Kubelet 可以知道当前 Pod 是否已经准备好接收请求了。只有已经准备好了的 Pod 才会被安排对外接客(接收请求)。

试想下,我们对「服务A」加上了 ReadinessProbe,且「服务A」有三个 Pod 副本(A1,A2,A3)正在对外提供服务。这个时候,我们重新发布一下「服务A」,若新建的副本 A4 还未准备就绪,则之前的A1,A2,A3 还将继续对外提供服务。当 A4 已经准备就绪,此时 Ta 才会替换掉 A1,A2,A3 其中一个副本。这样,就避免了出现 A4 还没准备好,就开始接客的尴尬时刻了。

四、新问题(迷惑)

到现在为止是不是一切看起来都很美好?ReadinessProbe 很完美的解决了开始提到的那个问题。

可是,但是,但可是 … 现实还是狠狠的抽了我一个嘴巴。

先看下我们系统结构的一张简单示意图:在这里插入图片描述

  • annoroad-xxx-front:前端应用
  • annoraod-xxx-server:对应前端的服务(BFF),有 3 个 Pod 副本,annoraod-xxx-server-1、annoraod-xxx-server-2、annoraod-xxx-server-3
  • springcloud-gateway:网关,有 3 个 Pod 副本,springcloud-gateway-1、springcloud-gateway-2、springcloud-gateway-3
  • 微服务A:提供实际的业务服务,有 3 个 Pod 副本,微服务A-1、微服务A-2、微服务A-3

请求的路径如下:

  1. 用户通过浏览器访问前端应用 annoroad-xxx-front
  2. 前端应用(annoroad-xxx-front)通过 SVC 路由到一个前端服务(annoroad-xxx-server-1)
  3. 前端服务(annoroad-xxx-server-1)通过 SVC 路由到一个 gateway(springcloud-gateway-3)
  4. 最后由该 gateway(springcloud-gateway-3) 路由到一个微服务A(微服务A-1)

我们分别在 annoroad-xxx-server、springcloud-gateway、微服务A、微服务B …. 上加上了ReadinessProbe(就绪探针),这样 服务准备就绪后再对外提供服务 的目标就能实现了吗?

让我来直接公布试验后的最终结果:

  1. annoroad-xxx-server、springcloud-gateway 可以达到预期的效果
  2. 微服务A、微服务B …… 不行!!!

之所以造成这个结果的原因是:

首先,annoroad-xxx-server、springcloud-gateway 的路由走的是 K8s 的 SVC,SVC 中的 Endpoint 描述了有关联的 Pod ,如果 Pod 的 Ready 状态变为 False,则 K8s 会自动将其从 Service 的 Endpoint 列表中删除,后续如果 Pod 的 Ready 状态又恢复了,那会将该 Pod 重新加到 Service 的 Endpoint 列表当中。所以, annoroad-xxx-server、springcloud-gateway 可以达到预期的效果。

我们再来说下从 gateway 到微服务。从 gateway 路由到 微服务A、微服务B …… 走的是 gateway 的 ribbon 路由,拉取的是 eureka 上的节点列表,也就是说只要节点已经注册到 eureka 上了,从 gateway就能路由到这个节点上了,即使这个节点在 K8s 中的还处于未就绪的状态。

为了更好的加以证明,我做了一个简单的实验,将某微服务的 ReadinessProbe 的 initialDelaySeconds 设置的时间长一点儿(模拟一直处于未就绪的状态)。然后,观察处于未就绪状态的该服务,启动完成后是否被注册到 eureka 上了,结果如下图:
在这里插入图片描述
从上图,我们可以看到 annoroad-alpha 的一个副本已经注册到 eureka 上了。但是在 K8s 容器内,该副本的 Ready 状态为0/1(未就绪)。此时,通过 gateway 访问该微服务(annoroad-alpha),是能够成功访问(完全绕过了 K8s 的就绪状态)。

四、最后

如果想再多了解些 ReadinessProbe(就绪探针)的相关概念,可以移步到我写的另外一篇文章《Pod健康检查和服务可用性检查》

k8s存活探针就绪探针是用来检测容器的状态和可用性的。存活探针(Liveliness Probe)用于判断容器是否处于正在运行状态,如果容器出现故障或死锁,k8s会自动将其下线并重新启动。而就绪探针Readiness Probe)用于判断服务是否已经准备好接收流量,如果服务还未完全启动或出现异常情况,k8s会将其从服务的负载均衡器中移除,不再接受或响应任何请求。 存活探针可以通过执行容器内部的shell命令、检查容器的TCP连接或发送HTTP请求来进行健康检查,如果探测失败,k8s会将故障的容器kill掉,并根据设置的重启策略进行重启。而就绪探针则通过HTTP请求来检查服务是否准备就绪,如果就绪探测失败,k8s会将服务从负载均衡器中移除,直到服务完全就绪后再将其添加回负载均衡器。 在使用存活探针就绪探针时,建议将检查服务的时间短于检查容器的时间,以实现先下线再重启的策略。这样,在故障发生后,服务会先被下线,如果一段时间后服务无法自动恢复,k8s会根据重启策略进行重启。通过使用这两种探针,可以确保服务的可用性和自动恢复能力。 总结来说,存活探针用于判断容器是否处于运行状态,并在容器故障时重新启动,而就绪探针用于判断服务是否已经准备好接收流量,并将未就绪的服务下线,直到服务完全就绪后再上线。这两种探针是确保k8s中应用的稳定性和可用性的重要工具。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [k8s就绪探针和存活探针](https://blog.csdn.net/qingqingxiangyang/article/details/118026170)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cab5

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值