2

我很难让 kubernetes livenessProbe exec 命令与环境变量一起工作。我的目标是让 liveness 探针监控 pod 上的内存使用情况以及执行 httpGet 健康检查。

“如果容器内存使用量超过资源限制的 90% 或 http 响应代码/health失败,则探测应该失败。”

liveness探针配置如下:


livenessProbe:
  exec:
    command:
    - sh
    - -c
    - |-
      "used=$(awk '{ print int($1/1.049e+6) }' /sys/fs/cgroup/memory/memory.usage_in_bytes);
      thresh=$(awk '{ print int( $1 / 1.049e+6 * 0.9 ) }' /sys/fs/cgroup/memory/memory.limit_in_bytes);
      health=$(curl -s -o /dev/null --write-out "%{http_code}" http://localhost:8080/health);
      if [[ ${used} -gt ${thresh} || ${health} -ne 200 ]]; then exit 1; fi"
  initialDelaySeconds: 240
  periodSeconds: 60
  failureThreshold: 3
  timeoutSeconds: 10

如果我执行到(ubuntu)pod 并运行这些命令,它们都可以正常工作并完成工作。

但是当部署为 livenessProbe 时,pod 会不断失败,并显示以下警告:

Events:                                                                                                                                                                                                               │
│   Type     Reason     Age                  From     Message                                                                                                                                                           │
│   ----     ------     ----                 ----     -------                                                                                                                                                           │
│   Warning  Unhealthy  14m (x60 over 159m)  kubelet  (combined from similar events): Liveness probe failed: sh: 4: used=1608;                                                                                          │
│ thresh=2249;                                                                                                                                                                                                          │
│ health=200;                                                                                                                                                                                                           │
│ if [[  -gt  ||  -ne 200 ]]; then exit 1; fi: not found

看起来好像探测内存和 curl 运行状况检查端点的初始命令都有效并填充了环境变量,但是这些变量替换随后没有填充到 if 语句中,因此探测永远不会通过。

知道为什么吗?或者如何将其配置为正常工作?我知道这有点令人费解。提前致谢。

4

3 回答 3

4

看起来 shell 将您的整个命令视为要执行的文件名。

我会删除外部引号

livenessProbe:
  exec:
    command:
    - sh
    - -c
    - |-
      used=$(awk '{ print int($1/1.049e+6) }' /sys/fs/cgroup/memory/memory.usage_in_bytes);
      thresh=$(awk '{ print int( $1 / 1.049e+6 * 0.9 ) }' /sys/fs/cgroup/memory/memory.limit_in_bytes);
      health=$(curl -s -o /dev/null --write-out "%{http_code}" http://localhost:8080/health);
      if [[ ${used} -gt ${thresh} || ${health} -ne 200 ]]; then exit 1; fi
  initialDelaySeconds: 240
  periodSeconds: 60
  failureThreshold: 3
  timeoutSeconds: 10

你已经告诉 YAML 解析器它是一个多行字符串

于 2021-10-26T13:57:04.377 回答
3

bash我认为您问题的根源是和sh(shell)之间的混淆。两者都在容器中广泛使用(但有时不存在 bash),但 bash 具有更多功能。在这里您使用[[的是特定于 bash 的,sh 不知道它并可能导致不需要的行为。

如果容器中存在,请首先在您的命令中替换sh为。bash如果不是,您将不得不使用 shell 语法来执行条件命令。

然后可以通过利用其他 Kubernetes 功能来完善您的活性探测:

  • 为避免较大的初始延迟,请使用Startup probe。它将禁用其他探测器,直到它响应一次成功并且应该具有较高的 failureThreshold。它允许在容器启动速度快于预期的情况下提供灵活性,并在您添加其他探针时集中延迟(这意味着没有值重复)。

  • 使用该resources字段。它允许您为特定部署或 pod指定内存和 CPU限制请求(阅读文档)。因为活性探测失败意味着您的 pod 将重新启动,所以设置限制将做同样的事情,但更干净。

于 2021-10-26T14:11:41.060 回答
0

事实证明,@Andrew McGuinness 和 @OreOP 的两个答案对我最终正常工作的解决方案至关重要:

  livenessProbe:
    exec:
      command:
      - /bin/bash
      - -c
      - |-
        used=$(awk '{ print int($1/1.049e+6) }' /sys/fs/cgroup/memory/memory.usage_in_bytes);
        thresh=$(awk '{ print int( $1 / 1.049e+6 * 0.9 ) }' /sys/fs/cgroup/memory/memory.limit_in_bytes);
        health=$(curl -s -o /dev/null --write-out "%{http_code}" http://localhost:8080/health);
        if [[ ${used} -gt ${thresh} || ${health} -ne 200 ]]; then exit 1; fi
    initialDelaySeconds: 240
    periodSeconds: 60
    failureThreshold: 3
    timeoutSeconds: 10

我非常需要 Andrews 关于删除引号的建议,因为我已经指示 yaml 解析器这是一个多行字符串。我想这实际上是我要问的。但是@OreOP 关于我在 bash 和 sh 之间的混淆以及哪个会接受双括号[[ conditional ]]声明是绝对正确的。

顺便说一句,我完全同意这两个最终不是解决手头更深层次问题的正确方法,但出于各种其他原因,我的团队要求此补丁作为临时措施。我的memory.limit_in_bytes脚本中的实际上是在引用我的 k8s 部署 yaml 中设置的资源限制。

于 2021-10-28T10:02:14.983 回答