Kubernetes资源建议工具:基于VPA为工作负载推荐requests与limits
goldilocks 是一个资源配额建议工具。它为命名空间里的每个工作负载自动创建一个 VerticalPodAutoscaler(VPA),再把 VPA 给出的建议汇总到一个看板上,让你一眼看到「这个应用的 requests 设得偏高还是偏低、该填多少」。
它的价值在于把 VPA 从「自动调整」变成「只给建议」:
VPA 的三种能力:recommender(算建议) / updater(实际改 Pod) / admission-controller(拦截新建 Pod 时改写)
goldilocks 只需要 recommender,后两者关掉 —— 这样 VPA 只出建议,不动任何线上 Pod
它不产生自己的算法。所有数字都来自 VPA recommender 的统计模型,因此建议质量完全取决于 VPA 能拿到多少历史数据。
自动创建出来的 VPA 命名规则是固定的:
goldilocks-<工作负载名>
# 例如 dev 命名空间里名为 nginx 的 Deployment
# 对应的 VPA 就是 goldilocks-nginx
goldilocks 依赖 VPA 与 metrics-server,推荐把 VPA 单独安装管理:
# 1. 安装 VPA —— 只启用 recommender
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
helm repo update
helm install vpa fairwinds-stable/vpa -n vpa --create-namespace \
--set updater.enabled=false \
--set admissionController.enabled=false
# 2. 安装 metrics-server(VPA recommender 的前置依赖,集群已有则跳过)
kubectl get apiservice v1beta1.metrics.k8s.io
kubectl top nodes
# 3. 安装 goldilocks
kubectl create namespace goldilocks
helm install goldilocks fairwinds-stable/goldilocks --namespace goldilocks
也可以让 goldilocks 的 chart 一并带上 VPA 子 chart,但必须显式关掉 updater 与 admission controller:
helm install goldilocks fairwinds-stable/goldilocks --namespace goldilocks \
--set vpa.enabled=true \
--set vpa.updater.enabled=false \
--set vpa.admissionController.enabled=false
子 chart 的默认值里 admission controller 是开启的,不显式关闭会往集群里装一个会拦截 Pod 创建的准入 Webhook,这与「只做建议」的初衷相悖。
不用 Helm 时也可以直接套用清单:
kubectl -n goldilocks apply -f hack/manifests/controller
kubectl -n goldilocks apply -f hack/manifests/dashboard
安装后会得到:
Deployment/goldilocks-controller 1 副本,负责创建与清理 VPA
Deployment/goldilocks-dashboard 2 副本,提供 Web 看板
Service/goldilocks-dashboard ClusterIP,服务端口 80 → 容器端口 8080
goldilocks 以命名空间为单位生效,必须给命名空间打标签:
# 纳入管理
kubectl label namespace dev goldilocks.fairwinds.com/enabled=true
# 显式排除
kubectl label namespace kube-system goldilocks.fairwinds.com/enabled=false
# 查看所有已启用的命名空间
kubectl get ns -l goldilocks.fairwinds.com/enabled=true
标签值的解析用的是 strconv.ParseBool,因此 true、True、1、t 都算启用;无法解析时按 false 处理,并且只会在日志里留一条记录,不会报错。
把标签改成 false 或直接删掉标签,goldilocks 会清理掉它在那个命名空间里创建的所有 VPA。
# 方式一:Web 看板
kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80
# 浏览器打开 http://localhost:8080
# 方式二:直接看 VPA 对象
kubectl get vpa -n dev
kubectl describe vpa goldilocks-nginx -n dev
kubectl get vpa goldilocks-nginx -n dev -o yaml
# 方式三:命令行摘要(输出 JSON)
goldilocks summary
VPA 的建议分三档,target 是要重点看的那个:
lowerBound 建议的下限,通常作为 requests
target VPA 认为最合适的值
upperBound 建议的上限,通常作为 limits
uncappedTarget 不受 minAllowed / maxAllowed 约束的原始建议
goldilocks 在看板上给出的解读是:工作负载属于 Guaranteed QoS 时,target 同时作为 requests 与 limits;属于 Burstable 时,把 lowerBound 当 requests、upperBound 当 limits。
除了 enabled,还有几个同样挂在 goldilocks.fairwinds.com/ 下的键:
# 修改该命名空间下 VPA 的 updateMode
kubectl label namespace dev goldilocks.fairwinds.com/vpa-update-mode=auto
# 为 VPA 配置 resourcePolicy,可限定上下限或关掉某些容器
kubectl annotate namespace dev goldilocks.fairwinds.com/vpa-resource-policy='{"containerPolicies":[{"containerName":"nginx","minAllowed":{"cpu":"250m","memory":"100Mi"}},{"containerName":"istio-proxy","mode":"Off"}]}'
# 排除某些容器不参与建议(打在工作负载上)
kubectl label deployment myapp -n dev goldilocks.fairwinds.com/exclude-containers=linkerd-proxy,istio-proxy
# 限制 VPA 的最小副本数
kubectl annotate deployment myapp -n dev goldilocks.fairwinds.com/vpa-min-replicas=2
vpa-update-mode 的合法取值是 Off、Initial、Recreate、InPlaceOrRecreate、InPlace,以及作为兼容别名的 auto(等价于 Recreate)。取值非法时会回退到 Off 并打一条警告。默认值是 Off,也就是只建议不执行。
goldilocks 的正确用法是「先看后改」,把建议当作评审材料而不是自动执行的配置:
# 1. 先在一个非核心命名空间上试水
kubectl label namespace staging goldilocks.fairwinds.com/enabled=true
# 2. 确认 VPA 已被创建(工作负载必须有存活的 Pod)
kubectl get vpa -n staging
# 3. 等 VPA 累积足够历史数据,期间用看板观察建议值是否趋于稳定
kubectl -n goldilocks port-forward svc/goldilocks-dashboard 8080:80
# 4. 查看某个工作负载的完整建议
kubectl describe vpa goldilocks-my-app -n staging
kubectl get vpa goldilocks-my-app -n staging -o jsonpath='{.status.recommendation.containerRecommendations}'
# 5. 人工确认后,把建议值写回工作负载
kubectl set resources deployment/my-app -n staging \
--requests=cpu=250m,memory=256Mi \
--limits=cpu=500m,memory=512Mi
# 6. 改完观察一段时间,确认没有 OOMKilled 与明显的 CPU 限流
kubectl get events -n staging --field-selector reason=OOMKilling
kubectl top pod -n staging
第 5 步是关键:goldilocks 给出的是参考值,直接照搬有可能把 requests 抬到节点放不下的程度,导致 Pod 无法调度。落库前要一并考虑节点的可分配资源与整个命名空间的配额。
null 或空建议。100G、100T 这类夸张数字通常不是 bug,而是模型上界。Off,这是安全的默认值,不要随手改。改成 auto/Recreate 后 VPA 会真的重建 Pod 来套用新配额,可能在毫无预告的情况下滚动重启整个工作负载。--set vpa.admissionController.enabled=false。creator=Fairwinds、source=goldilocks 标签且名字形如 goldilocks-<工作负载> 的对象 —— 手工创建的、名字不同的 VPA 不会被它接管或删除。resourcePolicy 分别限定各自管理的资源(例如 VPA 只管内存、HPA 只管 CPU)。由于 goldilocks 默认是 Off,风险会在切到主动模式时才显现。goldilocks-dashboard 的 Service 是普通 ClusterIP,靠端口转发访问尚可;要用 Ingress 对外暴露,必须自行在前面加上认证层,否则等于把整个集群的资源画像与命名空间结构公开出去。kubectl — Kubernetes集群管理工具hpa — 水平自动扩缩容,与 VPA 组合使用时需要划分职责metrics-server — 集群资源指标采集组件,VPA recommender 的前置依赖kube-state-metrics — 对象状态指标导出器,与 VPA 建议可交叉印证deployment — 常见的工作负载类型,资源建议的主要对象