介绍
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)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容器性能的罪魁祸首。