运用背景

当前打榜平台在去创建被测服务的时候,会根据被测服务 POD 的 Ready 状态来去判断被测服务 POD 是否准备就绪。然而,这存在一个问题,有的服务可能在启动后,还需要执行一些指令才算真的可以对外服务。如果这个时候,直接开始测试流程,与被测服务通信、发送数据,往往会请求失败。

最开始,使用了两种非常简单的方式来避免这个问题。

一种是,在测试流程开始,直接 sleep 3 分钟,推迟与被测服务通信的时间。

一种是,为测试流程的第一次请求增加重试机制,在一定的重试次数限制下进行测试。

然而,这两种方式都不够优雅。

最后了解到 K8S 有一个 readinessProbe 属性,可以用来更改 POD 的就绪检查机制。

使用 readinessProbe 解决 ready 需求

从官网中 copy 一个例子,内容如下。

apiVersion: v1
kind: Pod
metadata:
  labels:
    test: liveness
  name: liveness-http
spec:
  containers:
    - name: liveness
      image: registry.k8s.io/liveness
      args:
        - /server
      readinessProbe:
        httpGet:
          path: /healthz
          port: 8080
        initialDelaySeconds: 3
        periodSeconds: 3

readinessProbe 可以配置 httpGet 属性,代表 K8S 通过 get 请求 POD 的某个路径来判断 POD 服务是否真的处于 Ready 状态。

各个参数的含义如下:

  • path:http 请求路径
  • port:服务端口号
  • initialDelaySeconds:POD 拉起后多久进行第一次 readiness 检测
  • periodSeconds:两次 readiness 检测的时间

这样,被测服务只需要补充一个 /healthz 接口,在自身真正准备好了后,返回一个 200 状态码;当自身没有准备好时,返回一个大于 399 的状态码就可以。这样就可以优雅的实现上面的需求了。

各种 readinessProbe 方案

通过执行 command 来判断

当 command 在容器中执行后返回非 0 状态时,容器被认为是非就绪状态。

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

通过执行 HTTP GET 请求来判断

如果收到的 HTTP 状态码在 200 到 399 之间,则认为 Pod 已经就绪。每隔 5 秒钟,Kubernetes 都会重复进行一次检查。

如果应用暂时无法处理请求,则返回一个非 200-399 的状态码,这样 Kubernetes 就会让该 Pod 暂时不参与服务,直至 readiness probe 成功。

readinessProbe:
  httpGet:
    path: /health
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5

通过 TCP Socket 探测

K8S 尝试建立到容器的 TCP 连接。如果探针能够建立连接,那么健康检查就认为成功;反之,如果连接失败,则认为探针检查失败。

readinessProbe:
  tcpSocket:
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 5