找回密码
 立即注册
首页 业界区 科技 实用脚本公开!0成本实现GitOps中Kubernetes资源自动调 ...

实用脚本公开!0成本实现GitOps中Kubernetes资源自动调优

锄淫鲷 昨天 15:04
原文发布于 CloudPilot AI
在云原生环境中,Kubernetes 资源配置是一项非常关键的工作,尤其是当你通过 GitOps 流程来管理集群时更是如此。
这篇文章会带你了解资源管理中常见的一些“坑”——比如资源预留太多配额浪费严重,或者因为资源不足而无法部署新服务。同时我们也会介绍几种不花一分钱的方法,帮你更轻松地解决这些问题。
资源配置的核心逻辑和常见挑战

Kubernetes 的资源配置,其实主要围绕两个核心机制展开:资源配额(Resource Quotas) ,以及 Pod 的请求值和限制值(Requests & Limits) 。这两者共同作用,用来限制应用对资源的占用,确保整个集群既健康又高效地运行。
1.png

资源配额(Resource Quotas)

资源配额是 Kubernetes 提供的一种控制机制,用来限定某个命名空间(namespace)下能使用的资源总量。除了 CPU 和内存这种常见资源,它还能限制比如 Pod、Service、PersistentVolumeClaim(持久化存储申请)等对象的数量。
这么做的目的很简单:防止某个团队或者服务“独占资源”,影响到其他人的正常运行。通过资源配额,平台管理员可以实现资源的公平分配,避免“抢资源大战”,同时让整个集群的性能更加可控、可预期。
2.png

资源配额带来的挑战,开发和运维团队可能深有体会:

  • 很难拿捏“刚刚好”的配额: 配得太少,服务跑不起来;配得太多,又容易浪费资源,甚至让其他服务“饿死”;
  • 配额一旦超了,成本也跟着飙升: 过度预留资源不仅烧钱,还可能让整个平台的资源利用率大打折扣;
  • 协调配额成了日常负担: 每次资源不够用,都要和平台、运维、开发多方来回沟通调整配额设置。稍微出点差错,就可能卡住部署流程,影响上线节奏。
简单来说,资源配额虽然是个好工具,但调不好反而成了团队协作和系统效率的“绊脚石”。
Pod 的 Requests 和 Limits

Pod 的 Requests 和 Limits 是用来规定容器在运行过程中可以使用的 CPU 和内存资源范围。
其中,Request 是“起步资金” ,确保容器有足够的资源顺利启动并稳定运行;而 Limit 则像“信用卡额度” ,防止某个容器过度占用资源,拖慢同一节点上的其他服务。
3.png

但在实际操作中,这部分配置常常让开发和运维团队头疼不已,主要问题包括:

  • 设置得太低时,可能导致:


    • 容器启动缓慢,或由于 CPU 不足出现响应延迟;
    • 容器因为内存不足频繁崩溃。

  • 设置得太高时,则容易:


    • 浪费资源,甚至超出命名空间的 ResourceQuota 限制;
    • 导致新 Pod 无法调度,因为节点上的资源已经被高请求值占满;
    • 拖累其他应用,造成限速(throttling)或被 OOM Kill(内存溢出强制终止)。

换句话说,设置 Requests 和 Limits 并不是“越多越好”或“越省越稳”,而是需要不断调试和权衡,找到既满足性能又不过度浪费的平衡点。
关于 Kubernetes 服务启动时所需资源激增的问题,可以查看这篇文章寻找解决方案:KubeCon 演讲文字实录 | 从瓶颈到突破:征服 Kubernetes 中的应用程序启动高峰
解决部署延迟与资源分配难题

如何判断 ResourceQuota 是否阻碍了部署

在 Kubernetes 的部署过程中,有一个非常常见、但又让人头大的问题:Pod 因为触达了资源配额上限而无法部署。这种情况往往出现在关键更新或滚动发布时,对开发者来说影响极大,甚至会直接阻断上线流程
要解决这个问题,首先得搞清楚 ResourceQuota 是如何影响部署策略的。有了这层理解,开发者就能提前预判风险,在部署前做好准备,避免临时踩坑,从而提升整个发布流程的流畅度。
举个例子,如果你设定了一个 Deployment 使用滚动更新(rolling update),但新版 Pod 一直没法跑起来,你可能会在事件日志中看到类似这样的提示信息:
  1. # kubectl get events -n recipes
  2. LAST SEEN   TYPE      REASON                  OBJECT                 MESSAGE
  3. 18s         Warning   FailedCreate            replicaset/recipes-5cb59585d4   (combined from similar events): Error creating: pods "recipes-5cb59585d4-7r78l" is forbidden: exceeded quota: compute-resources, requested: requests.cpu=250m,requests.memory=128Mi, used: requests.cpu=375m,requests.memory=384Mi, limited: requests.cpu=375m,requests.memory=384Mi 
