【问题标题】:kubernetes liveness probe exec command environment variables in an if statement not workingkubernetes liveness 在 if 语句中探测 exec 命令环境变量不起作用
【发布时间】:2021-12-11 21:36:38
【问题描述】:

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

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

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 语句中,因此探测永远不会通过。

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

【问题讨论】:

    标签: kubernetes livenessprobe


    【解决方案1】:

    看起来 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 解析器这是一个多行字符串

    【讨论】:

    • 太棒了!谢谢@安德鲁。这很完美。很高兴拥有另一双眼睛。
    • 顺便说一句,我认为 OreOP 关于您的确切问题是错误的,但在他的建议中,活性探测可能不是进行这些检查的正确位置。
    【解决方案2】:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      事实证明,@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 中设置的资源限制。

      【讨论】:

        猜你喜欢
        • 2020-12-26
        • 1970-01-01
        • 2021-04-07
        • 2015-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-16
        相关资源
        最近更新 更多