钱益兵 發表於 2026-5-5 20:43:57

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

<p><em>原文发布于 CloudPilot AI</em></p>
<p>在云原生环境中,Kubernetes 资源配置是一项非常关键的工作,尤其是当你通过 GitOps 流程来管理集群时更是如此。</p>
<p>这篇文章会带你了解资源管理中常见的一些“坑”——比如<strong>资源预留太多</strong>,<strong>配额浪费严重</strong>,或者<strong>因为资源不足而无法部署新服务</strong>。同时我们也会介绍几种不花一分钱的方法,帮你更轻松地解决这些问题。</p>
<h2 id="资源配置的核心逻辑和常见挑战"><strong>资源配置的核心逻辑和常见挑战</strong></h2>
<p>Kubernetes 的资源配置,其实主要围绕两个核心机制展开:<strong>资源配额(Resource Quotas)</strong> ,以及 <strong>Pod 的请求值和限制值(Requests &amp; Limits)</strong> 。这两者共同作用,用来限制应用对资源的占用,确保整个集群既健康又高效地运行。</p>
<p><img src="https://img2024.cnblogs.com/blog/3543217/202507/3543217-20250721103118462-331858888.png"></p>
<h3 id="资源配额resource-quotas"><strong>资源配额(Resource Quotas)</strong></h3>
<p>资源配额是 Kubernetes 提供的一种控制机制,用来限定某个命名空间(namespace)下能使用的资源总量。除了 CPU 和内存这种常见资源,它还能限制比如 Pod、Service、PersistentVolumeClaim(持久化存储申请)等对象的数量。</p>
<p>这么做的目的很简单:<strong>防止某个团队或者服务“独占资源”,影响到其他人的正常运行</strong>。通过资源配额,平台管理员可以实现资源的公平分配,避免“抢资源大战”,同时让整个集群的性能更加可控、可预期。</p>
<p><img src="https://img2024.cnblogs.com/blog/3543217/202507/3543217-20250721103128100-1956858449.png"></p>
<p>资源配额带来的挑战,开发和运维团队可能深有体会:</p>
<ul>
<li>
<p><strong>很难拿捏“刚刚好”的配额:</strong> 配得太少,服务跑不起来;配得太多,又容易浪费资源,甚至让其他服务“饿死”;</p>
</li>
<li>
<p><strong>配额一旦超了,成本也跟着飙升:</strong> 过度预留资源不仅烧钱,还可能让整个平台的资源利用率大打折扣;</p>
</li>
<li>
<p><strong>协调配额成了日常负担:</strong> 每次资源不够用,都要和平台、运维、开发多方来回沟通调整配额设置。稍微出点差错,就可能卡住部署流程,影响上线节奏。</p>
</li>
</ul>
<p>简单来说,资源配额虽然是个好工具,但调不好反而成了团队协作和系统效率的“绊脚石”。</p>
<h3 id="pod-的-requests-和-limits"><strong>Pod 的 Requests 和 Limits</strong></h3>
<p>Pod 的 <code>Requests</code> 和 <code>Limits</code> 是用来规定容器在运行过程中可以使用的 CPU 和内存资源范围。</p>
<p>其中,<strong>Request 是“起步资金”</strong> ,确保容器有足够的资源顺利启动并稳定运行;而&nbsp;<strong>Limit 则像“信用卡额度”</strong> ,防止某个容器过度占用资源,拖慢同一节点上的其他服务。</p>
<p><img src="https://img2024.cnblogs.com/blog/3543217/202507/3543217-20250721103137110-1388614083.png"></p>
<p>但在实际操作中,这部分配置常常让开发和运维团队头疼不已,主要问题包括:</p>
<ul>
<li>
<p>设置得太低时,可能导致:</p>
</li>
<li>
<ul>
<li>
<p>容器启动缓慢,或由于 CPU 不足出现响应延迟;</p>
</li>
<li>
<p>容器因为内存不足频繁崩溃。</p>
</li>
</ul>
</li>
<li>
<p>设置得太高时,则容易:</p>
</li>
<li>
<ul>
<li>浪费资源,甚至超出命名空间的 ResourceQuota 限制;</li>
<li>导致新 Pod 无法调度,因为节点上的资源已经被高请求值占满;</li>
<li>拖累其他应用,造成限速(throttling)或被 OOM Kill(内存溢出强制终止)。</li>
</ul>
</li>
</ul>
<p>换句话说,设置 Requests 和 Limits 并不是“越多越好”或“越省越稳”,而是需要不断调试和权衡,找到既满足性能又不过度浪费的平衡点。</p>
<p>关于&nbsp;Kubernetes 服务启动时所需资源激增的问题,可以查看这篇文章寻找解决方案:KubeCon 演讲文字实录 | 从瓶颈到突破:征服 Kubernetes 中的应用程序启动高峰</p>
<h2 id="解决部署延迟与资源分配难题"><strong>解决部署延迟与资源分配难题</strong></h2>
<h3 id="如何判断-resourcequota-是否阻碍了部署"><strong>如何判断 ResourceQuota 是否阻碍了部署</strong></h3>
<p>在 Kubernetes 的部署过程中,有一个非常常见、但又让人头大的问题:Pod 因为触达了资源配额上限而无法部署。这种情况往往出现在关键更新或滚动发布时,对开发者来说影响极大,<strong>甚至会直接阻断上线流程</strong>。</p>
<p>要解决这个问题,首先得搞清楚 ResourceQuota 是如何影响部署策略的。有了这层理解,开发者就能提前预判风险,在部署前做好准备,避免临时踩坑,从而提升整个发布流程的流畅度。</p>
<p>举个例子,如果你设定了一个 Deployment 使用滚动更新(rolling update),但新版 Pod 一直没法跑起来,你可能会在事件日志中看到类似这样的提示信息:</p>
<pre><code># kubectl get events -n recipes
LAST&nbsp;SEEN &nbsp; TYPE &nbsp; &nbsp; &nbsp;REASON &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;OBJECT &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; MESSAGE
18s&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Warning &nbsp; FailedCreate &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;replicaset/recipes-5cb59585d4 &nbsp; (combined from similar events): Error creating: pods&nbsp;"recipes-5cb59585d4-7r78l"&nbsp;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&nbsp;
</code></pre>
<pre><code># kubectl describe resourcequota -n recipes
Name: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;compute-resources
Namespace: &nbsp; &nbsp; &nbsp; recipes
Resource &nbsp; &nbsp; &nbsp; &nbsp; Used &nbsp; Hard
--------&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;----&nbsp; &nbsp;----
limits.cpu &nbsp; &nbsp; &nbsp;&nbsp;375m &nbsp;&nbsp;2
limits.memory &nbsp; &nbsp;384Mi&nbsp;&nbsp;2Gi
requests.cpu &nbsp; &nbsp;&nbsp;375m &nbsp;&nbsp;375m
requests.memory &nbsp;384Mi&nbsp;&nbsp;384Mi&nbsp;
</code></pre>
<p>当你发现资源配额阻碍了部署,接下来的处理通常就比较“低效”了:团队必须手动排查当前配额使用情况,并和平台管理员协商资源调整。</p>
<p>这一来一回,不仅打断了工作节奏,还可能导致部署周期大幅延后。</p>
<h3 id="别再靠猜来配置容器资源请求了"><strong>别再靠猜来配置容器资源请求了</strong></h3>
<p>“我到底该设置多少资源才合适?”——这是开发过程中经常会遇到的问题,尤其是当应用还处于开发早期或者频繁变动时,更是无从下手。</p>
<p>大多数时候,初始的资源设置其实都是“靠感觉”,为了确保应用能跑起来,就先预留多一点,哪怕没有任何历史数据支撑。</p>
<p>比如说,一个 Deployment 在运行时并没有做资源监控。此时你用&nbsp;<code>kubectl top</code>&nbsp;查看,发现它只用了 5 millicores 的 CPU 和 15MB 的内存。</p>
<p>表面上看,一切正常。但这并不能说明它在实际压力下的表现,而这组数据也揭示了另一个问题——<strong>它现在的资源请求,可能比真实需求高出 25 倍之多</strong>。</p>
<p><img src="https://img2024.cnblogs.com/blog/3543217/202507/3543217-20250721103339114-305879929.png"></p>
<p>这种“过度预留”不仅浪费资源,还可能占用了本来可以分配给其他服务的空间,导致整个集群效率下降。</p>
<pre><code># kubectl top pods -n recipes
NAME&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CPU(cores) &nbsp; MEMORY(bytes)
recipes-postgresql-0&nbsp; &nbsp;5m &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;15Mi
</code></pre>
<pre><code># kubectl get pods -n recipes -o json | jq '.items[] | {name: .metadata.name, limits: .spec.containers[].resources.limits, requests: .spec.containers[].resources.requests}'
{&nbsp;&nbsp;
"name":&nbsp;"recipes-postgresql-0",&nbsp;&nbsp;
"limits": {&nbsp; &nbsp;&nbsp;
"cpu":&nbsp;"125m",&nbsp; &nbsp;&nbsp;
"memory":&nbsp;"256Mi"&nbsp;
   },&nbsp;&nbsp;
"requests": {&nbsp; &nbsp;&nbsp;
"cpu":&nbsp;"125m",&nbsp; &nbsp;&nbsp;
"memory":&nbsp;"256Mi"
   }
}&nbsp;
</code></pre>
<p>为了真正做到资源配置的“精细化”,通常需要让 Pod 在正常负载下运行一段时间,收集性能指标,再进行分析和调整,然后再把优化后的结果应用到 Pod 的配置中。</p>
<p>这个流程既耗时又复杂,难怪<strong>很多 Kubernetes 集群存在资源利用率偏低的问题</strong>——与其频繁调优,不如一开始就多申请点资源来得省事。</p>
<h2 id="简化这个过程"><strong>简化这个过程!</strong></h2>
<p>好消息是,有一些小工具和 Kubernetes 自带的能力,可以帮我们缓解这些烦恼。</p>
<h3 id="脚本检查命名空间中的-resourcequota-使用情况"><strong>脚本:检查命名空间中的 ResourceQuota 使用情况</strong></h3>
<p>下面这个脚本就非常实用,适合开发者或平台用户在遇到部署失败、怀疑资源配额相关问题时随时运行。</p>
<p>它会<strong>检查当前命名空间下所有的 ResourceQuota 使用情况</strong>,评估资源是否紧张,并根据使用率给出哪些资源项可能需要上调配额的建议。这样一来,不用等到部署挂了才发现问题,而是可以主动预警、及时处理。</p>
<pre><code> # KUBERNETES_DISTRIBUTION_BINARY=kubectl NAMESPACE=recipes CONTEXT=gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-clusterbash -c "$(curl -s https://raw.githubusercontent.com/runwhen-contrib/rw-cli-codecollection/main/codebundles/k8s-namespace-healthcheck/resource_quota_check.sh)" _
</code></pre>
<pre><code> Resource Quota and Usage for Namespace: recipes in Context: gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-cluster
===========================================
Quota: compute-resources
limits.cpu: OK ( 18 %)
limits.memory: OK ( 18 %)
requests.cpu: AT LIMIT( 100 %) - Immediately increase the resource quota for requests.cpu in recipes
requests.memory: AT LIMIT( 100 %) - Immediately increase the resource quota for requests.memory in recipes
-----------------------------------
Recommended Next Steps:
[
{
    "remediation_type": "resourcequota_update",
    "increase_percentage": "40",
    "limit_type": "hard",
    "current_value": "375",
    "suggested_value": "525",
    "quota_name": "compute-resources",
    "resource": "requests.cpu",
    "usage": "at or above 100%",
    "severity": "1",
    "next_step": "Increase the resource quota for requests.cpu in `recipes`"
},
{
    "remediation_type": "resourcequota_update",
    "increase_percentage": "40",
    "limit_type": "hard",
    "current_value": "384",
    "suggested_value": "537",
    "quota_name": "compute-resources",
    "resource": "requests.memory",
    "usage": "at or above 100%",
    "severity": "1",
    "next_step": "Increase the resource quota for requests.memory in `recipes`"
}
]
</code></pre>
<h3 id="自动化生成-pod-资源请求建议"><strong>自动化生成 Pod 资源请求建议</strong></h3>
<p>要精准地设置 Pod 需要的资源量,确实需要一段时间的监控和分析,然后再做调整。</p>
<p>幸运的是,Kubernetes 自带了一个非常实用的工具——Vertical Pod Autoscaler(垂直 Pod 自动伸缩器,VPA),它可以帮你解决这个问题!</p>
<p>Kubernetes 目前有两种弹性伸缩方式:</p>
<ul>
<li><strong>Horizontal Pod Autoscaler</strong>(水平 Pod 自动伸缩器),通过增加或减少 Pod 副本数来应对负载变化,不过这跟调整单个 Pod 的资源请求无关,没用在这里。</li>
<li><strong>Vertical Pod Autoscaler</strong>(垂直 Pod 自动伸缩器),专门监控单个 Pod 的资源使用情况,判断是应该“扩”资源还是“缩”资源。它可以自动调整,也可以只给出建议。</li>
</ul>
<p>针对“我到底应该设置多少资源?”这个问题,Vertical Pod Autoscaler 就很合适。</p>
<p>虽然自动调整运行中的 Pod 在某些场景(比如 GitOps 流程)可能不太适用,但你完全可以让它运行在 <strong>“推荐模式”</strong> ,只给出调整建议。</p>
<p>借助 Kubernetes 内置的指标服务,或者配合 Prometheus,VPA 能帮你做出合理的资源配置建议,大大减少猜测的盲目性。</p>
<p>当然,市场上还有一些更高级的资源推荐算法和工具,比如 CloudPilot AI,能实时监控集群资源使用情况,对资源利用率的节点进行资源优化,减少浪费,适合有更高要求的团队。</p>
<p><img src="https://img2024.cnblogs.com/blog/3543217/202507/3543217-20250721103213557-230238650.png"></p>
<h3 id="启用-vpa-的推荐模式"><strong>启用 VPA 的推荐模式</strong></h3>
<p>你可以很方便地按照官方文档,或者通过 Helm Chart,把 VPA 部署到正在运行的 Kubernetes 集群中。</p>
<p>使用 Helm Chart 的好处是灵活,可以轻松开启推荐器(recommender)功能,同时关闭自动更新(updater)和准入控制器(admissionController)这两个组件——如果你暂时不需要它们的话。</p>
<p>举个例子,下面是一个用于在沙箱集群中通过 FluxCD 部署 VPA 的 HelmRelease 配置示例:</p>
<pre><code> apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: vpa
namespace: vpa
spec:
releaseName: vpa
# (https://github.com/FairwindsOps/charts/blob/master/stable/vpa/values.yaml)
chart:
    spec:
      chart: vpa
      sourceRef:
      kind: HelmRepository
      name: fairwinds-stable
      namespace: flux-system
