基于利用负载动静治理 CPU、内存等资源的应用是云原生架构的最佳实际之一,Kubernetes 通过资源申请和限度以及 HPA/VPA 等机制,为云原生利用资源管理提供了很好的反对。原文: Infinite Scaling with Containers and Kubernetes
如果没有足够资源让容器实现工作,那么即便把世界上最好的代码容器化也没有任何意义。
我在写对于容器状态探测的文章时产生了这篇文章的想法,很显著,对 kubelet 查问返回精确响应只是解决方案的第一局部。
第二局部是本文的主题: 为容器分配资源。咱们须要摸索资源分配的所有畛域,从 Kubernetes pod 中的单个容器直到云上近乎有限的容量。
Kubernetes 资源管理: 概述
“ 如何确保容器始终领有所需资源?”
本节只是为刚开始应用 Kubernetes 治理资源的人简略介绍一下资源管理,对于命名空间限度范畴和 Kubernetes 容器资源管理的官网文档依然是必读材料,如果你对这一主题比拟相熟,能够跳到下一部分。
Kubernetes 资源管理次要包含 CPU、 内存 和本地长期存储,容器标准能够为每种资源类型定义资源申请和资源限度。
资源申请(resource request) 是容器运行时所需的最小资源量,节点调度器只有在节点满足 pod 中所有容器的最小资源申请时,才会将 pod 调度到该节点上。
资源限度(resource limit) 是 kubelet 在其生命周期内应该调配给容器的最大资源量。当容器设置了资源限度但没有资源申请时,相当于将资源申请设置为与资源限度雷同的值。
容器能够设置资源申请和限度的任意组合,CPU 和内存预留的不同组合定义了父 pod 的服务质量,如下所示:
- pod 中每个容器都有资源申请和限度,并且每个容器的申请和限度具备雷同的值: Guaranteed。
- pod 中至多有一个容器没有设置资源申请或限度: BestEfford。
- 不属于前两种的 pod: Burstable。
当 kube-scheduler 决定在工作节点上调度某个 pod 时,理解这些类别的含意会很有帮忙:
- “Guaranteed” 意味着调度程序只将 pod 调配给具备足够资源的工作节点,以满足 pod 中所有容器的申请。
- “Burstable” 意味着调度程序会寻找具备足够内存的工作节点来满足 pod 中所有容器的资源申请,调度器并不关怀工作节点是否可能满足 pod 中容器的资源限度 或资源申请之上的任何限度。
- “BestEffort” 是指调度程序在调度 ”BestEffort” pod 之前,将首先满足 ”Guaranteed” 或 ”Burstable” pod 的资源申请。调度器会一直从新评估,如果 ”Guaranteed” 或 ”Burstable” pod 须要资源,可能会 标记 ”BestEffort” pod 以便驱赶。
决策工夫: 谁来定义容器资源?
首先须要了解,资源申请是用来爱护容器的 ,而 资源限度是用来爱护集群的。
做出决策的次要参与方是 产品开发人员 和系统管理员,因为决策会随着工夫的推移而扭转,因而他们之间的 ” 会谈 ” 充斥挑战:
- 产品开发人员 将大部分工夫用于建设与部署与生产环境隔离的资源边界。
- 系统管理员 通常在解决 Kubernetes 工作负载标准时不足足够的文档阐明资源申请和限度的变动会如何影响工作负载。
产品开发人员能够更好的理解工作负载的需要及其在不同资源分配下的行为,一般来说,应该可能在公布前确定以下阈值:
- 相对最小 (Absolute minimum) 资源申请。这个值是加载运行时所需的资源,并且可能轻松响应来自 kubelet 的探测申请。
- 最大可用 (Maximum usable) 资源限度。这个值是容器的性能开始遇到内部限度的点,比方磁盘 I / O 或调用第三方服务的瓶颈。
现实状况下,产品开发人员还应该建设并记录容器性能在边界内的变动状况,这些信息能够帮忙零碎架构师在部署之前布局初始容量,并使系统管理员可能调整生产环境中的资源申请。
配额、范畴和公地喜剧
系统管理员能够查看集群容量及可用容量。作为偶然兼顾 SRE 的人,我比拟观赏 ”Guaranteed” 工作负载。对于组织来说,在 pod 中所有容器上设置固定的资源边界并信赖 pod 能够在边界内牢靠工作须要非凡的信念(以及大量测试)。
“Burstable” 工作负载在信赖范畴内的排名略低。当我做 SRE 时,最大的心愿是在 burstable pod 中的所有容器都设置了上一节提到的 ” 相对最小 ” 资源申请。
对于 burstable 工作负载的资源限度,我的观点来自资源限度背地的开发理念:
- (好的理念) 在工作负载内进行主动伸缩 (例如,启动具备最小和最大内存限度的 Java 虚拟机)。这种安顿(资源限度设置高于资源申请) 意味着开发团队花工夫确定了工作负载的可用操作范畴,并能很好的管制和治理资源。
- (不好的理念) 避免最终谬误。这种设计理念让我想起了 ” 公地喜剧 ”,即每个人都预期资源最终将被耗尽,因而须要占有更多共享资源,从而减速了共享资源的耗尽。当开发团队低估了资源需要时,这种理念尤其具备灾难性,在这种状况下,工作负载继续在其资源开销的突发区域内运行,使其容易受到 CPU 节流、内存耗尽和工作节点 kubelet 终止的影响。
最初留下来的是 ”BestEffort” 工作负载,它们不受约束的耗尽集群资源的能力,以及面对其余申请雷同资源的 pod 时软弱的调度状态,让咱们时刻放心集群的运行。
在解决这些类型的工作负载时,系统管理员必须花工夫思考以下选项:
- 用限度范畴 (limit ranges)”) 为命名空间中的容器和 pod 设置默认资源申请和限度。我认为,对跨命名空间的工作负载调配雷同的资源限度,再加上不足产品开发人员的投入,让这一主张并不事实。
- 用资源配额 (resource quotas)”) 限度命名空间中所有 pod 的组合资源。这种办法是更有前途的解决方案,缩小了最终容器对该命名空间失控的 ” 爆炸半径 ”,长处是防止了资源平安缓冲区叠加命名空间中 pod 数量所造成的节约。
- 深吸一口气,咱们无望从下一节中介绍的 pod 主动缩放技术中解脱进去。
Pod 主动缩放: 超过动态大小
许多读者可能曾经筹备好提出解决难以管制的工作负载的罕用办法:
- Horizontal pod autoscaling (HPA)”)
- Vertical pod autoscaling (VPA)”)
这两种风行的主动扩容技术能够依据资源指标在集群内动态分配容量。HPA 能够更改部署 pod 正本的数量,而 VPA 能够更改 pod 的资源申请和限度。留神,在 Kubernetes 加强倡议增加到 Kubernetes 之前,VPA 对 pod 的更改会导致 pod 重启。
尽管可能主动扩大容量,但这些组件并不能在不足对工作负载的操作范畴的准确定义。例如,如果 pod 中的容器没有对该度量的资源申请,HPA 将不会对该度量采取行动。HPA 也不适宜部署依赖于集群中 pod 的特定数量的正本的场景。
对于须要固定数量正本的工作负载或没有预设限度的工作负载,应用 VPA 成果更好。不过会有一个绝对较长的限度列表。此外,如果设置限度范畴,则须要思考的因素可能会非常复杂。
这些工具在主动伸缩工作负载方面最终是否无效取决于开发期间通过充沛钻研的资源申请和限度的剖析工作。在这方面我必须给予 VPA 额定的信赖,因为它可能 ” 学习 ” 部署的资源范畴。
自动化运维 operator: 即开即用的 SRE?
Kubernetes operator 引入了自定义资源的概念来管理应用程序和工作负载。从概念上讲,operator 继续监控自定义资源并将其内容映射到工作负载资源。
Operator 成熟度模型定义了五个不同级别的自动化,最高是 5 级,即 ” 主动驾驶(Auto Pilot)”。处于该成熟度阶段的 operator 应该对其治理的工作负载主动利用包含程度或垂直扩大在内的自主行为。
开发 operator 天然会有额定老本,包含设计和记录自定义资源定义,operator pod 还存在额定的运行时老本。这就是为什么我认为 operator 的价值只有在第 4 级或 ” 深度洞察(Deep Insights)” 时能力开始对消老本,这一级别须要生成指标、收回警报、实现工作负载剖析等。
在 4 级以下,operator 对于帮忙缓解产品开发人员对将来的预测以及帮忙系统管理员将这些预测变为事实简直没有任何帮忙。
Knative: 零节约的弹性容量
据其网站介绍,Knative” 是一个开源企业级解决方案,用于构建无服务器和事件驱动应用程序。”
从本文角度来看,咱们感兴趣的是 Knative 的服务模块。该模块蕴含 Knative Pod Autoscaler (KPA),它模拟 HPA 扭转 Pod 正本数量以满足需要的能力,具备两个要害区别:
- 依据内部申请的数量来缩放正本
- 当没有内部申请时,将正本放大到零
与 HPA 不同的中央在于,HPA 在超过预设边界时对资源利用率做出反馈,KPA 依据并发性和每秒申请数 target”)指标做出决策。
依据教训,HPA 更适宜资源需要不会忽然扭转的、长时间运行的、启动迟缓的过程。相同,KPA 更适宜可能疾速启动以满足即时需要的刹时过程。
最初,无论是否思考 ” 无服务器 ”,KPA 都要应用容器,因而资源限度依然很重要。
集群主动伸缩: 冲破极限
一旦对工作负载资源和 pod autoscaler 进行了适当的调优,就能够深刻理解工具箱并应用 Kubernetes 集群 autoscaler 了。
集群主动缩放器能够依据资源需要增加 (或删除) 工作节点,主动缩放器尊重可配置的上限和下限,以保障 pod 的最小容量以及肯定水平的老本管制,防止难以管制的工作负载使集群适度扩容。
迟缓扩容(Slow stretching)。记住,与 pod 主动缩放器相比,集群主动缩放器的响应工夫显著较慢,工作节点须要几分钟能力对 kube-scheduler 可用。
假如须要集群主动缩放器来解决峰值需要,在这种状况下,必须部署一个就义缓冲区的 ” 暂停舱(pause pod)”(在集群主动缩放器文档中有形容)。当新工作负载须要这些资源时,kube-scheduler 会立刻退出 pause pod 以开释资源,而后集群扩大节点数量以重新分配被驱赶的 pod。
请留神,Kubernetes 的污点 (taints) 和容忍 (tolerations) 也在主动缩放器的工作中发挥作用,如果没有对污点的容忍,则设有污点的工作节点将被禁止搁置 pod。
无服务器: 有限容量……但有限度
对于最终级别的主动扩大,是时候放弃集群的边界了(即便 Kubernetes 也有限度),并在云服务商级别思考无服务器性能。
次要的云服务商能够依据多个事件 (如 web 申请、数据库操作和计时器) 按需启动容器镜像。与单个集群相比,云服务商的资源容量实际上是有限的,与在集群中运行雷同的工作负载相比,只在容器中运行一会儿的老本简直能够忽略不计。
具备讥刺象征的是,只管每次调用的老本极低,但无服务器办法使咱们从放心资源限度转向放心老本超支:
- 容器限度依然很重要: 云服务商要求为每个容器调用指明 cpu 和内存数量。
- 估算限度: 如果测试套件中的谬误可能耗尽集群容量,那么在无服务器部署中,雷同的谬误可能会在一夜之间耗尽整个部门的估算。
无服务器产品还有几种变体,例如将一个小性能交给云引擎,而不是整个容器镜像,或者让云服务商应用托管集群来运行容器(以规模化换取安全性)。
为不便起见,这些产品都能够从蕴含 Dockerfile 的 Git 存储库开始,在调度该镜像的工作负载之前,用存储库构建和缓存容器镜像。
论断
咱们涵盖了工作负载的整个资源分配范畴,从调优单个容器到 Kubernetes 之外的超大规模工作负载。
本文首先概述了 Kubernetes 资源管理及其 资源申请和限度 的外围概念,而后在这些动态限度的根底上构建pod 主动缩放器: HPA、VPA 和 KPA。
从 pod 主动缩放器无效利用集群最大容量的能力开始,持续应用 集群主动缩放 来减少容量。最初以跨云服务商的 无服务器 产品模式,用 简直有限的资源 (和老本) 实现了整个视角的闭环。
除了 VPA,其余技术依然建设在开发时确定容器资源耗费的致力之上。例如,HPA 不会依据没有指定限度的资源采取行动,而云服务商会间接申请调配给每个容器运行的 CPU 和内存资源。
参考文献
- Practical Kubernetes — Top Ten Challenges — Part 6: Sizing and Footprint Optimization, by Andre Tost
- You can’t have both high utilization and high reliability, by Nathan Yellin
- Vertical Pod Autoscaler deep dive, limitations and real-world examples
- Vertical Pod Autoscaling: The Definitive Guide
- Kubernetes Workload Resources
- IBM Code Engine (Managed Knative)
- AWS Fargate
你好,我是俞凡,在 Motorola 做过研发,当初在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓重的趣味,平时喜爱浏览、思考,置信继续学习、一生成长,欢送一起交流学习。微信公众号:DeepNoMind
本文由 mdnice 多平台公布