即使端点正在工作,k8s 就绪性和活性探测也会失败

Mil*_*iez 7 kubernetes google-kubernetes-engine readinessprobe livenessprobe

我有一个 Next.js 应用程序,它有 2 个简单端点readinessliveness具有以下实现:

return res.status(200).send('OK');
Run Code Online (Sandbox Code Playgroud)

我已经根据api 路由文档创建了端点。/stats另外,我根据此处的文档有一个basePath 。因此,探测端点位于/stats/api/readiness/stats/api/liveness

当我在本地 Docker 容器中构建并运行应用程序时,探测端点可访问并返回 200 OK。

但是,当我将应用程序部署到 k8s 集群时,探测失败。时间还很充裕initialDelaySeconds,所以这不是原因。

我通过连接到servicepod port-forward,当 pod 刚刚启动时,在失败之前,我可以到达端点并返回 200 OK。过了一会儿,它开始像往常一样失败。

我还尝试通过健康的 pod 访问失败的 pod:

k exec -t [healthy pod name] -- curl -l 10.133.2.35:8080/stats/api/readiness
Run Code Online (Sandbox Code Playgroud)

同样的情况 - 一开始,虽然 pod 尚未失败,但我在curl 命令上得到 200 OK。过了一会儿,它开始失败。

我得到的探针错误是:

Readiness probe failed: Get http://10.133.2.35:8080/stats/api/readiness: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
Run Code Online (Sandbox Code Playgroud)

有趣的实验 - 我尝试为探针放置一个随机的、不存在的端点,但我得到了同样的错误。这让我想到探针失败是因为它无法访问正确的端点?

但话又说回来,在探测开始失败之前,端点可以访问一段时间。所以,我真的不知道为什么会发生这种情况。

这是我的探测器的 k8s 部署配置:

      livenessProbe:
        httpGet:
          path: /stats/api/liveness
          port: 8080
          scheme: HTTP
        initialDelaySeconds: 10
        timeoutSeconds: 3
        periodSeconds: 3
        successThreshold: 1
        failureThreshold: 5
      readinessProbe:
        httpGet:
          path: /stats/api/readiness
          port: 8080
          scheme: HTTP
        initialDelaySeconds: 10
        timeoutSeconds: 3
        periodSeconds: 3
        successThreshold: 1
        failureThreshold: 3
Run Code Online (Sandbox Code Playgroud)

更新

curl -v按照评论的要求使用。结果是:

*   Trying 10.133.0.12:8080...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* Connected to 10.133.0.12 (10.133.0.12) port 8080 (#0)
> GET /stats/api/healthz HTTP/1.1
> Host: 10.133.0.12:8080
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< ETag: "2-nOO9QiTIwXgNtWtBJezz8kv3SLc"
< Content-Length: 2
< Date: Wed, 16 Jun 2021 18:42:23 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
{ [2 bytes data]
100     2  100     2    0     0    666      0 --:--:-- --:--:-- --:--:--   666
* Connection #0 to host 10.133.0.12 left intact
OK%
Run Code Online (Sandbox Code Playgroud)

当然,一旦开始失败,结果就是:

*   Trying 10.133.0.12:8080...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0* connect to 10.133.0.12 port 8080 failed: Connection refused
* Failed to connect to 10.133.0.12 port 8080: Connection refused
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
* Closing connection 0
curl: (7) Failed to connect to 10.133.0.12 port 8080: Connection refused
command terminated with exit code 7
Run Code Online (Sandbox Code Playgroud)

SYN*_*SYN 8

错误告诉你:Client.Timeout exceeded while awaiting headers。意味着 TCP 连接已建立(未拒绝,也未超时)。

您的活动/就绪探测超时太低。您的应用程序没有足够的时间来响应。

可能是由于 CPU 或内存分配比使用笔记本电脑时要小,由于并发性较高,可能是 LimitRange 在您没有设置时设置了一些默认值。

检查:

time kubectl exec -t [healthy pod name] -- curl -l 127.0.0.1:8080/stats/api/readiness
Run Code Online (Sandbox Code Playgroud)

如果您无法分配更多 CPU,请将时间加倍,四舍五入,然后修复探测器:

  livenessProbe:
    ...
    timeoutSeconds: 10

  readinessProbe:
    ...
    timeoutSeconds: 10
Run Code Online (Sandbox Code Playgroud)

或者,虽然可能不那么精神化,但您可以用 tcpSocket 检查替换这些 httpGet 检查。他们会更快,但可能会错过实际问题。

  • 是的,增加 CPU 请求和限制修复了这个问题。当探测器失败时,我必须列出“要测试的东西”列表,因为错误看起来如此模糊。 (3认同)