首页 > 解决方案 > 作业完成后,K8s 作业(容器)中指定的内存请求/限制会发生什么情况?

问题描述

我有多环境 k8s 集群 ( EKS ),我正在尝试为 ResourceQuotas 设置准确的值。

我注意到的一件有趣的事情是,当作业成功完成并有效地释放它正在使用的 cpu/内存资源时,指定的 CPU/内存请求/限制在 k8s 集群中保持“占用” 。

由于我希望在环境中执行很多作业,这给我带来了问题。当然,我已经为成功执行的作业添加了对运行 cleanup cronjob 的支持,但这只是解决方案的一部分。

我知道k8s 上的 TTL 功能https ://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/#ttl-mechanism-for-finished-jobs 仍处于 alpha阶段状态,因此在 EKS k8s 集群上不可用。

我希望在该特定 pod(容器/s)上指定的请求/限制也被“释放”,但是在查看 Grafana 上的 k8s 指标时,我发现这不是真的。

这是一个示例(绿线标记当前资源使用情况,黄色标记资源请求,而蓝色标记资源限制): 在此处输入图像描述

我的问题是:

标签: kuberneteskubernetes-jobs

解决方案


我已经对我的环境进行了“负载”测试,以测试在已完成作业(pod)上分配的请求/限制是否确实会对我设置的 ResourceQuota 产生影响。

这就是我的 ResourceQuota 的样子:

apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-quota
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 2Gi
    limits.cpu: "2"
    limits.memory: 3Gi

这是每个 k8s 作业上存在的 cpu/内存的请求/限制(准确地说是在由作业启动的 Pod 中运行的容器上):

resources:
  limits:
    cpu: 250m
    memory: 250Mi
  requests:
    cpu: 100m
    memory: 100Mi

测试结果:

  • 当前运行的作业数:66
  • CPU 请求的预期总和(如果问题的假设是正确的)~= 6.6m
  • 内存请求的预期总和(如果问题的假设是正确的)~= 6.6Mi
  • CPU 限制的预期总和(如果问题的假设是正确的)~= 16.5
  • 内存限制的预期总和(如果问题的假设是正确的)~= 16.5

我创建了显示以下内容的 Grafana 图表:

一个命名空间中作业的 CPU 使用率/请求/限制

sum(rate(container_cpu_usage_seconds_total{namespace="${namespace}", container="myjob"}[5m]))
sum(kube_pod_container_resource_requests_cpu_cores{namespace="${namespace}", container="myjob"})
sum(kube_pod_container_resource_limits_cpu_cores{namespace="${namespace}", container="myjob"})

一个命名空间中作业的内存使用/请求/限制

sum(rate(container_memory_usage_bytes{namespace="${namespace}", container="myjob"}[5m]))
sum(kube_pod_container_resource_requests_memory_bytes{namespace="${namespace}", container="myjob"})
sum(kube_pod_container_resource_limits_memory_bytes{namespace="${namespace}", container="myjob"})

这是图表的样子: 在此处输入图像描述

根据该图,请求/限制会累积并远远超出 ResourceQuota 阈值。但是,我仍然可以毫无问题地运行新工作。

此时,我开始怀疑显示的指标是什么,并选择检查指标的其他部分。具体来说,我使用了以下一组指标:

中央处理器:

sum (rate(container_cpu_usage_seconds_total{namespace="$namespace"}[1m]))
kube_resourcequota{namespace="$namespace", resource="limits.cpu", type="hard"}
kube_resourcequota{namespace="$namespace", resource="requests.cpu", type="hard"}
kube_resourcequota{namespace="$namespace", resource="limits.cpu", type="used"}
kube_resourcequota{namespace="$namespace", resource="requests.cpu", type="used"}

记忆:

sum (container_memory_usage_bytes{image!="",name=~"^k8s_.*", namespace="$namespace"})
kube_resourcequota{namespace="$namespace", resource="limits.memory", type="hard"}
kube_resourcequota{namespace="$namespace", resource="requests.memory", type="hard"}
kube_resourcequota{namespace="$namespace", resource="limits.memory", type="used"}
kube_resourcequota{namespace="$namespace", resource="requests.memory", type="used"}

这是图表的样子: 在此处输入图像描述


结论:

从这个屏幕截图中可以清楚地看出,一旦负载测试完成并且作业进入完成状态,即使 pod 仍然存在(with READY: 0/1 and STATUS: Completed),cpu/memory request/limits 将被释放并且没有更长的表示需要计算到 ResourceQuota 阈值中的约束。这可以通过观察图表上的以下数据来看出:

CPU allocated requests
CPU allocated limits
Memory allocated requests
Memory allocated limits

当系统上发生负载并创建新作业时,所有这些都会增加,但一旦作业完成就会恢复到以前的状态(即使它们没有从环境中删除)

换句话说,只有当作业(及其对应的 Pod)处于 RUNNING 状态时,才会考虑 CPU/内存的资源使用/限制/请求


推荐阅读