在内存管理篇,我们研究了Kubernetes(K8s)requests和limits的资源含义,以及Docker容器运行时的内存含义。我们在这里将介绍K8中的CPU的含义,以及CPU的requests和limits,并研究如何为Pod设置合理的cpu资源。
CPU的含义
那么,CPU在kubernetes中的确切含义是什么?一个CPU等价于node操作系统提供的一个CPU核心。
Limits
与内存相反,CPU在kubernetes中是可压缩的,这意味着它可以被throttled(限制)。当您指定容器的CPU limits时,实际上是在nodes上限制该容器的CPU时间,而不是设置容器对特定的一个CPU或一组CPU的亲和性。这意味着,即使您指定的limits少于节点上的CPU总数,您的容器仍会看到(并使用)该节点的所有CPU,只是你的容器可以使用的cpu的时间是有限的。
例如,在具有8个CPU核心的node上指定某个容器的CPU limits为4,这也就意味着该容器只能使用相当于4个CPU核心的全部时间,但是可以分布在所有CPU核心上。对于在专用node上运行的单个容器,这种情况下,该node所有CPU核心的最大允许使用率将为50%。
那么,kuberne上的这种限制转换成Docker中的控制会是怎样呢? K8s通过传递cpu-period和cpu-quota选项来实现kubernetes中的CPU limits 。 cpu-period始终设置为100000μs(100ms),表示跟踪容器CPU利用率的时间段。 cpu-quota是容器在每个cpu周期内可以使用的CPU时间总量。这两个设置都控制着内核的完全公平调度程序(CFS)。这是不同的K8s CPU限制转换为Docker配置的方式:
limits 1: cpu-quota=100000
limits 4: cpu-quota=400000
limits 0.5: cpu-quota=50000
limits 1 意味着每100ms,允许使用总CPU时间相当于一个CPU核心的100%CPU时间, limits 4 意味着每100ms允许使用总CPU时间相当于一个CPU核心400%的CPU时间 (或者,相当于4个CPU核心100%的CPU时间) 。不要忘记,这些CPU时间都是分布在所有的CPU核心上的。 由于CFS配额的工作方式,在给定时间段内超出其配额的任何容器在该时间段内将不允许再次运行,直到下一个时间段-这意味着您的程序会感觉到莫名其妙的暂停,特别是如果您的程序设置了CPU limits,并且对延迟敏感的情况下这种感觉更加明显。
Requests
您可以通过指定Pod的request来指定Pod所需的CPU(或CPU的一部分),在指定request的时候,kubernetes不允许node的request的值超过节点的CPU核数(属于某个node上的所有pod的cpu的request的总和不能超过该node上显示的CPU数量)。您可以将request的总数设置为node的CPU的核数,但是当node的工作负载过高时,例如当CPU的使用率达到甚至超过100%时会怎样?这时,容器的CPU调度优先级由Pod的``requests''的值来决定,该requests的值乘以1024后的乘积作为cpu-shares选项传递给Docker。cpu-shares实际上就是一个权重;如果节点上运行的所有容器具有相同的权重,则在负载过大的情况下(没有空闲的CPU周期时),所有容器将具有相同的CPU调度优先级。如果一个容器的权重比其他容器大,则在负载过大的情况下,它将具有更高的CPU调度优先级,并能够比其他容器获得更多的CPU时间。
Guaranteed 还是 Burstable?
在内存篇, burstable的QoS配置意味着在其他容器不使用CPU的情况下,您的容器使用这些空闲的CPU时间,从而可能使用到比requests更多的CPU时间。这样可以潜在地更有效地利用基础资源,但具有更大的不可预测性,例如,对CPU比较依赖的应用程序的响应延迟可能会受到在同一nodes上的其他容器的暂时影响。在最坏的情况下,一个node上的burstable容器若过多,将会引起非常高的CPU负载,从而相互对彼此产生负面。
如果您是K8新手,那么最好将requests和limits的值设置为相同,从而确保你的pod是Guaranteed类型的容器。当您对CPU的资源利用特性了解的更深入时,并可能发现您在CPU方面的配置已过剩时,您可以考虑引入Burstable容器,以期获得更大的收益,甚至可以提高CPU的整体使用率。
需要为容器分配多少CPUs?
您应该为容器分配多少个CPU?根本没有标准答案,这取决于你应用的组特性,可接受的性能,pod的调度策略,主机类型,成本等。
但是-如果您对你的应用了如指掌,则可以在性能测试环境中甚至在生产环境中尝试不同的配置。最终你将会找到性能和成本的平衡点,但是container-throttling是Linux上运行的CPU密集型应用的重要影响因素。通常可以使用Prometheus来查看CPU的相关信息,也可以直接进入容器并查看cgroup CPU统计信息:
cat /sys/fs/cgroup/cpu,cpuacct/cpu.stat
该文件中包含了总共执行了多少次CPU调度,容器被限制的总次数以及累积限制的时间(以纳秒为单位)。