if 语句中的 kubernetes liveness probe exec 命令环境变量不起作用

kubernetes liveness probe exec command environment variables in an if statement not working

我很难让 kubernetes livenessProbe exec 命令使用环境变量。 我的目标是让 liveness 探测器监控 pod 上的内存使用情况,并执行 httpGet 健康检查。

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

liveness probe配置如下:


livenessProbe:
  exec:
    command:
    - sh
    - -c
    - |-
      "used=$(awk '{ print int(/1.049e+6) }' /sys/fs/cgroup/memory/memory.usage_in_bytes);
      thresh=$(awk '{ print int(  / 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

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

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

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

我会删除外引号

livenessProbe:
  exec:
    command:
    - sh
    - -c
    - |-
      used=$(awk '{ print int(/1.049e+6) }' /sys/fs/cgroup/memory/memory.usage_in_bytes);
      thresh=$(awk '{ print int(  / 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 解析器这是一个多行字符串

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

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

然后可以利用其他 Kubernetes 功能完善您的 liveness probe:

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

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

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

  livenessProbe:
    exec:
      command:
      - /bin/bash
      - -c
      - |-
        used=$(awk '{ print int(/1.049e+6) }' /sys/fs/cgroup/memory/memory.usage_in_bytes);
        thresh=$(awk '{ print int(  / 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 中设置的资源限制。