来源:小随小看 | 发布日期:2026-05-23
K8s 容量规划、Pod QoS 与成本优化实战指南
容量规划不是「资源填大一点」——而是在稳定性、利用率与成本之间找到平衡。核心在线服务用保底和优先级换稳定,普通服务用弹性换效率,离线任务用隔离和限额控风险,平台侧用自动化准入和成本归因做长期治理。
核心问题:容量规划回答的四件事
Kubernetes 容量规划不是简单给 Pod 写 requests/limits,而是回答四个问题:
| 问题 | 核心关注点 | 错误做法 | 正确做法 |
|---|---|---|---|
| 能不能调度上去 | requests、节点可分配资源 | 只看实时 CPU 使用率 | 基于 request 预算和节点池水位规划 |
| 高峰期能不能扛住 | P95/P99 资源消耗、QPS、RT | 所有服务统一 1C/2G | 按服务类型建模,留突发余量 |
| 故障时谁被牺牲 | QoS、PriorityClass、PDB | 所有 Pod 同优先级 | 核心链路 Guaranteed + 高优先级 |
| 钱花在哪里 | 成本标签、命名空间、节点池 | 只看云账单总额 | 按团队/服务/环境/SLA 归因 |
K8s 资源模型与 QoS
Requests vs Limits 的真实含义
| 配置 | 作用阶段 | 含义 | 谁执行 |
|---|---|---|---|
| requests.cpu | 调度 + 运行 | Pod 希望被保证的 CPU 份额 | Scheduler + cgroup 权重 |
| limits.cpu | 运行 | CPU 使用上限,超限后 throttling | CFS cgroup |
| requests.memory | 调度 + 驱逐排序 | Pod 希望被保证的内存 | Scheduler + kubelet eviction |
| limits.memory | 运行 | 内存硬上限,超限后 OOMKilled | OOM killer / cgroup |
关键理解:
- CPU 是可压缩资源 — 超限后被 throttling,表现为变慢
- 内存是不可压缩资源 — 超限后被 OOMKilled,表现为进程被杀
- 调度器主要看 request,不看实时使用率
- request 才是容量预算的基础,不是 limit
Pod QoS 三种等级
| QoS | 条件 | 特点 | 适用 |
|---|---|---|---|
| Guaranteed | 每个容器 CPU/Mem request=limit | 驱逐优先级最低 | 核心交易、网关、数据库代理 |
| Burstable | 至少一个容器设了 request/limit | 可弹性使用空闲资源 | 普通 Web 服务、异步消费 |
| BestEffort | 所有容器都未设 request/limit | 最易被驱逐 | 临时调试、开发环境 |
⚠️ 驱逐排序:BestEffort > 超 request 的 Burstable > Guaranteed。但 Guaranteed 超 memory limit 仍会被杀。
详细 QoS 机制参见 k8s-resource-limits-configuration。
容量规划方法论:从流量到资源预算
不要直接从当前使用率推 request
容量规划至少需要五类数据:
- 历史资源水位 — CPU/Memory/Network/Disk 的 P50/P90/P95/P99
- 业务流量指标 — QPS、并发、消息堆积、定时任务周期
- 服务性能指标 — RT、错误率、线程池队列、连接池等待、GC pause
- 副本与可用性策略 — 最小副本/最大副本/跨 AZ 容灾/PDB
- 增长与突发系数 — 日常增长、大促、批量任务、缓存击穿
容量估算公式
单 Pod CPU request = max(P95 CPU 使用量, 压测基准 CPU) × 安全系数
单 Pod Mem request = max(P95 RSS, 运行时推荐基线) × 1.2
单 Pod Mem limit = P99 RSS × 1.2 或 request × 1.3~2.0
业务总 request = Σ(每个 workload 的 request × replicas)
节点可分配资源 = node allocatable - 系统预留 - DaemonSet 预留
所需节点数 = ceil(业务总 request / 单节点可分配 / 目标装箱率)
安全系数推荐:S0(核心交易)1.3~1.8,S1(重要服务)1.2~1.5,S2(普通)1.1~1.3,Batch 1.0~1.2。
目标装箱率:核心节点池 CPU 55%~70%、Mem 60%~75%;普通节点池 CPU 65%~80%、Mem 70%~85%。
Little's Law 估算并发容量
并发数 L = 到达率 λ × 平均响应时间 W
示例:订单 QPS 2000,RT 80ms → L = 2000 × 0.08 = 160
单 Pod 承载 40 并发 → 需要 4 副本,加 N+1 滚动发布 → 6 副本
各运行时内存注意
Java 容器
容器 RSS ≈ Heap + Metaspace + Direct Memory + Thread Stack + Code Cache + GC Native + JNI + glibc arena
JAVA_TOOL_OPTIONS="-XX:MaxRAMPercentage=70 -XX:InitialRAMPercentage=70 ..."
resources:
limits: memory: "4Gi" # 统一 request=limit
requests: memory: "4Gi"
详见 jvm-container-oom-offheap-troubleshooting。
Go 容器
GOMEMLIMIT=1536MiB # Go 1.19+ 运行时内存上限
GOMAXPROCS=2 # 显式限制,避免容器 CPU limit 感知偏差
Node.js 容器
NODE_OPTIONS="--max-old-space-size=768" # RSS 需留余量
弹性伸缩协同
| 组件 | 职责 | 指标 |
|---|---|---|
| HPA | 副本扩缩容 | CPU 利用率 / QPS / 自定义指标 |
| VPA | request 推荐与垂直调整 | 历史 P95/P99 使用量 |
| Cluster Autoscaler | 节点扩缩容 | Pending Pod |
| Karpenter | 节点即时扩缩+规格最优 | Pending Pod + 节点池策略 |
⚠️ HPA 与 VPA 不要同时基于 CPU/Memory 控制同一对象 — VPA 调大 request 会使 HPA 利用率下降触发缩容,反之触发扩容,两者相互干扰。
平台架构分层
业务接入层 → Deployment / StatefulSet / Job / Argo Rollout
准入治理层 → MutatingWebhook / ValidatingWebhook / Kyverno
调度与隔离层 → PriorityClass / Taint/Toleration / Affinity / TopologySpread
弹性伸缩层 → HPA / VPA / Cluster Autoscaler / Karpenter
可观测与成本层 → 容量看板 / CPU throttling / OOM / 成本归因
成本优化体系
成本标签规范
所有生产 Workload 必须包含:
labels:
cost-center: commerce # 财务归因
owner-team: order-team # 团队归因
environment: production # 环境拆分
service-tier: s0 # SLA 与资源策略
成本归因模型
Pod CPU 成本 = 节点 CPU 成本 × Pod CPU request / 节点 CPU allocatable
Pod Mem 成本 = 节点 Mem 成本 × Pod Mem request / 节点 Mem allocatable
Pod 总成本 = CPU + Mem + 存储 + 网络 + 共享平台分摊
共享组件分摊:网关按 QPS、日志系统按日志量、链路追踪按 trace span 数。
Spot 节点使用规范
适合: Batch Job、消息消费(幂等)、离线报表、无状态低优先级服务 不适合: 核心交易、数据库/有状态中间件、无 checkpoint 的长时间任务、P99 极敏感服务
落地五阶段路线图
| 阶段 | 目标 | 关键动作 |
|---|---|---|
| 一:标准化 | 不让集群裸奔 | 全部 Pod 设 request+mem limit;核心服务设 PDB+probe;建服务等级和标签体系 |
| 二:可观测 | 资源可解释 | CPU request 利用率/ throttling / OOM / Pending Pod / 团队成本看板 |
| 三:准入控制 | 减少人为错误 | LimitRange / ResourceQuota / Kyverno 校验;禁止 BestEffort 到生产 ns |
| 四:弹性&成本 | 利用率 + SLA 兼顾 | HPA / VPA 推荐 / Cluster Autoscaler / Batch 迁移 Spot / 节点池碎片治理 |
| 五:FinOps 闭环 | 主动规划 | 30~90 天容量预测;大促容量演练;预算异常告警;月度资源账单 |
关联页面
| 页面 | 关联点 |
|---|---|
| k8s-resource-limits-configuration | K8s 资源限制与 QoS / CPU Throttling 详解 |
| k8s-scheduling-strategy-guide | Pod 调度策略六大机制 |
| jvm-container-oom-offheap-troubleshooting | JVM 容器 OOM 排障(堆外内存) |
| resource-rbac-scheduling-troubleshooting | 资源配额/OOMKilled 排障 |
| docker-production-pitfalls | Docker 生产坑(含 OOMKilled) |
| k8s-production-incident-case-studies | K8s 生产故障案例 |
| linux-memory-management-deep-dive | Linux 内存管理 |
| k8s-java-memory-tuning-production-guide | Kubernetes 下 Java 内存调优完整指南 — 内存预算模型、生产参数配置、四层诊断流程、 |
| k8s-architecture-core-concepts | K8s 架构核心概念 |