【滴滴弹性云技术分享】深入Kubernetes资源管理机制
内容提要
本文首先介绍了 Kubernetes 以及资源管理机制。根据滴滴弹性云现有的在线 / 离线业务混布的使用场景,对资源管理机制的两种方式进行了介绍:提供了容器参数配置和对服务质量中 limit 和 request 的配置。(注:滴滴弹性云平台是基于容器技术打造的一款稳定高效、可伸缩的服务管理平台。)
资源管理
Docker 相信大家都不陌生了,而 Kubernetes 作为 Docker 生态圈中最重要的一员,需要再一次地被重新介绍。
Kubernetes 是 Google 容器集群管理方案,是 Google 多年大规模容器管理技术 Borg 的开源版本。根据 Linux 基金会的统计和评分,Kubernetes 在过去一年里已经跻身成为最受欢迎的开源项目之一,和 Linux、Homebrew 等项目齐名。
其主要价值在于:
使用 Docker 对应用程序包装 (Package)、实例化 (Instantiate)、运行 (Run);
以集群的方式运行、管理跨机器的容器;
解决 Docker 跨机器容器之间的通讯问题;
Kubernetes 的自我修复机制使得容器集群总是运行在用户期望的状态;
合理的资源管理机制。
介绍下 Kubernetes 的资源管理机制。如果应用对资源的需求不受限,那么资源会被很快的耗尽,从而影响其他的应用;就等于容器集群管理无法发挥其作用。
Kubernetes 提供 3 个层次的资源管理机制:
利用容器自身的资源限制,如 Docker 对 CPU、内存的限制;
在 Pod 层次,对 Pod 创建过程中资源范围做限制,如最大、最小的 CPU、内存需求;
在 Namespace 层次限制用户的资源限额,包括了对 CPU、内存以及 Pod、Service 数量等。
以滴滴弹性云为例,如果要实现在线和离线业务的混布,来提高物理机资源的利用率。按照日均值,在线业务和离线业务对 CPU 的消耗是 4:6,而当在线业务高峰来临,特别是早晚高峰,此刻需要保证资源消耗比例在 10:0 从而保证线上业务的稳定性。
也就意味着离线业务自动全部退出,让出资源给在线业务。在这样的业务场景下,我们设置了两种方式来达到需求。
首先是限制每个容器的资源使用。由于 Docker 本身和 Cgroup 结合得很好,可以通过参数的设置就可以都达到资源控制。以 CPU 为例:
在介绍实现机制之前,需要先理解下资源管理,可以从以下两个方面入手:
1. 从集群的角度,提高资源利用率,控制用户的资源配额。
通过资源超售来提高资源利用率
多租户资源配额管理 Limit Range and Quota,以及资源再平衡 Rescheduling
通过实时监控加入人工调配
2. 从应用的角度,为每个 Pod 寻找合适的部署节点,保证用户体验。
借助于调度器 Sheduler 本身和改造,适应业务需求的变化
划分容器的 QoS 来实现调度
自动弹性机制 Auto-Scaling 来适应业务需求变化
滴滴弹性云通过设置容器的 QoS 来实现服务混布时,业务对资源需求的变化来实现调度。
服务质量
服务质量(QoS):英文全称为 Quality of Service,中文名为服务质量,取决于用户对服务质量的预期,也就是期望的服务质量。在容器领域就是指容器所能获取到的物理资源的质量。
在实践过程中,容器根据其承载的应用不同可以粗略的分成两类:
重要的 Long Running Service:如 Borg 中的 prod。是指哪些需要长时间运行,并对延时十分敏感的服务。如 Web 服务、生产环境的监控、控制进程等;
相对不重要的 Batch Jobs:如 Borg 中的 non-prod。是指那些仅仅需要运行一段时间,并对计算时间不敏感的服务。如 Map-Reduce 等计算类服务。
而在 Kubernets 中,容器服务质量被划分为 3 个优先级:
Guaranteed:拥有最高的优先级,类似 prod;
Best-Effort:拥有最低的优先级,类似 non-prod;
Burstable:优先级介于以上两者之间
request 资源即为容器保证能够获得的资源。limit 资源即为容器在宿主资源充足的情况下可以拿到的资源。
通常 limit 大于 request,也即当宿主资源充足的情况下除了能拿到规定好的那部分资源还能拿到更多额外的资源。举个例子,一个容器的 mem.Request = 2G,mem.Limit = 4G:
QoS 级别决定了当我们资源不足时 Kubernetes 处理这些容器的方式。还是拿内存来举例:
当宿主上内存资源不够的时候,QoS 级别是 Best-Effort 的容器会最先被 kill掉;当宿主节点上内存资源充足的时候,QoS 级别是 Best-Effort 的容器可以使用宿主节点上剩余的所有内存资源;
当宿主节点上内存资源不够的时候,如果 QoS 级别是 Best-Effort 的容器已经都被 kill 掉了,那么会查找 QoS 级别是 Burstable 的容器,并且这些容器使用的内存已经超出了 requests 设置的内存值,这些被找到的容器会被 kill 掉;当宿主节点上内存资源充足的时候,QoS 级别是 Burstable 的容器会按照 requests 和 limits 的设置来使用。
当宿主节点上内存资源不够的时候,如果 QoS 级别是 Best-Effort 和 Burstable 的容器都已经被 kill 掉了,那么会查找 QoS 级别是 Guaranteed 的容器,并且这些容器使用的内存已经超出了 limits 设置的内存值,这些被找到的容器会被 kill 掉;当宿主节点上内存资源充足的时候,QoS 级别是 Burstable 的容器会按照 requests 和 limits 的设置来使用。
看到这里大家就可以想到,在上面提到的在线、离线业务混布的场景中,我们可以把离线容器的 request 资源调的很低,低到根本无法满足其基本运行的需求,而 limit 不设上限。
把在线业务容器的服务等级设为 Guaranteed,保证他们的资源使用量。这样当宿主资源充足的时候离线容器可以相安无事的运行,但是当资源高峰来临,大量的在线业务新容器在宿主上创建时,离线计算的容器的资源会被一步步蚕食,最终消亡殆尽,达到支撑高峰业务的目的。
结果测试
根据上述的业务场景,我们在测试环境中进行了示意性的测试。首先物理机的内存容量为 250G,分别创建:
· Guaranteed 容器:request == limit = 240G
· Burstable 容器:request == limit = 18G
· Best-Effort 容器:不设限
然后使用测试程序,分别让三个容器占用 220G、15G 和 40G 内存,并观察容器的状态。
首先,让 Guaranteed 容器占用 200G 内存,如图所示:
然后分别让 Burstable 容器占用 18G,Best-Effort 容器占用 40G,如图所示:
在以上的情况下,由于 3 个容器的占用的内存大小已经超过 250G 物理机的内存,所以会触发 Kubernetes 的资源管理机制,依照 QoS 的优先级顺序,杀死 Best-Effort 容器,来保证更高优先级的容器正常运行。如图所示:
当然,在上面举离线、在线业务混部的例子只是想更好的引出 Kubernetes 对容器服务质量的优化和探索,有这样一套策略的存在,对在线业务容器的稳定性是一个极大的保证(因为所有的宿主上都会运行一部分 Best-Effort 容器)。
对待真正的线上业务也并不能仅仅依靠这一个策略来完成调度,这可能需要像打车动态调价一样更多优秀的算法辅助决策。
所幸,Kubernetes 本身支持用户以插件的形式运行自己的调度策略,我们可以在资源调度方面和业务线一起做更多的探索。
总结
容器编排技术 Kubernetes,在原有的 Docker + cgroup 资源限制层面上建立了一套优秀的服务质量管理体系,这套体系能帮助更好的管理容器资源,保证容器服务质量。
更多的云计算行业动态、产品资讯、活动报名、技术干货及案例分析,请关注「滴滴云」微信号!