复制代码
  1. # kubectl describe resourcequota -n recipes
  2. Name:            compute-resources
  3. Namespace:       recipes
  4. Resource         Used   Hard
  5. --------         ----   ----
  6. limits.cpu       375m   2
  7. limits.memory    384Mi  2Gi
  8. requests.cpu     375m   375m
  9. requests.memory  384Mi  384Mi 
复制代码
当你发现资源配额阻碍了部署,接下来的处理通常就比较“低效”了:团队必须手动排查当前配额使用情况,并和平台管理员协商资源调整。
这一来一回,不仅打断了工作节奏,还可能导致部署周期大幅延后。
别再靠猜来配置容器资源请求了

“我到底该设置多少资源才合适?”——这是开发过程中经常会遇到的问题,尤其是当应用还处于开发早期或者频繁变动时,更是无从下手。
大多数时候,初始的资源设置其实都是“靠感觉”,为了确保应用能跑起来,就先预留多一点,哪怕没有任何历史数据支撑。
比如说,一个 Deployment 在运行时并没有做资源监控。此时你用 kubectl top 查看,发现它只用了 5 millicores 的 CPU 和 15MB 的内存。
表面上看,一切正常。但这并不能说明它在实际压力下的表现,而这组数据也揭示了另一个问题——它现在的资源请求,可能比真实需求高出 25 倍之多
4.png

这种“过度预留”不仅浪费资源,还可能占用了本来可以分配给其他服务的空间,导致整个集群效率下降。
  1. # kubectl top pods -n recipes
  2. NAME                   CPU(cores)   MEMORY(bytes)
  3. recipes-postgresql-0   5m           15Mi
