资讯详情

资讯详情

K8s资源限制+监控+Dashboard实战:构建资源治理闭环

1. 先聊清楚这三个功能为什么要放在一起搞Kubernetes后文简称K8s用得越久越会发现一个规律资源限制、资源监控、可视化面板根本不是三个独立功能而是一套完整的资源治理闭环。资源限制解决的是怎么分的问题——每个容器能拿多少CPU、多少内存超了会不会被干掉资源监控解决的是分得合不合理、跑得稳不稳的问题——实际用了多少有没有打满有没有浪费而Dashboard解决的是怎么看的问题——总不能天天Kubectl敲命令看图表吧。我接手模拟项目X的K8s集群时最直观的感受是如果只做资源限制不做监控就像只给汽车装了限速器却没有仪表盘——确实限制了速度但根本不知道发动机转速和油耗情况。反过来只做监控不做限制生产环境的Pod分分钟变成三不管的野马一台节点把整个集群拖垮的案例我见过太多。这篇文章就按这个闭环来展开把三块内容逐一拆透先讲资源限制的原理和参数配置再说监控方案怎么选、数据怎么看最后说Dashboard如何部署落地。每个部分都会给出可以直接抄作业的配置和实操经验。2. 容器资源限制不只是YAML里写几行参数2.1 先搞懂requests和limits的区别否则配置全是拍脑袋K8s的每个Pod更准确说是Pod里的每个Container都可以声明两类资源需求requests所需和limits上限。这两个词容易混淆我拿租房子来打比方就清楚了。requests是最基本的生存需求相当于你租房时承诺的最少居住面积——只有你这么要求房东kube-scheduler才能在选房子调度节点时确保能腾出这么大地方。调度器只看requests不看limits。如果节点资源不够requests这个Pod根本不会被调度上去会一直Pending等待。limits是顶格限制相当于房子的物理边界——多住一个人就住不下了谁也不能越界。CPU的limit是强制限速的内核会通过CFS调度配额把CPU使用率压在线内内存的limit更像一把铁闸门一旦超过就要被OOM Killer请出局。实际操作里最常见的错误是requests和limits设成一样或者只设limits不设requests。这会导致两种截然不同的问题——前者浪费资源后者存在巨大的超卖隐患。正确做法是理解一个原则requests决定调度和QoS等级limits决定运行时的硬上限一般情况下limits应该大于等于requests。给个我常用的基础配置参考模拟应用场景resources: requests: cpu: 250m # 0.25个CPU核 memory: 256Mi limits: cpu: 1 # 最多使用1个CPU核 memory: 1Gi2.2 为什么说CPU限制和内存限制的原理完全不同这一点非常关键理解了原理才知道为什么内存超了是OOM、CPU超了只是慢。CPU是可压缩资源。K8s底层用CFSCompletely Fair Scheduler的配额机制来实现CPU限制。容器跑的其实是节点内核的线程当容器使用的CPU时间超过limits配额后内核会强制将它节流throttled表现为CPU使用率被削平进程继续运行、变慢但不会被杀死。所以CPU超限是温和的、不影响可用性的只是延迟增加。内存是不可压缩资源。进程分配了内存页后如果超过limits内核没有限速的概念因为代码都加载到内存里了没地方放就只能走OOM Killer流程。内核会按质量等级挑一个最该杀的进程干掉——如果容器超过自己的limits那这个容器里的进程基本上是最优先被杀的K8s会把Pod标记为OOMKilled并尝试重启。经验提醒压测的时候如果看到Pod反复重启查看kubectl describe pod的输出遇到Reason: OOMKilled第一反应要查内存limits是不是设置得过紧而不是无脑加副本数。很多人一听Pod重启就上HPA自动扩缩容结果扩了发现底层OOM问题还在白费功夫。2.3 QoS等级为什么有些Pod被打死、有些只被限速K8s根据你配置的requests和limits组合会给每个Pod划分三个QoS等级之一Guaranteed、Burstable、BestEffort。这三个等级不只是标签它决定了节点内存紧张时谁的进程先被牺牲。我列个速查表QoS等级配置条件被OOM优先级适用场景Guaranteed所有容器都设置了requestslimits且不为0最低最不容易被杀核心数据库、网关、注册中心等关键服务Burstable至少一个容器设置了requests或limits且两者不同中等多数普通Web应用BestEffort完全没有设置requests和limits最高先被祭天不推荐生产环境使用仅用于开发调试我之前踩过一个典型的坑给某个Web应用只配置了limits忘了配requests。按照QoS规则只要requests和limits不同Pod就会判定为Burstable——本来可以晋级Guaranteed拿到更高生存优先级的结果白白降级了。核心服务建议直接把requests和limits设置为相同数值。虽然会牺牲一些资源利用率但换来的是稳定的性能CPU不会被节流和更高的存活优先级。我处理过的真实案例里Redis这类吞吐强烈的服务设置Guaranteed后集群在内存压力下的稳定性提升明显。2.4 资源配额一个人用多少不如一个部门分多少单容器配置毕竟只能管住个体一个团队如果把几个高limits的Pod塞到同一个Namespace里就算单容器没超Namespace总和也会失控。所以生产环境需要再上一层ResourceQuota资源配额和LimitRange默认范围。ResourceQuota可以直接限制一个Namespace下所有Pod加起来最多能请求多少CPU和内存apiVersion: v1 kind: ResourceQuota metadata: name: quota-demo namespace: demo spec: hard: requests.cpu: 10 requests.memory: 20Gi limits.cpu: 20 limits.memory: 40Gi设置之后如果该Namespace下的Pod累计requests.cpu超过10新Pod就创建不出来了。这个报错非常经典exceeded quota。LimitRange则用来兜底——给没写resources的Pod套一个默认配置防止新人漏写直接丢个BestEffort Pod进生产环境apiVersion: v1 kind: LimitRange metadata: name: limitrange-demo namespace: demo spec: limits: - default: cpu: 500m memory: 512Mi defaultRequest: cpu: 250m memory: 256Mi type: Container部署ResourceQuota和LimitRange是生产环境团队协作的基本功。只要Namespace多、团队多就必须把这两套东西配上否则过不了审计和合规检查。3. 容器资源监控得先知道平常用量才能设定合理限额3.1 只看Kubectl top你还需要理解Metrics Server的位置资源限制配置完了紧接着的问题就是我凭什么设这些数这不是拍脑袋的题得看基线数据。监控的第一步是Metrics Server。它是K8s内置的资源指标管道负责从每个节点上的kubelet采集容器和节点的CPU、内存数据然后通过Metrics API暴露出来。命令kubectl top node、kubectl top pod的数据来源就是它。可以理解成一个只负责体温、脉搏这类核心指标的基础监控组件。但Metrics Server有两个限制要注意第一它只保留最近1-5分钟的数据没有历史趋势第二它只管容量使用率不管应用层面的请求延迟、错误率这些业务指标。所以它适合做实时巡检不适合做长期分析。部署Metrics Server特别简单在模拟项目X的集群里我用官方YAML直接安装kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml需要检查一下如果集群是自签证书的或私有云环境Metrics Server的连接可能会失败这时候在Deployment的参数里加一条--kubelet-insecure-tls就行。3.2 Prometheus Grafana 才是生产环境监控的完美组合Metrics Server数据有限想看历史趋势和告警规律就得引入Prometheus。这套组合已经是K8s监控的事实标准我直接给落地思路。Prometheus抓取指标的核心机制是服务发现——它会动态发现集群里所有Pod和Service然后按规则周期性拉取/metrics接口的数据。配合kube-state-metrics采集集群对象状态比如Pod副本数、Deployment期望值再加上node-exporter采集节点级别的系统指标磁盘、网络、温度等基本就能覆盖运维所需的全部监控面。Timeline上我用的是标准架构Prometheus核心时序数据库指标采集与告警计算node-exporter采集节点操作系统层指标kube-state-metrics采集K8s对象层状态Grafana可视化面板对接Prometheus数据源Alertmanager告警路由与通知通道有现成的Kube-Prometheus-Stack也叫Prometheus Operator项目是一套全家桶部署方案一条命令就能拉起所有组件helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update helm install prometheus prometheus-community/kube-prometheus-stack装完之后默认自带全套的告警规则比如节点不可用、Pod频繁重启、PVC接近满容量、CPU负载过高等相当省心。3.3 监控数据怎么解读CPU用到了多少是不正常监控上了手接下来是看数据。生产环境里我最常用的判断标准大概是这样的——这套经验不一定适合所有业务但至少参考价值很高CPU使用率从Pod视角平均值持续超过80%而且不回落说明需要扩容或优化超过limits时出现throttled需要先看是不是limits设得太低。内存使用量关键指标是Working Set通过container_memory_working_set_bytes看真实活跃内存。通常Pod内存使用率稳定在limits的60%-80%是安全的超过90%持续波动在OOM边缘试探基本说明limits给小了或者业务有内存泄漏。节点维度单节点总CPU使用率持续超过85%有调度不均衡的可能内存使用率接近100%大概率要触发节点级别的驱逐EvictionNode上的Pod会被赶走。我常用的三条Grafana告警规则配置如下可以直接参考告警规则PromQL表达式阈值冷却时间节点CPU超过85%(1 - avg(rate(node_cpu_seconds_total{modeidle}[5m])) by (instance)) * 1008510分钟Pod CPU节流sum(increase(container_cpu_cfs_throttled_periods_total[5m])) by (pod)大于05分钟Pod内存接近limitssum(container_memory_working_set_bytes) by (pod, namespace) / sum(kube_pod_container_resource_limits{resourcememory}) by (pod, namespace) 0.990%5分钟注意第二类告警CPU节流容易被忽略但一旦出现说明应用的性能表现已经因为资源限制而打折扣了很多程序变慢的排查最终都指向这个问题。3.4 设定资源消耗基线从监控数据反推配置监控数据直接的反哺作用就是帮重新审视原来的资源限制配置。我总结了一个实操步骤先用默认配置比如requests 250m/256Mi、limits 500m/512Mi运行至少一周期间戴上Prometheus跟踪。收集P99、平均值和峰值的使用量画一条资源使用曲线。关键公式limits建议按峰值用量加20%-30%的安全余量requests建议按平均值下探30%左右给调度器留出装箱的富余空间。举例比如某应用连续七天平均CPU使用是420m峰值是600m。按照上面的经验limits至少给到780m6001.3requests可以给到300m4200.7左右留余量。这样既稳妥又不浪费。如果requests和limits最终趋近说明这个业务的资源使用很稳定直接设成Guaranteed完全合理。这套闭环完成之后资源限制数字就不再是拍脑袋了而是有监控数据支撑的理性决策。4. Dashboard部署K8s也需要一个看得见的驾驶舱4.1 一条命令部署Kubernetes Dashboard可视化部署最主流的就是Kubernetes Dashboard——官方出品的Web界面面板。K8s自己能搭载它默认不开启需要主动安装kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml安装完成后Dashboard的Service默认在kubernetes-dashboardNamespace下类型是ClusterIP集群外不能直接访问。需要加一层访问方式最常用的方法是kubectl proxy开一个本地代理kubectl proxy然后浏览器访问http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/登录会要求提供Kubeconfig文件或者Token。这里有个新手容易卡住的点Dashboard默认分配的ServiceAccount权限非常受限直接拿token登录基本什么都看不到显示一堆forbidden错误。需要创建一个管理员账号我下面详细展开。4.2 创建管理员账号与Token获取这一步卡了多少人很多教程在这块写得含糊我给出一个完整、可复制的流程。创建管理员服务的YAML命名个admin-userapiVersion: v1 kind: ServiceAccount metadata: name: admin-user namespace: kubernetes-dashboard --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: admin-user roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: admin-user namespace: kubernetes-dashboard保存为dashboard-admin.yaml并执行kubectl apply -f dashboard-admin.yaml然后获取Tokenkubectl -n kubernetes-dashboard create token admin-user这里注意有些老教程会让你先查询Secret再去解码Token。新版K8s1.24以上已经不再自动为ServiceAccount创建带Token的Secret了直接用kubectl create token更可靠。把输出的一长串Token复制粘贴到Dashboard登录页就能进去了。4.3 生产环境常用配置入口认证、域名与HTTPS开发环境用kubectl proxy看看没问题生产环境对外提供Dashboard就得认真规划了。几个经验分享不能直接暴露NodePort让Dashboard的Service以NodePort方式暴露在公网上会暴露面板端口不推荐安全风险很高。推荐通过Ingress暴露用已有的Ingress Controller比如Nginx Ingress把Dashboard绑定到指定域名上并配合证书自动签发如cert-manager配置Lets Encrypt证书完成HTTPS。这个方案兼顾了安全和易用符合生产环境预期。加一层认证Dashboard自身的Token认证已有一层还可以在上游加一层基本认证或OIDC认证避免Token泄露后无人察觉。一个Nginx Ingress配置示例仅供参考apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: dashboard-ingress namespace: kubernetes-dashboard spec: ingressClassName: nginx tls: - hosts: - k8s-dashboard.example.com secretName: dashboard-tls rules: - host: k8s-dashboard.example.com http: paths: - path: / pathType: Prefix backend: service: name: kubernetes-dashboard port: number: 4434.4 Dashboard里的高频操作部署应用、看日志、查事件面板部署好重点是怎么用。从运维视角看最有用的功能有三个。第一个是工作负载管理可以在可视化界面直接创建Deployment、修改副本数、滚动更新镜像版本。写YAML不太熟的新人可以切换到Create模式勾选参数自动生成配置。第二个是日志与事件查看Dashboard把Pod的标准输出日志整合成了图形界面省得每次进入终端。特别方便的是事件列表K8s中所有资源对象的状态变化比如ImagePullBackOff、CrashLoopBackOff、OOMKilled都会记录在事件里界面上直接能看到红色告警标识。第三个是资源缩放面板上可以直接调整Deployment的副本数量操作HPA也直观。配合前面说的监控数据看到Pod CPU干到90%顺手就在面板上扩到5个副本非常流畅。5. 常见故障排查实录三套疑难杂症与解决思路5.1 症状一Pod反复OOMKilled内存limit正确怎么办遇到过几次这样的场景Pod每次启动运行几小时就被OOMKilled但内存limit看着也合理比如设置了4Gi。上来先别着急调参打开Prometheus查container_memory_working_set_bytes的时间序列。排查步骤看Working Set是缓慢上升还是突刺。缓慢上升大概率是内存泄漏突刺要结合日志看是否是批量任务引起的临时峰值。检查JVM如果是Java应用。JVM的堆外内存Metaspace、DirectBuffer很容易被忽略容器可用的内存不能只是-Xmx参数还要留出堆外部分。调参再验证。确认是持续增长后要么提高limit要么在应用层加内存上限控制。建议先限流验证不要直接盲目加到巨量内存浪费集群资源。经验之谈线上排查OOM先看时间序列再对照应用日志最后谈调参——顺序反了经常会白改参数。5.2 症状二Metrics Server部署成功但kubectl top报错错误信息大概是Error: metrics.k8s.io/v1beta1: the server is currently unable to handle the request。排错步骤查看Metrics Server的Pod日志kubectl logs -n kube-system -l k8s-appmetrics-server如果是x509: cannot validate certificate基本是证书问题。在参数中加--kubelet-insecure-tls。如果是connection refused检查kubelet是否在监听端口。部分云厂商的节点安全组拦截了端口的10250访问让相关人员确认。如果一切正常但界面还是无数据可能需要重启一下Metrics Server的Pod让它强制重新同步。这套检查基本能覆盖九成以上的Metrics Server故障。5.3 症状三Dashboard没法登录Token粘贴过去就报错最常见原因是Token过期或者复制不完整。新版Dashboard的Token有有效期时长设置默认可能较短过期需要重新生成。其次是粘贴过程中多了空格或换行符这也是高频低级的坑。还有一点容易被忽视Dashboard是HTTPS协议如果你用了HTTP方式访问部分操作可能被浏览器拦掉。登录页要确保走的是HTTPS链路kubectl proxy方式是支持的协议不一致会莫名登录失败。6. 最后一个建议三者联动才算真正的资源治理关于这三块内容我最后再分享一个小技巧不要等出问题才想起资源限制和监控集群刚搭好就该把Metrics Server和Prometheus装上Dashboard账号建好。然后在业务压测通过后根据监控结果第一时间回填资源限制配置。这样下来新业务上线的流程就变成部署应用 → 无限制运行观察两天 → 根据Prometheus数据设定requests和limits → 在Dashboard上看到配额生效 → 后续持续监控并微调。这套流程一旦跑顺集群里基本不需要天天盯报警资源利用率和稳定性都会是舒服的状态。我个人还有一个习惯每隔一个月翻一次Grafana面板重点看各个Namespace的资源水位有没有悄悄变化。很多问题比如某团队新模块上线疯狂吃内存都是在这种例行巡检里提前发现的而不是等压垮节点后才追根溯源。资源治理这件事功夫在平时不在一朝一夕。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →