介绍Kubernetes是一个开源容器编排平台,可帮助编排您的容器化应用程序。使用Kubernetes,无需担心应用程序的扩展性和可用性。在将应用程序迁移到Kubernetes集群之前,集群需要对灾难恢复具有高可用性、安全性、可扩展性和优化性。Kubernetes利用来自底层虚拟机或物理机的资源,然后由各个容器使用。最常见的资源是CPU和RAM,但还有其他资源。如果需要,Kubernetes可以限制这些资源及其容器的消耗。限制容器的CPU/内存使用是一种常见的做法。CPU/内存限制是容器可以使用的最大CPU/内存。它限制容器使用节点上所有可用的CPU/内存。所以从理论上讲,这听起来不错,可以保护节点免于耗尽资源并变得无响应。CPU和内存限制的实施和工作方式各不相同。内存限制更容易检测,我们只需要检查pod的最后一次重启状态是否由于内存不足(OOMKilled)而被杀死。另一方面,为了实现CPU边界,Kubernetes使用内核限制并公开指标,而不是使用cgroup相关指标,这使得检测CPU边界变得困难。这意味着如果应用程序超过CPU限制,它将被限制。这就是问题所在。在了解CPU节流之前,让我们先了解CPU节流的必要性及其工作原理。如果我们在Kubernetes中没有指定请求的CPU限制怎么办?如果不指定CPU限制,容器将没有任何CPU上限,然后它可以使用节点上所有可用的CPU。这会使CPU密集型容器减慢同一节点上的其他容器的速度,并可能耗尽该节点上所有可用的CPU。这反过来会触发Kubernetes组件(例如kubelet)变得无响应的事件。这会导致节点变为NotReady,并且来自该节点的容器将被重新安排到其他节点上。什么是CPU节流以及CPU节流如何工作?CPU节流确保如果应用程序超过指定限制,它将被节流。有时即使CPU使用率接近限制,也可以观察到容器节流。发生这种情况是因为Linux内核中的错误会不必要地限制CPU绑定容器。现在,在我们继续之前,让我们首先了解CPU节流在Kubernetes中是如何工作的。Kubernetes使用CFS(https://kubernetes.io/docs/tasks/administer-cluster/cpu-management-policies/)配额对运行应用程序的pod实施CPU限制。完全公平调度程序(CFS)是一种进程调度程序,它根据时间段而不是基于可用的CPU功率处理用于执行进程的CPU资源分配,并使用两个文件: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_uso/p→100000此处,100000us=100mscat/sys/fs/cgroup/cpu,cpuacct/cpu.cfs_quota_uso/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之前,让我们在集群上部署一个“MetricsServer”,用于获取有关资源使用情况的指标。特别是Pod/Node指标。可以使用以下命令部署Metrics服务器,这些命令首先克隆“kubernetes-metrics-server”git存储库并在集群上创建所需的对象。git克隆https://github.com/kodekloudhub/kubernetes-metrics-server.gitcdkubernetes-metrics-server/kubectlapply-f。要创建具有CPU请求和限制的pod,请创建一个具有以下pod定义的文件“pod-with-cpu-limit.yaml”。这为Pod设置了限制“1”和请求“0.5”。Request是容器保留的资源,Limit保证容器永远不会超过某个值。(https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-resource-requests-and-limits)requests:cpu:100mlimits:cpu:500m这会创建一个没有任何问题的pod,因为Limit没有超过我们在worker节点上的实际CPU数量,并且请求在我们指定的limit之内。使用以下命令创建一个pod:kubectlapply-fpod-with-cpu-limit.yamlkubectlgetpodskubectldescribepodcpu-demo-pod现在,如果您使用以下命令检查pod的实际CPU使用率,它是1003m(1中央处理器)。此处CPU正在节流,因为我们向pod传递的参数多于我们在限制中指定的参数。使用以下命令检查用法。kubectltoppodscpu-demo-pod但是,如果您指定的CPU限制超过工作节点上可用的数量,您将面临问题并且Pod将进入Pending状态。首先删除现有的pod,更改CPU限制和请求,然后尝试使用以下命令创建pod。kubectlgetpodskubectldeletepodcpu-demo-podkubectlapply-fpod-with-cpu-limit.yaml通过描述Pod查看失败原因。kubectlgetpodskubectldescribepodcpu-demo-pod可以清楚的看到Pod无法创建,处于Pending状态,因为CPU请求超过了worker节点上实际可用的CPU。删除CPU限制时要小心就集群稳定性而言,删除CPU限制并不是一个容易的决定。如果默认情况下没有设置CPU限制,则默认为节点的最高可用值。在取消CPU限制之前,了解应用程序的工作方式及其CPU需求非常重要。我们可以尝试为对延迟敏感的应用程序删除CPU限制,而不是随机删除所有应用程序的CPU限制。隔离不受CPU限制的应用程序是个好主意。如果资源分配存在任何问题,这将有助于轻松控制和识别此类应用程序pod。结论如果Docker容器/KubernetesPod在Linux系统上运行,它们可能会由于节流而表现异常。虽然这可能很危险,但删除CPULimited是解决此节流问题的方法。这也可以通过将内核升级到修复CPU节流问题的版本来解决。不受CPU限制的应用程序也可以隔离到不同的节点,从而更容易查明影响Pod容器性能的罪魁祸首。