复制代码
  1. # kubectl get pods -n recipes -o json | jq '.items[] | {name: .metadata.name, limits: .spec.containers[].resources.limits, requests: .spec.containers[].resources.requests}'
  2. {  
  3. "name": "recipes-postgresql-0",  
  4. "limits": {    
  5. "cpu": "125m",    
  6. "memory": "256Mi" 
  7.    },  
  8. "requests": {    
  9. "cpu": "125m",    
  10. "memory": "256Mi"
  11.    }
复制代码
为了真正做到资源配置的“精细化”,通常需要让 Pod 在正常负载下运行一段时间,收集性能指标,再进行分析和调整,然后再把优化后的结果应用到 Pod 的配置中。
这个流程既耗时又复杂,难怪很多 Kubernetes 集群存在资源利用率偏低的问题——与其频繁调优,不如一开始就多申请点资源来得省事。
简化这个过程!

好消息是,有一些小工具和 Kubernetes 自带的能力,可以帮我们缓解这些烦恼。
脚本:检查命名空间中的 ResourceQuota 使用情况

下面这个脚本就非常实用,适合开发者或平台用户在遇到部署失败、怀疑资源配额相关问题时随时运行。
它会检查当前命名空间下所有的 ResourceQuota 使用情况,评估资源是否紧张,并根据使用率给出哪些资源项可能需要上调配额的建议。这样一来,不用等到部署挂了才发现问题,而是可以主动预警、及时处理。
  1. # KUBERNETES_DISTRIBUTION_BINARY=kubectl NAMESPACE=recipes CONTEXT=gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-cluster  bash -c "$(curl -s https://raw.githubusercontent.com/runwhen-contrib/rw-cli-codecollection/main/codebundles/k8s-namespace-healthcheck/resource_quota_check.sh)" _
复制代码
  1. Resource Quota and Usage for Namespace: recipes in Context: gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-cluster
  2. ===========================================
  3. Quota: compute-resources
  4. limits.cpu: OK ( 18 %)
  5. limits.memory: OK ( 18 %)
  6. requests.cpu: AT LIMIT  ( 100 %) - Immediately increase the resource quota for requests.cpu in recipes
  7. requests.memory: AT LIMIT  ( 100 %) - Immediately increase the resource quota for requests.memory in recipes
  8. -----------------------------------
  9. Recommended Next Steps:
  10. [
  11.   {
  12.     "remediation_type": "resourcequota_update",
  13.     "increase_percentage": "40",
  14.     "limit_type": "hard",
  15.     "current_value": "375",
  16.     "suggested_value": "525",
  17.     "quota_name": "compute-resources",
  18.     "resource": "requests.cpu",
  19.     "usage": "at or above 100%",
  20.     "severity": "1",
  21.     "next_step": "Increase the resource quota for requests.cpu in `recipes`"
  22.   },
  23.   {
  24.     "remediation_type": "resourcequota_update",
  25.     "increase_percentage": "40",
  26.     "limit_type": "hard",
  27.     "current_value": "384",
  28.     "suggested_value": "537",
  29.     "quota_name": "compute-resources",
  30.     "resource": "requests.memory",
  31.     "usage": "at or above 100%",
  32.     "severity": "1",
  33.     "next_step": "Increase the resource quota for requests.memory in `recipes`"
  34.   }
  35. ]
复制代码
自动化生成 Pod 资源请求建议

要精准地设置 Pod 需要的资源量,确实需要一段时间的监控和分析,然后再做调整。
幸运的是,Kubernetes 自带了一个非常实用的工具——Vertical Pod Autoscaler(垂直 Pod 自动伸缩器,VPA),它可以帮你解决这个问题!
Kubernetes 目前有两种弹性伸缩方式:

  • Horizontal Pod Autoscaler(水平 Pod 自动伸缩器),通过增加或减少 Pod 副本数来应对负载变化,不过这跟调整单个 Pod 的资源请求无关,没用在这里。
  • Vertical Pod Autoscaler(垂直 Pod 自动伸缩器),专门监控单个 Pod 的资源使用情况,判断是应该“扩”资源还是“缩”资源。它可以自动调整,也可以只给出建议。
针对“我到底应该设置多少资源?”这个问题,Vertical Pod Autoscaler 就很合适。
虽然自动调整运行中的 Pod 在某些场景(比如 GitOps 流程)可能不太适用,但你完全可以让它运行在 “推荐模式” ,只给出调整建议。
借助 Kubernetes 内置的指标服务,或者配合 Prometheus,VPA 能帮你做出合理的资源配置建议,大大减少猜测的盲目性。
当然,市场上还有一些更高级的资源推荐算法和工具,比如 CloudPilot AI,能实时监控集群资源使用情况,对资源利用率的节点进行资源优化,减少浪费,适合有更高要求的团队。
5.png

启用 VPA 的推荐模式

你可以很方便地按照官方文档,或者通过 Helm Chart,把 VPA 部署到正在运行的 Kubernetes 集群中。
使用 Helm Chart 的好处是灵活,可以轻松开启推荐器(recommender)功能,同时关闭自动更新(updater)和准入控制器(admissionController)这两个组件——如果你暂时不需要它们的话。
举个例子,下面是一个用于在沙箱集群中通过 FluxCD 部署 VPA 的 HelmRelease 配置示例:
  1. apiVersion: helm.toolkit.fluxcd.io/v2beta1
  2. kind: HelmRelease
  3. metadata:
  4.   name: vpa
  5.   namespace: vpa
  6. spec:
  7.   releaseName: vpa
  8.   # (https://github.com/FairwindsOps/charts/blob/master/stable/vpa/values.yaml)
  9.   chart:
  10.     spec:
  11.       chart: vpa
  12.       sourceRef:
  13.         kind: HelmRepository
  14.         name: fairwinds-stable
  15.         namespace: flux-system
  16.   interval: 5m
  17.   values:
  18.     recommender:
  19.       enabled: true
  20.     updater:
  21.       enabled: false
  22.     admissionController:
  23.       enabled: false
复制代码
配置 VPA 为指定 Deployment 提供资源推荐

在成功部署 VPA 后,你可以创建一个 VerticalPodAutoscaler 资源清单,指定它要监控哪个 Deployment,并且只生成资源配置的推荐,而不会自动修改 Pod。
比如,下面这个 VPA 配置示例就是针对某个特定 Deployment,只输出资源调整建议,避免自动变更 Pod。这对于使用 GitOps 管理的环境来说非常重要,能保证配置变更都在版本控制之下,避免自动更新带来的不确定性。
  1. apiVersion: autoscaling.k8s.io/v1
  2. kind: VerticalPodAutoscaler
  3. metadata:
  4.   name: recipes-vpa
  5. spec:
  6.   targetRef:
  7.     apiVersion: "apps/v1"
  8.     kind: Deployment
  9.     name: recipes
  10.   updatePolicy:
  11.     updateMode: "Off"   #Set to off since the 'recipes' deployment manifest is managed with GitOps
复制代码
脚本:自动获取命名空间内 Pod 的资源推荐

有了 VPA 之后,这个脚本可以帮助开发者自动查询当前命名空间中各个 Pod 的资源推荐情况。
需要注意的是,虽然 VPA 本身提供了接口可以直接查询推荐结果,但这些数据通常比较原始,需要进一步解读并转化为具体的调整方案
这个脚本就是为了解决这个问题,它会整理出详细的推荐信息和配置变更建议,方便自动化处理和后续执行。
  1. # KUBERNETES_DISTRIBUTION_BINARY=kubectl NAMESPACE=recipes CONTEXT=gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-cluster LABELS=  bash -c "$(curl -s https://raw.githubusercontent.com/runwhen-contrib/rw-cli-codecollection/main/codebundles/k8s-podresources-health/vpa_recommendations.sh)" _
  2. VPA Recommendations for Namespace: recipes for Context: gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-cluster
  3. ===========================================
  4. Recommendation for recipes-nginx in Deployment recipes: Adjust CPU request from 125 to 20 millicores
  5. Recommendation for recipes-nginx in Deployment recipes: Adjust Memory request from 64 to 50 Mi
  6. Recommendation for recipes in Deployment recipes: Adjust CPU request from 125 to 20 millicores
  7. Recommendation for recipes in Deployment recipes: Adjust Memory request from 64 to 50 Mi
  8. Recommended Next Steps:
  9. [
  10.   {
  11.     "remediation_type": "resource_request_update",
  12.     "vpa_name": "recipes-vpa",
  13.     "resource": "cpu",
  14.     "current_value": "125",
  15.     "suggested_value": "20",
  16.     "object_type": "Deployment",
  17.     "object_name": "recipes",
  18.     "container": "recipes-nginx",
  19.     "severity": "4",
  20.     "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust CPU request from 125 to 20 millicores"
  21.   },
  22.   {
  23.     "remediation_type": "resource_request_update",
  24.     "vpa_name": "recipes-vpa",
  25.     "resource": "memory",
  26.     "current_value": "64",
  27.     "suggested_value": "50",
  28.     "object_type": "Deployment",
  29.     "object_name": "recipes",
  30.     "container": "recipes-nginx",
  31.     "severity": "4",
  32.     "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust Memory request from 64 to 50 Mi"
  33.   },
  34.   {
  35.     "remediation_type": "resource_request_update",
  36.     "vpa_name": "recipes-vpa",
  37.     "resource": "cpu",
  38.     "current_value": "125",
  39.     "suggested_value": "20",
  40.     "object_type": "Deployment",
  41.     "object_name": "recipes",
  42.     "container": "recipes",
  43.     "severity": "4",
  44.     "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust CPU request from 125 to 20 millicores"
  45.   },
  46.   {
  47.     "remediation_type": "resource_request_update",
  48.     "vpa_name": "recipes-vpa",
  49.     "resource": "memory",
  50.     "current_value": "64",
  51.     "suggested_value": "50",
  52.     "object_type": "Deployment",
  53.     "object_name": "recipes",
  54.     "container": "recipes",
  55.     "severity": "4",
  56.     "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust Memory request from 64 to 50 Mi"
  57.   }
  58. ]
复制代码
将资源调优融入GitOps流水线

前面提到的脚本帮你找出了哪些资源配置需要调整,以及具体该怎么改,最后一步就是把这些推荐结果整合进 GitOps 流水线里。
虽然不同团队的 GitOps 流程会有所差异,但一般来说,可以把脚本输出中“Recommended Next Steps”(推荐的后续操作)部分的 JSON 内容提取出来,传给一个自动化脚本。
这个脚本会根据推荐内容更新 GitOps 代码仓库,并通过既有的审批流程通知相关负责人,确保资源调整变更有序、安全地落地。这样一来,资源配置的优化就能无缝融入日常的开发和交付节奏。
6.png

举个例子,这个脚本(https://github.com/runwhen-contrib/rw-cli-codecollection/blob/main/codebundles/k8s-gitops-gh-remediate/update_github_manifests.sh)适用于存放在 GitHub 上的 GitOps 仓库,兼容 ArgoCD 和 FluxCD 两种 GitOps 引擎。它的工作流程大致如下:

  • 首先识别负责管理资源的 GitOps 控制器(FluxCD 或 ArgoCD);
  • 获取对应的 Git 仓库地址以及存放 Kubernetes 清单(manifest)文件的路径;
  • 解析输入的 JSON,识别需要修正的资源操作,并按类型分类,比如资源配额更新、资源请求建议、PVC 容量扩容等;
  • 针对每个需要修正的操作,动态生成对应的 YAML 文件变更内容;
  • 克隆目标 Git 仓库,创建一个新的分支,将修改后的 YAML 文件写入并提交;
  • 自动生成一份详细的 Pull Request(PR)说明,阐述修改原因并附带相关信息链接,然后发起针对主分支的 PR;
  • 最后输出 PR 链接,方便团队成员进行代码审查和审批。
这个流程让资源调优的变更能自动、有序地推进,减少人工干预和出错风险。
7.png

总  结

资源管理,特别是在性能和成本之间找到最佳平衡,对处于生产环境的平台来说确实是一项复杂的挑战。本文介绍了一些免费且实用的脚本和工具,适合作为平台或应用团队入门的参考。
目前市面上也有许多厂商投入大量资源,提供更深入的应用使用洞察和资源调优方案,比如 CloudPilot AI (我们即将推出一个全新的Dashboard,将带来更直观的成本监控体验,敬请期待!) ,这些方案尤其适合规模大、环境复杂的场景。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册