77·调度与资源进阶

资源限制

kubernetesresourceslimits

资源限制

学习目标

  1. 理解资源限制(limits)的概念和作用
  2. 掌握 CPU 和内存限制的行为差异
  3. 了解 OOM Killer 和 CPU 节流机制

核心概念

一句话解释

资源限制定义 Pod 可以使用的最大资源量,超过限制会被限制(CPU)或杀掉(内存)。

Requests 与 Limits 关系

┌─────────────────────────────────────────────────────────┐
│                    资源模型                              │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  ┌─────────────────────────────────────────┐           │
│  │  节点 CPU: 4 核, 内存: 8Gi              │           │
│  │                                         │           │
│  │  ┌─────────────────────────────────┐    │           │
│  │  │  Pod A                          │    │           │
│  │  │  requests: cpu=500m, mem=256Mi  │    │           │
│  │  │  limits:   cpu=1,    mem=512Mi  │    │           │
│  │  │                                 │    │           │
│  │  │  ┌─────────────────────────┐    │    │           │
│  │  │  │  实际使用: 0.8 CPU      │    │    │           │
│  │  │  │  实际使用: 300Mi 内存   │    │    │           │
│  │  │  └─────────────────────────┘    │    │           │
│  │  │                                 │    │           │
│  │  │  - 保证获得 500m CPU           │    │           │
│  │  │  - 最多使用 1 CPU              │    │           │
│  │  │  - 超过 1 CPU 会被节流         │    │           │
│  │  └─────────────────────────────────┘    │           │
│  └─────────────────────────────────────────┘           │
│                                                         │
└─────────────────────────────────────────────────────────┘

YAML 语法

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        cpu: "500m"
        memory: "256Mi"
      limits:
        cpu: "1000m"
        memory: "512Mi"

CPU 限制行为

┌─────────────────────────────────────────────────────────┐
│                    CPU 节流                              │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  CPU 是可压缩资源                                        │
│  - 超过 limits 不会被杀掉                               │
│  - 会被节流(throttled)                                │
│                                                         │
│  时间 ──────────────────────────────────────────────►  │
│                                                         │
│  限制: 1 CPU                                            │
│  ┌─────────────────────────────────────────┐           │
│  │  请求: 1.5 CPU                          │           │
│  │                                         │           │
│  │  ████████████░░░░░░████████████░░░░░░░  │           │
│  │  运行 1 CPU    节流  运行 1 CPU   节流   │           │
│  └─────────────────────────────────────────┘           │
│                                                         │
│  实际获得的 CPU 时间受限,但进程不会被杀掉               │
│                                                         │
└─────────────────────────────────────────────────────────┘

内存限制行为

┌─────────────────────────────────────────────────────────┐
│                    OOM Killer                           │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  内存是不可压缩资源                                      │
│  - 超过 limits 会被 OOM Killer 杀掉                     │
│                                                         │
│  内存使用                                                │
│  │                                                      │
│  │  ┌─────────────────────────────────┐  limits: 512Mi │
│  │  │                                 │                 │
│  │  │     ████████████████████        │                 │
│  │  │     │  实际使用 400Mi  │        │  requests: 256Mi│
│  │  │     ████████████████████        │                 │
│  │  │                                 │                 │
│  │  └─────────────────────────────────┘                 │
│  │                                                      │
│  │  ┌─────────────────────────────────┐  limits: 512Mi │
│  │  │                                 │                 │
│  │  │     ████████████████████████    │                 │
│  │  │     │   实际使用 600Mi     │    │                 │
│  │  │     ████████████████████████    │  OOM Killed!   │
│  │  │                                 │                 │
│  │  └─────────────────────────────────┘                 │
│  │                                                      │
│  └──────────────────────────────────────────────────────│
│                                                         │
└─────────────────────────────────────────────────────────┘

QoS 类别

┌─────────────────────────────────────────────────────────┐
│                    QoS 类别                              │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  Guaranteed(保证)                                      │
│  - requests == limits(所有容器)                        │
│  - 最高优先级,最后被杀掉                               │
│                                                         │
│  Burstable(可突发)                                     │
│  - requests < limits(至少一个容器)                    │
│  - 中等优先级                                           │
│                                                         │
│  BestEffort(尽力而为)                                  │
│  - 没有设置 requests 和 limits                          │
│  - 最低优先级,最先被杀掉                               │
│                                                         │
│  优先级:Guaranteed > Burstable > BestEffort            │
│                                                         │
└─────────────────────────────────────────────────────────┘

LimitRange 默认值

# 设置默认 limits
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: my-namespace
spec:
  limits:
  - default:           # 默认 limits
      cpu: "500m"
      memory: "256Mi"
    defaultRequest:    # 默认 requests
      cpu: "100m"
      memory: "128Mi"
    max:               # 最大 limits
      cpu: "2"
      memory: "2Gi"
    min:               # 最小 requests
      cpu: "50m"
      memory: "64Mi"
    type: Container

