Wiki LogoWiki - The Power of Many

Kubernetes 资源控制: 深入理解 Cgroups 机制

解析 Kubernetes 如何利用 Linux Control Groups (cgroups) 实现 Pod 的资源限制, 公平分配以及 QoS 分级.

在 Kubernetes 中, 资源管理的核心在于 "限制" 与 "隔离". 这种能力并非由 Kubernetes 凭空创造, 而是建立在 Linux 内核的 Control Groups (cgroups) 机制之上.


1. Cgroups 基础

1.1 什么是 Cgroups

Cgroups 是 Linux 内核提供的一种机制, 用于对一组进程进行资源配额和度量:

功能描述
资源限制限制 CPU, 内存, I/O 等使用量
优先级分配资源权重
统计监控资源使用情况
控制冻结, 恢复进程组

1.2 Cgroups 层级


2. Cgroups 控制器

2.1 主要控制器

控制器功能文件
cpuCPU 时间配额cpu.cfs_quota_us, cpu.shares
cpusetCPU 核心绑定cpuset.cpus, cpuset.mems
memory内存限制memory.limit_in_bytes
blkio块 I/O 限制blkio.throttle.*
pids进程数限制pids.max

2.2 v1 vs v2 对比

特性Cgroups v1Cgroups v2
层级每个控制器独立层级统一层级
接口各控制器接口不同统一接口
内存控制基础更精细 (memory.high)
I/O 控制基础更强 (统一回写控制)
默认状态大多数发行版新发行版默认

3. Kubernetes 资源配置

3.1 Requests 与 Limits

spec:
  containers:
  - name: app
    resources:
      requests:
        cpu: "500m"      # 0.5 核
        memory: "256Mi"
      limits:
        cpu: "1000m"     # 1 核
        memory: "512Mi"

3.2 CPU 映射

K8s 配置Cgroup 参数计算
requests.cpucpu.shares1000m = 1024 shares
limits.cpucpu.cfs_quota_us1000m = 100000 (1 period)

示例: limits.cpu: 500m

  • period = 100000 μs (100ms)
  • quota = 50000 μs (50ms)
  • 含义: 每 100ms 只能使用 50ms CPU 时间

3.3 内存映射

K8s 配置Cgroup 参数
limits.memorymemory.limit_in_bytes
requests.memory用于调度, 不直接映射

OOM 行为:

  • 超过 limit → OOM Kill
  • 容器退出, 根据 restartPolicy 重启

4. QoS 分级

4.1 三个等级

4.2 判定条件

QoS条件oom_score_adj
Guaranteed所有容器 requests = limits (全设置)-997
Burstable至少一个容器有 request2 - 999
BestEffort无任何 requests/limits1000

4.3 Guaranteed 示例

spec:
  containers:
  - name: app
    resources:
      requests:
        cpu: "1"
        memory: "1Gi"
      limits:
        cpu: "1"         # = requests
        memory: "1Gi"    # = requests

4.4 Cgroup 层级

/sys/fs/cgroup/kubepods.slice/
├── kubepods-besteffort.slice/     # BestEffort Pod
│   └── kubepods-besteffort-pod<uid>.slice/
├── kubepods-burstable.slice/      # Burstable Pod
│   └── kubepods-burstable-pod<uid>.slice/
└── kubepods-pod<uid>.slice/       # Guaranteed Pod
    └── <container-id>/

5. CPU 节流 (Throttling)

5.1 CFS 调度器原理

5.2 监控节流

# 查看 CPU 统计
cat /sys/fs/cgroup/cpu/kubepods.slice/.../cpu.stat
# nr_periods: 周期数
# nr_throttled: 被节流次数
# throttled_time: 被节流总时间 (ns)

# Prometheus 指标
container_cpu_cfs_throttled_periods_total
container_cpu_cfs_throttled_seconds_total

5.3 节流问题排查

现象可能原因
高节流, 低利用率瞬时突发超过配额
延迟增加等待下一个 period
响应时间不稳定周期性节流

解决方案:

  1. 增加 CPU limits
  2. 优化应用减少 CPU 突发
  3. 考虑 CPU Burst (内核支持)

6. 内存管理

6.1 内存层级

# Cgroups v2
memory.current   # 当前使用量
memory.min       # 最低保证 (不可回收)
memory.low       # 低优先级回收阈值
memory.high      # 软限制 (触发回收)
memory.max       # 硬限制 (触发 OOM)

6.2 OOM 处理

6.3 内存监控

# 查看内存使用
cat /sys/fs/cgroup/memory/kubepods.slice/.../memory.usage_in_bytes
cat /sys/fs/cgroup/memory/kubepods.slice/.../memory.limit_in_bytes

# Prometheus 指标
container_memory_usage_bytes
container_memory_working_set_bytes
container_memory_rss

7. 资源配额最佳实践

7.1 设置原则

原则说明
始终设置 requests影响调度决策
合理设置 limits防止单个 Pod 耗尽资源
requests ≤ limits必须满足
观察后调整基于实际使用量优化

7.2 推荐配置

# 生产环境建议
resources:
  requests:
    cpu: "100m"      # 基于 P50 使用量
    memory: "128Mi"  # 略高于稳态使用
  limits:
    cpu: "500m"      # 允许突发
    memory: "256Mi"  # 防止内存泄漏

7.3 Namespace 配额

apiVersion: v1
kind: ResourceQuota
metadata:
  name: team-quota
  namespace: team-a
spec:
  hard:
    requests.cpu: "10"
    requests.memory: "20Gi"
    limits.cpu: "20"
    limits.memory: "40Gi"
    pods: "50"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: team-a
spec:
  limits:
  - default:
      cpu: "500m"
      memory: "512Mi"
    defaultRequest:
      cpu: "100m"
      memory: "128Mi"
    type: Container

8. 高级特性

8.1 CPU 亲和性 (cpuset)

# Guaranteed Pod 可使用 static CPU manager
# kubelet 配置
--cpu-manager-policy=static
--reserved-cpus=0-1

8.2 拓扑感知 (Topology Manager)

# kubelet 配置
--topology-manager-policy=best-effort
--topology-manager-scope=container

8.3 内存 QoS (v2)

# 启用 MemoryQoS feature gate
--feature-gates=MemoryQoS=true

9. 调试命令

# 查看 Pod Cgroup 路径
kubectl get pod <name> -o jsonpath='{.metadata.uid}'
ls /sys/fs/cgroup/kubepods.slice/

# 查看 CPU 配置
cat /sys/fs/cgroup/cpu/.../cpu.shares
cat /sys/fs/cgroup/cpu/.../cpu.cfs_quota_us

# 查看内存配置
cat /sys/fs/cgroup/memory/.../memory.limit_in_bytes

# 使用 crictl
crictl inspect <container-id> | jq '.info.runtimeSpec.linux.resources'

Cgroups 是 K8s 实现多租户隔离的基石. 理解了 cgroup 的权重和配额机制, 才能真正做到对集群容量心中有数.

On this page