Kubernetes No CPU Limit:不限制 CPU 可能会更好
作者 | 祝祥
来源 | 新钛云服(ID:newtyun)
转载请联系授权(微信ID:zlm935177782)
介绍
Kubernetes 是一个开源容器编排平台,可帮助编排您的容器化应用程序。使用Kubernetes之后 ,无需担心应用程序的扩展和可用性。在将应用程序迁移到Kubernetes 集群之前,集群需要拥有灾难恢复的高可用性,以及安全、可扩展和优化的特性。
Kubernetes 利用来自底层虚拟机或物理机的资源,然后由各个容器使用。最常见的资源是 CPU 和 RAM,还有其他资源。如果需要,Kubernetes 可以限制这些资源及其容器对它们的消耗。对容器的 CPU/Memory 使用设置限制是一种普遍的做法。
CPU/Memory 限制是容器可以使用的最大 CPU/Memory。它限制容器使用节点上所有可用的 CPU/Memory。因此,从理论上讲,这听起来不错,可以保护节点不会耗尽资源并变得无响应。
CPU 和内存限制的实现方式和工作方式彼此不同。内存限制更容易检测到,我们只需要检查 pod 的上次重启状态,如果它由于内存不足(OOMKilled)而被杀死。另一方面,为了实现 CPU 限制,Kubernetes 使用内核限制并暴露指标而不是使用 cgroup 相关的指标,这使得很难检测 CPU 限制。这意味着,如果应用程序超出 CPU 限制,它就会受到限制。
这就是问题所在。
在我们了解 CPU throttling之前,让我们了解 CPU 限制的需求以及它是如何工作的。
如果我们没有在 Kubernetes 中指定 CPU limit 与 request怎么办?
如果您不指定 CPU 限制,则容器将没有任何 CPU 上限,然后它可以使用节点上所有可用的 CPU。这会使 CPU 密集型容器降低同一节点上的其他容器的速度,并可能耗尽节点上所有可用的 CPU。这反过来又会触发诸如 kubelet 等 Kubernetes 组件变得无响应的事件。这可以使节点变为 NotReady 状态,并且来自该节点的容器将被重新调度到某个其他节点上。
什么是 CPU 限制以及 CPU 限制如何工作?
CPU throttling确保如果应用程序超过指定的限制,它就会受到限制。有时,即使 CPU 使用率接近限制,也可以观察到容器throttling。发生这种情况是因为 Linux 内核中的一个错误会不必要地限制拥有 CPU 限制的容器。
现在,在我们继续之前,让我们首先了解 CPU 限制在 Kubernetes 中是如何工作的。Kubernetes使用CFS (https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/) 配额来对运行应用程序的 pod 实施 CPU 限制。Completely Fair Scheduler (CFS) 是一个进程调度程序,它根据时间段而不是基于可用的 CPU 功率来处理执行进程的 CPU 资源分配,并使用两个files:cfs_period_us 和 cfs_quota_us。(https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt)
- cpu.cfs_quota_us:一段时间内的总可用运行时间[以微秒为单位]
- cpu.cfs_period_us:一个周期的长度[以微秒为单位]
cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_period_us o/p → 100000
这里,100000 us = 100 ms
cat /sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_us
o/p → -1
这里,cpu.cfs_quota_us 的值为 -1 表示没有任何带宽限制
例如,有一个单线程应用程序在 CPU 上运行,但有 CPU 限制,应用程序需要 200 毫秒的处理时间。应用程序完成其请求的图表如下所示。
在第二种情况下,如果我们为应用程序设置 0.4 个 CPU 的 CPU 限制,则应用程序在每 100 毫秒周期后获得 40 毫秒的运行时间。在这里,之前需要 200 毫秒的请求现在需要 440 毫秒才能完成。
从上面的例子可以看出,CPU 限制是问题的真正原因。
案例
让我们以以下示例为例,其中工作节点有1 个 CPU。您可以在 linux 服务器上使用“cat /proc/cpuinfo”命令检查它。
现在,在我们创建有 CPU 限制的 Pod 之前,让我们在集群上部署一个“Metrics Server”,它可以用来获取资源使用率的相关指标。尤其是Pod/Node的指标。
可以使用以下命令部署 Metrics 服务器,这些命令首先克隆“kubernetes-metrics-server”git 存储库并在集群上创建所需的对象。
git clone https://github.com/kodekloudhub/kubernetes-metrics-server.git
cd kubernetes-metrics-server/
kubectl apply -f .
要创建有 CPU 请求和限制的 pod,请使用以下 pod 定义创建一个文件“pod-with-cpu-limit.yaml”。这为 Pod 设置了Limit “1”和Request “0.5”。Request是容器预留的资源,Limit确保容器永远不会超过某个值。 (https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-resource-requests-and-limits)
requests:
cpu: 100m
limits:
cpu: 500m
这将创建一个没有任何问题的 pod,因为 Limit 不超过我们在工作节点上拥有的实际 CPU 数量,并且请求在我们指定的限制范围内。
使用以下命令创建一个 pod
kubectl apply -f pod-with-cpu-limit.yaml
kubectl get pods
kubectl describe pod cpu-demo-pod
现在,如果您使用以下命令检查 pod 的实际 CPU 使用率,它是 1003m(1 个 CPU)。由于我们传递给 pod 的参数超过了我们在限制中指定的参数,这里 CPU 正在throttling。
使用以下命令检查使用情况。
kubectl top pods cpu-demo-pod
但是,如果您指定的 CPU 限制超过了工作节点上可用的数量,您将面临问题并且 Pod 将进入 Pending 状态。
首先删除现有的 pod,更改 CPU 限制和请求,然后尝试使用以下命令创建一个 Pod。
kubectl get pods
kubectl delete pod cpu-demo-pod
kubectl apply -f pod-with-cpu-limit.yaml
通过描述 Pod 来检查失败的原因。
kubectl get pods
kubectl describe pod cpu-demo-pod
您可以清楚地看到,由于 CPU 请求超过了工作节点上实际可用的 CPU,因此 Pod 无法创建并处于 Pending 状态。删除 CPU 限制时要小心
就集群稳定性而言,移除 CPU 限制并不是一个容易的决定。如果默认情况下未设置 CPU 限制,则它的默认限制则是节点的最高可用值。
在取消 CPU 限制之前,了解应用如何工作以及它们对 CPU 的需求非常重要。
我们可以尝试移除对延迟敏感的应用的 CPU 限制,而不是随意的从所有应用中移除 CPU 限制。
隔离没有 CPU 限制的应用是个好的方式。如果资源分配出现任何问题,这将有助于轻松控制和识别此类应用pod。
结论
如果 Docker container/Kubernetes Pod 在 Linux 系统上运行,那么它们可能会由于throttling而表现异常。虽然这可能很危险,但删除 CPU Limited 是解决此限制问题的解决方案。
这也可以通过将内核升级到修复 CPU throttling问题的版本来解决。没有 CPU 限制的应用程序也可以隔离到不同的节点,以便更容易找出影响pod容器性能的罪魁祸首。