实践练习

练习 1:设置资源限制

# pod-limits.yaml
apiVersion: v1
kind: Pod
metadata:
  name: limits-pod
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        cpu: "250m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "256Mi"
kubectl apply -f pod-limits.yaml
kubectl describe pod limits-pod | grep -A 10 "Limits"

练习 2:观察 CPU 节流

# pod-cpu-throttle.yaml
apiVersion: v1
kind: Pod
metadata:
  name: cpu-throttle
spec:
  containers:
  - name: stress
    image: polinux/stress
    command: ["stress"]
    args: ["--cpu", "2"]  # 尝试使用 2 核 CPU
    resources:
      limits:
        cpu: "500m"  # 限制为 0.5 核
kubectl apply -f pod-cpu-throttle.yaml
# 观察 CPU 使用率和节流情况
kubectl top pod cpu-throttle

练习 3:观察 OOM Killer

# pod-oom.yaml
apiVersion: v1
kind: Pod
metadata:
  name: oom-pod
spec:
  containers:
  - name: stress
    image: polinux/stress
    command: ["stress"]
    args: ["--vm", "1", "--vm-bytes", "300M"]  # 尝试使用 300Mi 内存
    resources:
      limits:
        memory: "128Mi"  # 限制为 128Mi
kubectl apply -f pod-oom.yaml
# 观察 Pod 状态
kubectl get pod oom-pod -w
# 应该会被 OOM Killed

# 查看 Pod 状态和原因
kubectl describe pod oom-pod | grep -A 10 "Last State"

练习 4:查看 QoS 类别

# 不同 QoS 类别的 Pod
apiVersion: v1
kind: Pod
metadata:
  name: guaranteed-pod
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        cpu: "500m"
        memory: "256Mi"
      limits:
        cpu: "500m"
        memory: "256Mi"
---
apiVersion: v1
kind: Pod
metadata:
  name: burstable-pod
spec:
  containers:
  - name: nginx
    image: nginx
    resources:
      requests:
        cpu: "250m"
        memory: "128Mi"
      limits:
        cpu: "500m"
        memory: "256Mi"
---
apiVersion: v1
kind: Pod
metadata:
  name: besteffort-pod
spec:
  containers:
  - name: nginx
    image: nginx
kubectl apply -f qos-pods.yaml

# 查看 QoS 类别
kubectl get pods -o custom-columns=NAME:.metadata.name,QOS:.status.qosClass

练习 5:使用 LimitRange

# limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
spec:
  limits:
  - default:
      cpu: "500m"
      memory: "256Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    type: Container
kubectl apply -f limitrange.yaml

# 创建不带资源设置的 Pod
kubectl run test-pod --image=nginx

# 查看 Pod 的资源设置(自动添加默认值)
kubectl get pod test-pod -o yaml | grep -A 10 resources

最佳实践

1. 始终设置 limits
   - 防止单个 Pod 耗尽节点资源
   - 特别是内存限制

2. requests 和 limits 的比例
   - CPU: requests <= limits
   - 内存: requests <= limits
   - 建议 ratio: 1:2 到 1:4

3. 根据工作负载类型设置
   - CPU 密集型:关注 CPU limits
   - 内存密集型:关注内存 limits

4. 使用 LimitRange 强制限制
   - 设置默认值
   - 设置最大/最小值

5. 监控和调整
   - 使用 kubectl top 查看实际使用
   - 根据监控数据调整 limits

常见问题

1. Pod 被 OOM Killed

# 查看 Pod 状态
kubectl describe pod <pod-name> | grep -A 10 "Last State"

# 原因:内存使用超过 limits
# 解决:增加内存 limits 或优化应用内存使用

2. CPU 使用率低但应用响应慢

# 查看 CPU 节流情况
kubectl top pod <pod-name>

# 原因:CPU limits 过低导致节流
# 解决:增加 CPU limits

3. 不设置 limits 会怎样?

# CPU: 可以使用节点所有可用 CPU(共享)
# 内存: 无限制,可能导致 OOM

# 建议:至少设置内存 limits
resources:
  requests:
    cpu: "100m"
    memory: "128Mi"
  limits:
    memory: "256Mi"  # 至少设置内存限制

小结

要点说明
limitsPod 可以使用的最大资源量
CPU 超限会被节流(throttled),不会被杀
内存超限会被 OOM Killer 杀掉
QoS 类别Guaranteed > Burstable > BestEffort
LimitRange设置默认和最大/最小值
最佳实践始终设置内存 limits,合理设置 CPU limits

练习编辑器

bash
Loading...

继续学习

完成本课后,建议继续学习下一课「QoS 类别」 以巩固所学知识。