interval: 5m
values:
    recommender:
      enabled: true
    updater:
      enabled: false
    admissionController:
      enabled: false
</code></pre>
<h3 id="配置-vpa-为指定-deployment-提供资源推荐"><strong>配置 VPA 为指定 Deployment 提供资源推荐</strong></h3>
<p>在成功部署 VPA 后,你可以创建一个 VerticalPodAutoscaler 资源清单,指定它要监控哪个 Deployment,并且只生成资源配置的推荐,而不会自动修改 Pod。</p>
<p>比如,下面这个 VPA 配置示例就是针对某个特定 Deployment,只输出资源调整建议,避免自动变更 Pod。<strong>这对于使用 GitOps 管理的环境来说非常重要</strong>,能保证配置变更都在版本控制之下,避免自动更新带来的不确定性。</p>
<pre><code> apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: recipes-vpa
spec:
targetRef:
    apiVersion: "apps/v1"
    kind: Deployment
    name: recipes
updatePolicy:
    updateMode: "Off"   #Set to off since the 'recipes' deployment manifest is managed with GitOps
</code></pre>
<h3 id="脚本自动获取命名空间内-pod-的资源推荐"><strong>脚本:自动获取命名空间内 Pod 的资源推荐</strong></h3>
<p>有了 VPA 之后,这个脚本可以帮助开发者自动查询当前命名空间中各个 Pod 的资源推荐情况。</p>
<p>需要注意的是,虽然 VPA 本身提供了接口可以直接查询推荐结果,但<strong>这些数据通常比较原始,需要进一步解读并转化为具体的调整方案</strong>。</p>
<p>这个脚本就是为了解决这个问题,它会整理出详细的推荐信息和配置变更建议,方便自动化处理和后续执行。</p>
<pre><code> # 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)" _
VPA Recommendations for Namespace: recipes for Context: gke_runwhen-nonprod-sandbox_us-central1_sandbox-cluster-1-cluster
===========================================
Recommendation for recipes-nginx in Deployment recipes: Adjust CPU request from 125 to 20 millicores
Recommendation for recipes-nginx in Deployment recipes: Adjust Memory request from 64 to 50 Mi
Recommendation for recipes in Deployment recipes: Adjust CPU request from 125 to 20 millicores
Recommendation for recipes in Deployment recipes: Adjust Memory request from 64 to 50 Mi
Recommended Next Steps:
[
{
    "remediation_type": "resource_request_update",
    "vpa_name": "recipes-vpa",
    "resource": "cpu",
    "current_value": "125",
    "suggested_value": "20",
    "object_type": "Deployment",
    "object_name": "recipes",
    "container": "recipes-nginx",
    "severity": "4",
    "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust CPU request from 125 to 20 millicores"
},
{
    "remediation_type": "resource_request_update",
    "vpa_name": "recipes-vpa",
    "resource": "memory",
    "current_value": "64",
    "suggested_value": "50",
    "object_type": "Deployment",
    "object_name": "recipes",
    "container": "recipes-nginx",
    "severity": "4",
    "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust Memory request from 64 to 50 Mi"
},
{
    "remediation_type": "resource_request_update",
    "vpa_name": "recipes-vpa",
    "resource": "cpu",
    "current_value": "125",
    "suggested_value": "20",
    "object_type": "Deployment",
    "object_name": "recipes",
    "container": "recipes",
    "severity": "4",
    "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust CPU request from 125 to 20 millicores"
},
{
    "remediation_type": "resource_request_update",
    "vpa_name": "recipes-vpa",
    "resource": "memory",
    "current_value": "64",
    "suggested_value": "50",
    "object_type": "Deployment",
    "object_name": "recipes",
    "container": "recipes",
    "severity": "4",
    "next_step": "Adjust pod resources to match VPA recommendation in `recipes`\nAdjust Memory request from 64 to 50 Mi"
}
]
</code></pre>
<h2 id="将资源调优融入gitops流水线"><strong>将资源调优融入GitOps流水线</strong></h2>
<p>前面提到的脚本帮你找出了哪些资源配置需要调整,以及具体该怎么改,最后一步就是把这些推荐结果整合进 GitOps 流水线里。</p>
<p>虽然不同团队的 GitOps 流程会有所差异,但一般来说,可以把脚本输出中“Recommended Next Steps”(推荐的后续操作)部分的 JSON 内容提取出来,传给一个自动化脚本。</p>
<p>这个脚本会根据推荐内容更新 GitOps 代码仓库,并通过既有的审批流程通知相关负责人,确保资源调整变更有序、安全地落地。这样一来,资源配置的优化就能无缝融入日常的开发和交付节奏。</p>
<p><img src="https://img2024.cnblogs.com/blog/3543217/202507/3543217-20250721103254359-457672034.png"></p>
<p>举个例子,这个脚本(https://github.com/runwhen-contrib/rw-cli-codecollection/blob/main/codebundles/k8s-gitops-gh-remediate/update_github_manifests.sh)适用于存放在 GitHub 上的 GitOps 仓库,兼容 ArgoCD 和 FluxCD 两种 GitOps 引擎。它的工作流程大致如下:</p>
<ul>
<li>首先识别负责管理资源的 GitOps 控制器(FluxCD 或 ArgoCD);</li>
<li>获取对应的 Git 仓库地址以及存放 Kubernetes 清单(manifest)文件的路径;</li>
<li>解析输入的 JSON,识别需要修正的资源操作,并按类型分类,比如资源配额更新、资源请求建议、PVC 容量扩容等;</li>
<li>针对每个需要修正的操作,动态生成对应的 YAML 文件变更内容;</li>
<li>克隆目标 Git 仓库,创建一个新的分支,将修改后的 YAML 文件写入并提交;</li>
<li>自动生成一份详细的&nbsp;Pull Request(PR)说明,阐述修改原因并附带相关信息链接,然后发起针对主分支的 PR;</li>
<li>最后输出&nbsp;PR 链接,方便团队成员进行代码审查和审批。</li>
</ul>
<p>这个流程让资源调优的变更能自动、有序地推进,减少人工干预和出错风险。</p>
<p><img src="https://img2024.cnblogs.com/blog/3543217/202507/3543217-20250721103305265-721487670.png"></p>
<h2 id="总-结"><strong>总 &nbsp;结</strong></h2>
<p>资源管理,特别是在性能和成本之间找到最佳平衡,对处于生产环境的平台来说确实是一项复杂的挑战。本文介绍了一些免费且实用的脚本和工具,适合作为平台或应用团队入门的参考。</p>
<p>目前市面上也有许多厂商投入大量资源,提供更深入的应用使用洞察和资源调优方案,比如&nbsp;<strong>CloudPilot AI (我们即将推出一个全新的Dashboard,将带来更直观的成本监控体验,敬请期待!)</strong> ,这些方案尤其适合规模大、环境复杂的场景。</p><br><br>
来源:https://www.cnblogs.com/cloudpilot-ai/p/18995355/k8s-gitops
頁: [1]
查看完整版本: 实用脚本公开!0成本实现GitOps中Kubernetes资源自动调优