拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Kubernetes生产运维12:Requests和Limits到底怎么设,才不会既浪费又被驱逐

Kubernetes生产运维12Requests和Limits到底怎么设才不会既浪费又被驱逐写在前面Requests和Limits是每个Pod都要填的两个数字但很多人是凭感觉填的要么照抄一个模板要么设得很大图省事要么干脆不设。这两个数字其实决定了很多事Pod能不能调度上去、会不会浪费资源、节点紧张时会不会被赶走、超用时是被限流还是被杀。设错了轻则浪费成本重则关键服务在节点压力下先被驱逐。这篇讲清楚requests和limits各自决定什么三种QoS等级怎么判定、节点压力时谁先被驱逐CPU超限和内存超限的后果完全不同到底该怎么设这两个数字这不是纯排障而是资源配置的设计方法但同样用证据和机制说话。本文按照Kubernetes官方机制整理。由于当前没有连接可验证的实验集群配置和输出均为C级生产化重建不是生产原始记录。不同版本、cgroup、CPU管理策略可能影响细节落地前应结合实际负载和监控调整。一、requests和limits各自决定什么1.1 requests保底和调度依据requests是容器至少需要的资源它决定两件事调度调度器按节点可分配资源减去已有Pod的requests之和判断新Pod放不放得下。它看的是requests账本不是实时用量这点第03篇讲过。QoS判定requests和limits的关系决定QoS等级影响驱逐顺序。requests不是限制容器可以用超过requests的量如果节点有空闲。1.2 limits上限limits是容器最多能用的资源由内核cgroup强制CPU超limit被限流throttle变慢但不被杀内存超limit被OOMKilled直接杀掉这个区别很重要下面第三节展开。1.3 两者的关系只设requests不设limits容器可以用到节点上限容易挤占别人只设limits不设requestsKubernetes通常把requests默认设为等于limits都不设BestEffort节点压力时最先被驱逐requests等于limitsGuaranteed最稳二、三种QoS等级QoS服务质量等级由requests和limits的关系自动判定Pod创建时确定、不可更改。2.1 三种等级的判定QoS判定条件稳定性Guaranteed每个容器的CPU和内存都设了requests和limits且requests等于limits最高Burstable至少一个容器设了requests或limits但不满足Guaranteed中等BestEffort所有容器都没设requests和limits最低查看某个Pod的QoSkubectl get podpod-name-nnamespace-ojsonpath{.status.qosClass}{\n}2.2 QoS决定节点压力时的驱逐顺序节点内存压力触发驱逐时kubelet大致按这个顺序赶Pod先赶BestEffort没设资源的再赶超出requests较多的Burstable最后才考虑Guaranteed所以关键服务应该设成Guaranteed或至少requests合理的Burstable降低被驱逐概率不设资源的BestEffort在节点紧张时最危险最先被赶走超出requests越多的Burstable越靠前被驱逐2.3 QoS不能靠resize改变QoS在Pod创建时确定即使后来原地调整资源也不改变QoS等级。想改QoS要重建Pod。三、CPU超限和内存超限一个限流一个被杀这是资源配置里最容易混淆的点。3.1 CPU是可压缩资源超限被限流CPU是可压缩资源。容器CPU用量顶到limit时内核不会杀它而是限流CPU throttling给它的CPU时间片被压缩表现为变慢、延迟升高但进程活着。后果CPU limit设太小应用会莫名变慢但看不到崩溃或OOM排查CPU问题要看throttling指标而不是等它崩3.2 内存是不可压缩资源超限被杀内存是不可压缩资源。容器内存用量超过limit时内核OOM killer直接杀掉进程Reason为OOMKilled退出码通常137这点第05篇详细讲过。后果内存limit设太小应用会被反复OOMKilled、CrashLoopBackOff内存问题是硬性的超了就杀没有限流这种缓冲3.3 这个区别对配置的影响CPU limit可以适当宽松甚至有观点认为对某些延迟敏感服务不设CPU limit避免限流但要评估对同节点其他Pod的影响内存limit要设得贴近真实峰值并留余量太小会被杀太大浪费且降低调度密度CPU设太小的症状是变慢内存设太小的症状是被杀排查方向不同四、到底怎么设这两个数字4.1 用真实用量而不是拍脑袋设置的依据应该是历史监控里的真实用量requests设成日常稳定用量如P50到P90的工作集保证调度合理又不过度占坑CPU limit设成能容忍的峰值或对延迟敏感服务谨慎评估是否设内存limit设成真实峰值加合理余量避免OOM没有监控数据时先给保守值上线再根据实际用量收敛而不是一开始就拍一个大数字。4.2 按服务重要性分级关键有状态服务、核心链路Guaranteedrequests等于limits最稳一般无状态服务Burstablerequests按稳定用量、limits留弹性批处理、可中断任务可以用较低优先级容忍被驱逐4.3 别把requests设成0或不设不设requests的BestEffort在节点压力时最先被赶走关键服务绝不能这样配。requests设太小也会让调度器误判节点还能塞更多Pod造成超卖和驱逐。4.4 注意超卖集群常见做法是limits之和大于节点容量超卖赌大家不会同时用满。这能提高利用率但节点真的被用满时会触发OOM和驱逐。超卖比例要根据业务波动和QoS分布谨慎设定关键服务用Guaranteed保护。五、C级生产化重建案例内存limit过小导致关键服务被反复驱逐5.1 先说明哪些是真的哪些是重建的下面不是作者声称亲历的生产事故而是根据Kubernetes QoS和驱逐机制构造的生产化重建。内容证据属性requests、limits、QoS和驱逐顺序的机制Kubernetes官方机制关键服务因QoS低在节点压力时被驱逐机制一致的重建场景Namespace、资源名、数值和终端输出为讲解构造的说明性信息关键服务未设requests导致BestEffort模拟根因不是作者生产记录设置合理requests和limits后验证不再被驱逐受控验证设计不声称已在当前集群执行所有输出按真实对象关系编排但没有连接实际集群采集读者不能把下面的数值引用为真实事故数据。5.2 现场卡片一个核心服务在节点资源紧张时反复被驱逐Evicted而同节点一些不重要的服务反而活着。团队最初怀疑是节点资源不够要扩容。重建的相对时间线相对时间观察或动作当时能够得出的结论T00核心服务Pod被Evicted存在驱逐原因未知T02怀疑节点资源不足待验证假设T04发现被驱逐的是核心服务不重要的反而在转向QoS和驱逐顺序T06核心服务QoS是BestEffort得到可验证的主假设T验证设置合理requests和limits后观察单变量验证相对时间只表示排查顺序不代表真实数值。5.3 确认是驱逐且顺序反常NSexample-prod kubectl get pods-n$NS-owide|grep-ievicted kubectl get pod core-api-xxxx-n$NS\-ojsonpath{.status.phase}{\t}{.status.reason}{\n}机制一致的说明性输出core-api-xxxx 0/1 Evicted ... Failed Evicted核心服务被Evicted而同节点不重要的服务还在这个顺序反常指向QoS。5.4 查QoS和资源配置kubectl get pod core-api-yyyy-n$NS-ojsonpath{.status.qosClass}{\n}kubectl get pod core-api-yyyy-n$NS\-ojsonpath{range .spec.containers[*]}{.name}{ req}{.resources.requests}{ lim}{.resources.limits}{\n}{end}机制一致的说明性输出BestEffort core-api reqmap[] limmap[]关键发现核心服务既没设requests也没设limitsQoS是BestEffort节点内存压力时最先被驱逐。而那些不重要的服务反而设了requestsQoS更高。证据链核心服务被Evicted不重要服务存活 核心服务未设requests和limits QoS为BestEffort BestEffort在节点压力时最先被驱逐 强烈支持QoS过低导致核心服务优先被驱逐这仍是主假设验证前不写成根因已闭环。真正要扩容与否是另一个问题但当前现象的直接原因是QoS。5.5 止损与单变量验证单变量修正给核心服务按真实用量设置requests和limits提升QoS。不同时扩容节点或改副本先验证QoS是不是主因resources:requests:cpu:500mmemory:512Milimits:cpu:1memory:512Mi# 内存requests等于limits配合CPU也相等则为Guaranteed如果CPU和内存的requests都等于limitsQoS会变成Guaranteed如果只想要Burstable也至少要设合理requests脱离BestEffort。验证并保存修复后证据kubectl rollout status deployment/core-api-n$NS--timeout5m kubectl get pod core-api-zzzz-n$NS-ojsonpath{.status.qosClass}{\n}kubectl get pods-n$NS|grep-ievicted|grepcore-api||echo核心服务无新驱逐机制一致的说明性输出deployment core-api successfully rolled out Guaranteed 核心服务无新驱逐QoS从BestEffort升到Guaranteed后节点压力时核心服务不再最先被驱逐。这些输出分别证明不同范围的事实输出能够支持不能单独证明QoS变Guaranteed驱逐优先级提升节点容量一定充足核心服务无新驱逐QoS修正生效极端压力下绝不被驱逐rollout成功配置已下发所有服务QoS都合理5.6 根因闭环条件修正只有设置requests和limits提升QoS这一项主要变量。修正后核心服务QoS提升不再优先被驱逐。现象是核心被驱逐、次要存活符合QoS驱逐顺序。没有靠扩容就缓解了核心服务的驱逐。观察窗口内再遇节点压力核心服务不再最先被赶。如果提升QoS后核心服务仍被驱逐就要停止把QoS当唯一原因检查节点是否真的容量严重不足需要扩容或重新规划。六、资源配置要分层层次配置动作关键边界分级关键服务Guaranteed一般服务合理Burstable可中断任务低优先级关键服务绝不用BestEffort按实际设requests按稳定用量内存limit按真实峰值加余量数字来自监控而非拍脑袋CPU与内存区别对待内存limit贴合峰值防OOMCPU limit谨慎防限流CPU超限变慢内存超限被杀超卖控制超卖比例按波动和QoS分布设定关键服务用Guaranteed保护监控监控利用率、限流、OOM和驱逐区分浪费和不足治理requests/limits纳入模板和容量评审定期按真实用量收敛一个平衡requests设太大浪费成本、降低调度密度设太小会超卖过度、节点压力时被驱逐。核心是用真实监控数据设置并按服务重要性分级。七、资源配置检查清单QoS分级 [ ] 关键服务是否是Guaranteed或合理的Burstable [ ] 有没有关键服务是BestEffort必须否 按实际设置 [ ] requests是否来自历史监控的稳定用量 [ ] 内存limit是否按真实峰值加余量避免OOM [ ] CPU limit是否评估过限流影响 区别对待 [ ] 是否理解CPU超限限流、内存超限被杀 [ ] 内存问题往OOM查CPU问题往限流查 超卖 [ ] 超卖比例是否评估过业务波动 [ ] 节点被用满时哪些Pod会先被驱逐是否清楚 监控 [ ] 是否监控利用率、CPU限流、OOM和驱逐八、监控与治理8.1 监控什么各工作负载的CPU、内存利用率与requests/limits的比值CPU限流throttling指标OOMKilled次数Pod被Evicted事件和节点压力各QoS等级的分布告警要能区分浪费用量远低于requests和不足贴近或超过limits两者治理方向相反。8.2 治理requests和limits纳入工作负载模板关键服务默认Guaranteed定期按真实用量收敛资源配置避免长期浪费或不足超卖策略和QoS分布纳入容量评审用VerticalPodAutoscaler等工具辅助推荐资源评估后使用九、常见误区误区1requests和limits随便填它们决定调度、QoS和驱逐填错会浪费或被驱逐。误区2关键服务不设资源不设是BestEffort节点压力时最先被赶走。误区3以为CPU超限也会被杀CPU超限是限流变慢不被杀被杀的是内存超限。误区4内存limit设太小会反复OOMKilled和CrashLoopBackOff。误区5requests设太大浪费成本降低调度密度。误区6以为resize能改QoSQoS创建时确定改资源不改QoS要重建。误区7无脑超卖节点被用满时触发OOM和驱逐超卖要评估。误区8配完不监控利用率不监控就无法区分浪费和不足也发现不了限流和OOM。十、面试怎么说60秒版本requests决定调度和QoSlimits是上限。CPU超limit是限流变慢内存超limit是OOMKilled被杀这个区别很关键。QoS分三级requests等于limits是Guaranteed最稳设了部分是Burstable什么都不设是BestEffort最先被驱逐。所以关键服务要设成Guaranteed或合理Burstable绝不能是BestEffort。数字要按历史监控的真实用量设内存limit贴合峰值防OOMrequests别太大浪费也别太小超卖。最后监控利用率、限流、OOM和驱逐。3分钟场景版本假设核心服务在节点紧张时反复被驱逐而同节点不重要的服务反而活着。这个顺序反常我先看QoS发现核心服务既没设requests也没设limits是BestEffort而BestEffort在节点内存压力时最先被驱逐。根因不是节点容量绝对不够而是核心服务QoS太低。我给它按真实用量设requests和limits让CPU和内存的requests等于limitsQoS升到Guaranteed只改这一个变量。之后节点再有压力核心服务不再最先被赶。这体现了资源配置的核心requests和limits不只是数字它们通过QoS决定了谁在压力下被牺牲。关键服务必须用QoS保护而不是靠扩容掩盖配置问题。十一、延伸问答1. requests和limits最本质的区别requests是保底和调度依据、决定QoSlimits是上限、由内核强制。2. CPU和内存超限后果一样吗不一样。CPU超限被限流变慢内存超限被OOMKilled杀掉。3. QoS怎么判定requests等于limits是Guaranteed设了部分是Burstable都不设是BestEffort。4. 节点压力时谁先被驱逐先BestEffort再超出requests多的Burstable最后Guaranteed。5. 关键服务该用什么QoSGuaranteed或至少requests合理的Burstable绝不用BestEffort。6. requests设大了有什么坏处浪费成本降低调度密度让节点看起来更满。7. 超卖安全吗提高利用率但有风险节点被用满时触发OOM和驱逐要按波动和QoS评估。8. resize能改QoS吗不能QoS创建时确定要改得重建Pod。小结requests决定调度和QoSlimits是内核强制的上限。CPU超限被限流变慢内存超限被OOMKilled后果完全不同。QoS分Guaranteed、Burstable、BestEffort决定驱逐顺序。关键服务用Guaranteed或合理Burstable绝不用BestEffort。数字按历史监控真实用量设内存limit贴合峰值防OOM。requests太大浪费太小超卖要平衡。QoS创建时确定改资源不改QoS。监控要区分浪费和不足覆盖限流、OOM和驱逐。下一篇预告下一篇进入RBAC最小权限与权限排查。我们会讲清Subject、Role、Binding和ServiceAccount的关系用can-i排查权限并整理一份权限排查清单。参考资料Kubernetes官方文档Resource Management for Pods and ContainersKubernetes官方文档Pod Quality of Service ClassesKubernetes官方文档Node-pressure EvictionKubernetes官方文档Assign Memory Resources to Containers and PodsKubernetes官方文档Assign CPU Resources to Containers and PodsKubernetes官方文档Configure Quality of Service for PodsKubernetes官方文档Control CPU Management Policies on the NodeKubernetes官方文档Limit RangesKubernetes官方文档Resource QuotasKubernetes官方文档Vertical Pod Autoscaling
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门