Kubernetes 中的 Resources,通常指容器对计算和存储资源的声明,核心字段是:
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"它用于描述:
最常见的资源类型包括:
cpu
memory
ephemeral-storage
GPU 等扩展资源
HugePages可以把 Kubernetes 资源治理理解为:
requests:调度和容量规划依据
limits:容器运行时上限
resources:容器对资源需求的完整声明resources 位于:
Pod.spec.containers[].resources也就是说,资源是按容器配置的,不是直接配置在 Deployment 或 Pod 的顶层。
一个 Pod 有多个容器时,资源通常需要分别配置:
这个 Pod 的普通容器资源总和是:
CPU request:600m
内存 request:640Mi
CPU limit:1.3
内存 limit:1.25Girequests 表示容器向 Kubernetes 声明的资源需求,主要用于调度。
resources:
它表示:
500m CPU 和 512Mi 内存 可分配空间的节点重要的是:
Scheduler 主要根据 requests 调度,而不是根据实时使用量调度。例如:
节点总 CPU:8
节点已分配 CPU request:7.5
节点实际 CPU 使用量:2即使节点实际只使用了 2 CPU,新 Pod 也可能因为没有足够的 CPU request 可分配而无法调度。
limits 表示容器运行时允许使用的资源上限。
resources:
典型行为:
| 资源 | 超过 limit 的典型结果 |
|---|---|
| CPU | 被限流、CPU throttling |
| Memory | 可能 OOMKill |
| ephemeral-storage | 可能触发驱逐 |
| GPU | 通常无法超过设备数量 |
| HugePages | 通常要求严格匹配 |
limits 是容器运行时层面的限制,底层通常由 Linux cgroup 配合容器运行时执行。
CPU 是可压缩资源。
如果容器配置:
limits:
cpu: "500m"而程序需要 1 CPU,通常不会直接退出,而是:
容器继续运行,但 CPU 使用会被限制可能出现:
所以 CPU limit 过低可能造成性能问题。
内存是不可压缩资源。
如果容器配置:
limits:
memory: "512Mi"而容器实际使用超过该上限,可能发生:
OOMKill典型现象:
kubectl describe pod <pod-name> -n <namespace>看到:
Last State: Terminated
Reason: OOMKilled
Exit Code: 137容器可能随后被重启,取决于 Pod 的重启策略。
内存 limit 必须考虑:
Kubernetes 中 CPU 使用 CPU 核和 millicore 表示。
1 CPU = 1000m
500m = 0.5 CPU
100m = 0.1 CPU
10m = 0.01 CPU示例:
cpu: "1"
cpu: "500m"
cpu: "250m"常见错误:
cpu: "1000"这表示 1000 个 CPU,而不是 1 个 CPU。
如果要表示 1 个 CPU,可以写:
cpu: "1"或者:
cpu: "1000m"常见写法:
二进制单位:
Ki、Mi、Gi、Ti十进制单位:
K、M、G、T生产环境建议优先统一使用:
Mi、Gi例如:
memory: "512Mi"因为它更容易在团队之间保持一致。
需要注意:
1Gi = 1024Mi
1G = 1000Mresources:
这种情况下,是否存在 limit 取决于:
如果没有 limit,容器可能没有明确的运行时上限。
resources:
在 Kubernetes 常见行为中,如果没有显式配置 request,通常会将 request 补为对应的 limit:
这可能影响:
所以不要以为“只写 limits”就一定是低 request 的 Burstable Pod。
这是最推荐、最清晰的方式:
含义是:
稳定调度需求:250m CPU、512Mi 内存
运行上限:1 CPU、1Gi 内存以下配置通常是不合法的:
一般要求:
request <= limit否则 API Server 会拒绝创建对象。
一个 Pod 包含两个普通容器:
容器 A:
CPU request 500m
内存 request 512Mi
容器 B:
CPU request 200m
Pod 的普通容器 request 为:
CPU:700m
内存:640Mi对于普通容器,Pod 资源通常是各容器资源之和。
Init Container 的资源计算不是简单地与普通容器全部相加。
通常可以理解为:
Pod 有效 request =
max(
所有 Init Container 中最大的 request,
所有普通容器 request 的总和
)例如:
Init Container:
CPU 2,内存 2Gi
普通容器:
CPU 500m,内存 512Mi
CPU 500m,内存 512MiPod 有效 request 近似为:
CPU:max(2, 0.5 + 0.5) = 2
内存:max(2Gi, 512Mi + 512Mi) = 2Gi因此,大资源 Init Container 可能显著影响 Pod 调度。
某些 RuntimeClass 可能配置 Pod overhead:
overhead:
这部分资源会影响 Pod 的调度和资源计算。
需要考虑 Pod overhead 的场景包括:
资源配置会影响 Pod 的 QoS Class。
Pod 中所有容器都满足:
CPU request = CPU limit
Memory request = Memory limit示例:
特点:
注意:QoS 为 Guaranteed 的前提是 Pod 中相关容器都满足条件,不能只看主容器。
只要配置了部分资源,或者 request 小于 limit,通常就是 Burstable。
这是生产环境最常见的 QoS 类型。
所有容器都没有 request 和 limit:
resources: {}特点:
查看 QoS:
调度器主要依据 requests 进行节点筛选。
假设某节点:
CPU capacity:8
CPU allocatable:7.5
已分配 request:7
剩余可分配:500m新 Pod 需要:
requests:
cpu: "1"即使节点实际 CPU 使用只有 2,也可能无法调度,因为剩余 allocatable request 不足。
常见调度失败信息:
0/3 nodes are available:
3 Insufficient cpu查看:
kubectl describe pod <pod-name> -n <namespace>重点查看:
Events:
FailedScheduling查看节点:
kubectl describe node <node-name>通常会看到:
含义:
| 概念 | 含义 |
|---|---|
| Capacity | 节点理论总资源 |
| Allocatable | 可分配给 Pod 的资源 |
| Requests | 已被 Pod 声明的调度资源 |
| Limits | Pod 允许使用的运行时上限 |
Allocatable 通常小于 Capacity,因为节点需要为系统组件预留资源。
节点不是所有资源都可以给业务 Pod 使用。
需要预留:
相关配置包括:
systemReserved
kubeReserved
evictionHard
evictionSoft如果只关注业务 Pod 的 requests,不关注节点预留,可能出现:
业务资源声明看起来合理
节点却频繁 MemoryPressure 或 DiskPressure生产环境应同时进行:
Pod 资源治理
Node 资源预留
Cluster 容量规划限制单个对象的资源范围和默认值:
限制 Namespace 总量:
可以简单记忆:
LimitRange:一个容器或 Pod 能申请多少
ResourceQuota:整个 Namespace 能申请多少HPA 使用 CPU 或内存利用率时,通常以 request 作为基准。
例如:
resources:
requests:
cpu: "250m"容器实际使用:
500m CPU利用率大致为:
500m / 250m = 200%如果 request 配置成:
requests:
cpu: "1"相同实际使用量的利用率变成:
500m / 1 = 50%因此 request 会直接影响 HPA 是否扩容。
典型 HPA:
如果 Pod 没有 CPU request,基于 CPU utilization 的 HPA 可能无法正常计算。
VPA 可以根据历史资源使用情况推荐或调整:
requests
limits常见模式:
LimitRange 提供初始默认值
VPA 根据实际使用生成建议
运维审核后调整 DeploymentVPA 需要谨慎使用,因为调整资源可能导致 Pod 重建。
一般建议:
recommendation当节点资源不足时,Kubernetes 可能驱逐 Pod。
一般情况下,资源压力下的驱逐倾向与以下因素有关:
通常可粗略理解为:
BestEffort 更容易被驱逐
Burstable 次之
Guaranteed 相对更晚但 Guaranteed 并不意味着绝对不会被驱逐。
此外还要区分:
容器 OOMKill
节点内存压力驱逐二者不是同一个事件:
| 类型 | 说明 |
|---|---|
| OOMKill | 容器或 cgroup 超过内存限制 |
| Eviction | kubelet 因节点资源压力驱逐 Pod |
ephemeral-storage 表示容器使用的临时存储,通常包括:
emptyDir示例:
还可以限制 emptyDir:
生产中需要关注:
/tmpemptyDir 是否被无限写入DiskPressure排查:
重点查看:
DiskPressure
Evicted
ephemeral-storageGPU 这类资源通常以扩展资源表示:
resources:
limits:
nvidia.com/gpu: 1也可以通过 ResourceQuota 限制 Namespace 总 GPU 数量:
GPU 资源通常需要配合:
GPU 一般不能像 CPU 一样被任意拆分或超卖,除非使用专门的 GPU 共享或虚拟化技术。
HugePages 是特殊资源:
特点:
使用前必须确认:
节点是否预留对应 HugePages
Pod 是否设置了正确的资源名称
调度器是否能识别该资源不要让关键服务完全依赖 LimitRange 默认值:
显式配置便于:
一种常见参考方法:
CPU request:稳定负载 P50/P70/P95 附近
内存 request:稳定 working set 加合理余量
CPU limit:根据是否允许突发决定
内存 limit:覆盖峰值和运行时开销不能简单照搬某个固定比例。
例如:
只适合作为起点,最终要看:
内存 limit 不应直接等于 -Xmx:
容器内存 =
JVM Heap
+ Metaspace
例如:
limits:
memory: "2Gi"JVM 堆不应直接配置到 2Gi,而要留出其他内存空间。
需要考虑:
需要考虑:
CPU limit 过低会导致:
CPU throttling
延迟升高
吞吐下降建议监控:
container_cpu_cfs_throttled_seconds_total
container_cpu_cfs_throttled_periods_total
container_cpu_cfs_periods_total对于延迟敏感的服务,可以评估:
也就是不设置 CPU limit,允许使用节点空闲 CPU。
但这需要结合:
一个 Pod 可能不仅有主容器:
业务容器
Service Mesh Sidecar
日志采集容器
监控 Agent
安全 Agent如果主容器 request 是:
CPU 200m,内存 256MiSidecar request 是:
CPU 200m,内存 256Mi那么 Pod 实际至少需要:
CPU 400m,内存 512Mi生产环境不能只按照主业务容器估算资源。
如果一个 DaemonSet 每个 Pod 有:
requests:
cpu: "200m"
memory: "256Mi"100 个节点就可能需要:
CPU:20
内存:25.6Gi因此 DaemonSet 的资源成本会随节点数量增长,必须单独纳入集群容量规划。
适合:
如果配合 HPA:
CPU request 会直接影响扩容阈值特点:
是否采用这种方式,要通过压测和线上指标确认。
JVM 参数:
-XX:MaxRAMPercentage=70示意:
env:
- name: JAVA_TOOL_OPTIONS
value: 不要让 JVM Heap 占满整个容器 memory limit。
适合:
需要同时规划:
需要结合:
对于消息消费者,CPU limit 过低可能造成消费延迟增加和队列积压。
适合:
GPU 资源通常需要:
requests 与 limits 一致并配合专用 GPU Namespace 和 ResourceQuota。
不一定。
有些 CPU 密集型服务为了减少 throttling,可能不设置 CPU limit,但仍然设置:
是否设置 CPU limit,应该基于隔离和性能要求决定。
不是。
request 是调度声明
实际使用量由应用运行状态决定容器可能只使用 50m,也可能经常使用 500m。
不是。
limit 是上限,不是保证值。
真正影响调度保证的是 request。
错误。
如果应用超过 memory limit,反而可能被 OOMKill。
此外,即使容器没有超过自己的 limit,节点整体内存压力也可能导致 Pod 被驱逐。
不一定。
如果 CPU request 是:
100m实际使用:
500m那么相对 request 的 CPU 利用率就是:
500%这可能是正常的,只要:
不会。
LimitRange 的默认注入和校验主要发生在 Pod 创建或更新时。
修改资源策略后:
查看 Pod 资源声明:
kubectl get pod <pod-name> 查看 Pod 描述和事件:
kubectl describe pod <pod-name> -n <namespace>查看实时资源使用:
kubectl top pod <pod-name> -n <namespace> 查看节点资源:
kubectl describe node <node-name>查看所有节点使用情况:
kubectl top nodes查看 Namespace 配额:
查看 LimitRange:
kubectl get limitrange -n <namespace> -o yaml查看 QoS:
查看容器是否 OOM:
kubectl get pod <pod-name> 或者:
kubectl describe pod <pod-nam查看服务端处理后的资源默认值:
kubectl create
至少观察:
至少区分:
核心生产工作负载不应只依赖默认值:
防止未配置资源的工作负载完全失去资源边界。
防止团队通过大量 Pod 或副本消耗整个集群。
HPA:调整副本数
VPA:调整单 Pod 资源二者同时使用时要避免互相干扰。
尤其检查:
maxSurgemaxUnavailable资源配置不是一次性工作。
应定期根据实际数据调整:
requests
limits
HPA target
LimitRange default
Kubernetes 中的 Resources 可以这样理解:
生产环境中推荐遵循:
requests 和 limitsrequests 根据稳定负载和容量规划确定memory limit 必须覆盖运行时额外开销LimitRange 设置默认值和边界最核心的一句话是:
Requests 决定 Kubernetes 如何安排 Pod,
Limits 决定容器运行时能用多少资源,
而合理的 Resources 配置决定了生产集群的稳定性、利用率和扩缩容行为。有。前面的内容已经覆盖了常规使用,下面补充一些更底层、容易被忽略的高级细节,以及几条需要纠正或精确理解的地方。
requests 不是资源保证值很多人把 request 理解成“容器一定能获得这么多资源”,这不完全准确。
CPU request 主要用于:
它不是一个严格的 CPU 独占保证。
例如:
requests:
cpu: "500m"表示调度时按 500m 计算,但在节点 CPU 紧张时,容器实际性能仍可能受到影响。
如果需要真正的 CPU 独占,通常还需要:
requests.cpu == limits.cpucpuManagerPolicyOptions示例:
但这仍然需要确认节点和 kubelet 的 CPU Manager 配置。
内存 request 主要用于:
它不是硬内存上限。硬上限主要由:
limits:
memory: "4Gi"决定。
如果多个容器同时竞争 CPU,CPU request 通常会影响它们在 cgroup 中的相对权重。
例如:
容器 A:request 100m
容器 B:request 500m在 CPU 紧张时,容器 B 通常会获得更高的 CPU 权重。
因此,request 不只是调度字段,也会影响运行时资源竞争。
但要注意:
CPU request 越大,不代表容器永远独占这么多 CPU。如果需要独占,应使用 CPU Manager 和专用 CPU 配置。
下面的配置会让 Pod 更接近 Guaranteed QoS:
但它不自动意味着:
如果需要 CPU 独占,通常还要满足:
整数 CPU request
request 等于 limit
Guaranteed QoS
CPU Manager static
节点有足够可分配的独占 CPU示例:
500m 这类非整数 CPU 通常不能获得完整的独占 CPU 核。
CPU limit 通常通过 Linux cgroup 的 CPU quota 实现。
例如:
limits:
cpu: "1"意味着容器在一个调度周期内最多使用大约一个 CPU 的计算时间。
CPU limit 过低时,可能出现:
container_cpu_cfs_throttled_seconds_total 增加
请求延迟增加
吞吐量下降
健康检查超时生产环境不能只看:
CPU 使用率是否超过 limit还要看:
CPU throttling 比例
应用尾延迟
请求超时
消息积压对于低延迟服务,CPU limit 是否设置,需要通过压测验证。
如果配置:
limits:
memory: "1Gi"这不是说应用在达到恰好 1Gi 的瞬间一定立即退出。
实际行为还受到以下因素影响:
但生产上应把它当作严格上限进行容量规划,不能依赖“可能还能多用一点”。
常见的内存指标含义不同:
container_memory_working_set_bytes
container_memory_usage_bytes
container_memory_rss
container_memory_cache简单理解:
usage:cgroup 使用的总内存,可能包含缓存working_set:常用于观察相对活跃的内存rss:匿名内存和部分实际驻留内存cache:文件缓存等内容排查 OOM 时,不要只看单一指标。最好同时结合:
容器内存通常包括:
例如 Java:
容器 memory limit = 2Gi不应直接设置:
-Xmx2g因为 JVM Heap 之外还需要:
常见做法是让 Heap 占容器 limit 的一部分,而不是全部。
ephemeral-storage 的统计可能和预期不同临时存储通常涉及:
emptyDir但具体统计和隔离效果还受以下因素影响:
生产环境应验证:
并观察:
DiskPressure
ephemeral-storage
Evicted
node_filesystem_avail_bytes设置了 ephemeral-storage limit,也不能替代节点磁盘监控和日志轮转。
传统资源配置是容器级别:
较新的 Kubernetes 版本开始支持 Pod 级别的 resources:
该能力与 Kubernetes 版本和 Feature Gate 有关,不能假设所有集群都支持。
使用前确认:
kubectl version
kubectl explain pod.spec.resources如果集群不支持,可能出现字段无法识别或资源行为与预期不同。
生产环境引入 Pod 级资源前,需要验证:
GPU、FPGA 等扩展资源通常需要:
不能像 CPU 一样随意设置:
requests:
对于扩展资源,一般原则是:
requests == limits而且通常要求使用整数:
nvidia.com/gpu: 1不能写成:
nvidia.com/gpu: "500m"Kubernetes 支持自定义扩展资源,例如:
resources:
limits:
example.com/fpga: 1但这通常需要:
查看节点上可用资源:
kubectl describe node <node-name>查看:
Capacity
Allocatable如果节点没有注册该资源,Pod 会一直 Pending。
假设 Deployment 有:
replicas:
发布期间可能同时存在:
10 个旧 Pod + 3 个新 Pod如果每个 Pod 的 request 是:
CPU:500m
内存:1Gi发布瞬间额外需要:
CPU:1.5
内存:3Gi如果没有预留发布容量,可能出现:
新 Pod Pending
Deployment 发布卡住
ResourceQuota exceeded
PDB 阻塞生产中资源配置要和发布策略一起规划:
strategy:
不是所有业务都适合使用默认的 25%。
Cluster Autoscaler 通常根据 Pod 的调度需求和 request 判断是否需要增加节点。
如果 request 过大:
Pod 可能需要很大的节点才能调度
自动扩容成本增加如果 request 过小:
Pod 可能被调度到看似有容量、实际无法承载峰值的节点如果设置了:
nodeSelector:
workload: high-memory或者:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:还必须确认目标节点池具备足够资源。
资源规划不能只看总集群容量,还要看:
节点规格
节点池类型
调度约束
可用区
GPU/设备资源
Pod 拓扑分布例如节点规格:
16 CPU集群剩余资源总量可能还有:
CPU 8但分散在多个节点:
节点 A 剩余 2 CPU
节点 B 剩余 2 CPU
节点 C 剩余 2 CPU
节点 D 剩余 2 CPU如果新 Pod 需要:
requests:
cpu: "6"虽然集群总剩余量足够,但没有任何单个节点能放下,Pod 仍然无法调度。
这叫资源碎片或装箱问题。
需要结合:
进行分析。
kubectl top 不能直接决定 requestskubectl top 只能看到当前或近期使用情况:
kubectl top pod -n production
它通常不足以直接决定生产资源,因为:
更合理的方式是使用 Prometheus 等系统分析:
可以用以下方法作为初始估算。
CPU request ≈ 稳定负载 P95 + 运行时余量Memory request ≈ 稳定 working set P95 + 运行时余量Memory limit ≈ 峰值 working set + 应用额外开销 + 安全余量Pod request =
普通容器 request 总和
与 Init Container 最大 request 的较大值
+ Pod overhead这只是估算方法,不是 Kubernetes 的强制公式。最终仍要通过压测和线上观察校准。
可以把团队的资源治理分成几个阶段。
resources: {}问题:
使用统一默认值:
LimitRange
ResourceQuota优点:
问题:
业务显式声明:
resources:
requests:
limits:同时使用:
进一步引入:
到这里,Kubernetes Resources 从 API 配置、调度、cgroup、QoS、扩缩容、特殊资源、发布容量到生产治理边界,基本就完整了。
spec:
containers:
- name: app
image: example/app:v1
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"spec:
containers:
- name: app
image: example/app:v1
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
- name: sidecar
image: example/sidecar:v1
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "300m"
memory: "256Mi"memory: "128Mi"
memory: "512Mi"
memory: "1Gi"
memory: "2Gi"resources:
requests:
cpu: "1"
memory: "512Mi"
limits:
cpu: "1"
memory: "512Mi"resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"resources:
requests:
cpu: "2"
limits:
cpu: "1"resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "1"
memory: "1Gi"resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"kubectl get pod <pod-name> -n <namespace> \
-o jsonpath='{.status.qosClass}{"\n"}'Capacity:
cpu: 8
memory: 32Gi
Allocatable:
cpu: 7.5
memory: 30Gi
Allocated resources:
cpu requests: 5
cpu limits: 12
memory requests: 18Gi
memory limits: 40GiapiVersion: v1
kind: LimitRange
metadata:
name: resource-policy
namespace: production
spec:
limits:
- type: Container
defaultRequest:
cpu: "200m"
memory: "256Mi"
default:
cpu: "1"
memory: "1Gi"
min:
cpu: "10m"
memory: "64Mi"
max:
cpu: "8"
memory: "16Gi"apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "100"
requests.memory: "200Gi"
limits.cpu: "200"
limits.memory: "400Gi"
pods: "200"apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 3
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70resources:
requests:
ephemeral-storage: "512Mi"
limits:
ephemeral-storage: "2Gi"kubectl describe node <node-name>
kubectl describe pod <pod-name> -n <namespace>apiVersion: v1
kind: ResourceQuota
metadata:
name: gpu-quota
namespace: ai
spec:
hard:
requests.nvidia.com/gpu: "8"
limits.nvidia.com/gpu: "8"resources:
requests:
hugepages-2Mi: 512Mi
limits:
hugepages-2Mi: 512Miresources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
memory: "2Gi"apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: example/api:v1.2.0
ports:
- containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"resources:
requests:
cpu: "2"
memory: "2Gi"
limits:
memory: "4Gi"resources:
requests:
cpu: "500m"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"apiVersion: batch/v1
kind: Job
metadata:
name: report-job
namespace: batch
spec:
template:
spec:
restartPolicy: Never
containers:
- name: report
image: example/report:v1
resources:
requests:
cpu: "1"
memory: "2Gi"
limits:
cpu: "4"
memory: "8Gi"resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "2"
memory: "1Gi"apiVersion: v1
kind: Pod
metadata:
name: worker
spec:
containers:
- name: worker
image: example/worker:v1
resources:
requests:
cpu: "200m"
memory: "256Mi"
ephemeral-storage: "512Mi"
limits:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "2Gi"
volumes:
- name: cache
emptyDir:
sizeLimit: 1GiapiVersion: apps/v1
kind: Deployment
metadata:
name: inference
namespace: ai
spec:
replicas: 1
selector:
matchLabels:
app: inference
template:
metadata:
labels:
app: inference
spec:
nodeSelector:
accelerator: nvidia
containers:
- name: inference
image: example/inference:v1
resources:
requests:
cpu: "2"
memory: "8Gi"
nvidia.com/gpu: 1
limits:
cpu: "4"
memory: "16Gi"
nvidia.com/gpu: 1requests:
cpu: "1"
memory: "1Gi"
limits:
memory: "2Gi"kubectl get resourcequota -n <namespace>
kubectl describe resourcequota -n <namespace>kubectl get pod <pod-name> -n <namespace> \
-o jsonpath='{.status.qosClass}{"\n"}'CPU P50/P95/P99
内存 working set
OOMKill
CPU throttling
Pod 重启
节点压力
Pod 驱逐
调度失败
磁盘使用率在线 API
消息消费者
批处理
定时任务
Java 服务
数据库
DaemonSet
GPU 工作负载
带 Sidecar 的服务resources:
requests:
cpu: "250m"
memory: "512Mi"
limits:
cpu: "1"
memory: "1Gi"apiVersion: v1
kind: LimitRange
metadata:
name: production-resource-policy
namespace: production
spec:
limits:
- type: Container
defaultRequest:
cpu: "200m"
memory: "256Mi"
ephemeral-storage: "256Mi"
default:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "2Gi"
min:
cpu: "10m"
memory: "64Mi"
ephemeral-storage: "32Mi"
max:
cpu: "8"
memory: "16Gi"
ephemeral-storage: "20Gi"
maxLimitRequestRatio:
cpu: "10"
memory: "4"
ephemeral-storage: "8"
- type: Pod
max:
cpu: "16"
memory: "32Gi"
ephemeral-storage: "40Gi"
- type: PersistentVolumeClaim
min:
storage: "1Gi"
max:
storage: "2Ti"apiVersion: v1
kind: ResourceQuota
metadata:
name: production-quota
namespace: production
spec:
hard:
requests.cpu: "100"
requests.memory: "200Gi"
limits.cpu: "200"
limits.memory: "400Gi"
requests.ephemeral-storage: "1Ti"
limits.ephemeral-storage: "2Ti"
pods: "200"
persistentvolumeclaims: "100"
requests.storage: "20Ti"apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: production
spec:
replicas: 3
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: example/api:v1.0.0
ports:
- containerPort: 8080
resources:
requests:
cpu: "250m"
memory: "512Mi"
ephemeral-storage: "256Mi"
limits:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "2Gi"resources.requests:
Pod 调度时需要预留多少资源
resources.limits:
容器运行时最多允许使用多少资源
cpu:
可压缩资源,超限通常表现为 throttling
memory:
不可压缩资源,超限可能 OOMKill
ephemeral-storage:
容器临时存储、缓存、日志和 emptyDir 的资源边界
扩展资源:
GPU、HugePages 等特殊设备或内存资源ResourceQuota 限制 Namespace 总量resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "2"
memory: "4Gi"resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "1"
memory: "1Gi"resources:
requests:
cpu: "2"
limits:
cpu: "2"应用堆
Native Memory
线程栈
JVM Metaspace
Direct Buffer
Go runtime
文件映射
共享库
内存缓存
临时内存
Sidecarkubectl describe node <node-name>
kubectl describe pod <pod-name> -n <namespace>spec:
containers:
- name: app
resources:
requests:
cpu: "500m"spec:
resources:
requests:
cpu: "1"
memory: "1Gi"
limits:
cpu: "2"
memory: "2Gi"
containers:
- name: app
image: example/app:v1resources:
requests:
nvidia.com/gpu: 1
limits:
nvidia.com/gpu: 1CPU P50/P95/P99
内存 working set P95/P99
峰值持续时间
OOM 次数
CPU throttling
请求延迟
吞吐量
副本数变化[ ] 每个关键容器是否显式声明 resources
[ ] requests 是否基于历史数据
[ ] memory limit 是否包含运行时额外开销
[ ] CPU limit 是否经过 throttling 压测
[ ] 是否考虑 Init Container
[ ] 是否考虑 Sidecar
[ ] 是否考虑 Pod overhead
[ ] 是否考虑 DaemonSet 总量
[ ] 是否设置 ephemeral-storage
[ ] 是否配置 LimitRange
[ ] 是否配置 ResourceQuota
[ ] 是否有 CI 或 Admission 校验
[ ] HPA 是否依赖合理的 CPU request
[ ] VPA 是否与 HPA 冲突
[ ] 滚动发布是否有额外容量
[ ] 节点是否预留系统资源
[ ] 是否监控 OOMKill
[ ] 是否监控 CPU throttling
[ ] 是否监控磁盘压力
[ ] 是否监控调度失败
[ ] 是否定期重新评估 requests/limitsresources.requests:
影响调度、CPU 权重、HPA、QoS 和容量规划
resources.limits:
影响运行时上限、CPU throttling、OOMKill 和驱逐风险
CPU:
可压缩,重点关注性能和 throttling
Memory:
不可压缩,重点关注 OOM 和运行时额外开销
ephemeral-storage:
重点关注容器日志、emptyDir、缓存和节点磁盘压力
GPU/HugePages:
属于特殊资源,需要节点、设备插件和调度策略配合
生产资源治理:
显式声明 + LimitRange + ResourceQuota
+ HPA/VPA + Admission Policy + 监控 + 持续校准