容器 的 cpu request limit 与 linux cgroups 的关系

Kubernetes 通过对 Cgroups 的精细控制来实现其 requestslimits 机制。

简单来说:

  • requests -> 主要对应 cpu.shares
  • limits -> 主要对应 cpu.cfs_quota_uscpu.cfs_period_us

下面我们进行详细的分解和解释。


核心概念对应关系

Kubernetes 概念 Cgroup 文件 作用机制 性质
spec.containers[].resources.requests.cpu cpu.shares 相对权重(Shares) 软限制、弹性
spec.containers[].resources.limits.cpu cpu.cfs_quota_us cpu.cfs_period_us 绝对上限(Quota) 硬限制、严格

1. CPU Request (requests.cpu) -> cpu.shares

  • 作用requests.cpu 在 Kubernetes 中表示容器请求的、保证的最小 CPU 资源量。它主要影响 Pod 的调度------调度器会确保节点上有足够的可用资源(CPU 和内存)才会将 Pod 分配上去。
  • Cgroups 实现 :Kubernetes 通过设置 Cgroup v1 的 cpu.shares 属性来实现这一点。
  • 工作原理
    • cpu.shaes 是一个相对权重,而不是一个绝对的 CPU 核心数。
    • 它的默认值是 1024。
    • Kubernetes 的计算公式大致为:容器申请的 cpu.shares = 1024 * requests.cpu
    • 例如 :如果一个容器设置了 requests.cpu: 1.5,那么它的 cpu.shares 将被设置为 1024 * 1.5 = 1536
  • 行为
    • 当节点上的 CPU 资源充足 时,一个设置了 requests.cpu 的容器可以使用的 CPU 可以超过其请求值,它几乎可以使用任何空闲的 CPU。
    • 当节点上的 CPU 资源紧张 (多个容器竞争 CPU)时,CFS(完全公平调度器)会根据每个容器的 cpu.shares 比例来分配 CPU 时间。
    • 再例如 :假设一个节点上只有两个 Pod:
      • Pod A: requests.cpu: 1 -> cpu.shares = 1024
      • Pod B: requests.cpu: 2 -> cpu.shares = 2048
      • 当两者都全力使用 CPU 时,它们将按照 1024:2048(即 1:2)的比例分配 CPU 时间。Pod A 大约获得 33% 的 CPU,Pod B 大约获得 66% 的 CPU。

总结:requests.cpu 通过 cpu.shares 确保在资源竞争时获得最低保证份额,是一种"软"限制。


2. CPU Limit (limits.cpu) -> cpu.cfs_quota_us & cpu.cfs_period_us

  • 作用limits.cpu 在 Kubernetes 中表示容器能使用的 CPU 资源的绝对硬性上限,无论节点上的 CPU 是否空闲,它都不能超过这个限制。
  • Cgroups 实现 :Kubernetes 通过设置 Cgroup v1 的 CPU 带宽控制 (CPU bandwidth control)子系统来实现,即 cpu.cfs_quota_uscpu.cfs_period_us 这两个文件。
    • cpu.cfs_period_us:定义了一个时间周期(单位:微秒),通常固定设置为 100,000 μs(即 100毫秒)。
    • cpu.cfs_quota_us:定义了在以上一个周期内,该容器最多可以使用的 CPU 时间(单位:微秒)。
  • 工作原理
    • 计算公式为:cpu.cfs_quota_us = limits.cpu * cpu.cfs_period_us
    • 例如 :如果一个容器设置了 limits.cpu: 1,那么:
      • cpu.cfs_period_us = 100000
      • cpu.cfs_quota_us = 1 * 100000 = 100000
      • 这意味着在每 100ms 的时间内,该容器最多可以使用 100ms 的 CPU 时间,即相当于独占 1 个 CPU 核心
    • 再例如 :如果一个容器设置了 limits.cpu: 1.5,那么:
      • cpu.cfs_quota_us = 1.5 * 100000 = 150000
      • 这意味着在每 100ms 的时间内,该容器最多可以使用 150ms 的 CPU 时间,即相当于独占 1.5 个 CPU 核心
    • 如果容器在周期内耗尽了它的配额(cpu.cfs_quota_us),它就会被节流(Throttled),必须等待下一个周期才能继续运行。

总结:limits.cpu 通过 cpu.cfs_quota_uscpu.cfs_period_us 设置一个严格的"天花板",是一个"硬"限制。


综合示例与实践意义

一个 Pod 的配置可以同时包含 requestslimits

apiVersion: v1

kind: Pod

metadata:

name: example-pod

spec:

containers:

  • name: example-container
    image: nginx
    resources:
    requests:
    memory: "64Mi"
    cpu: "0.5" # 请求 0.5 核
    limits:
    memory: "128Mi"
    cpu: "1" # 限制最多使用 1 核

在这个例子中:

  1. 调度:调度器会寻找至少有 0.5 核空闲 CPU 和 64MiB 空闲内存的节点。
  2. Cgroups 设置
    • CPU :
      • cpu.shares = 1024 * 0.5 = 512
      • cpu.cfs_quota_us = 1 * 100000 = 100000
      • cpu.cfs_period_us = 100000
    • 内存 :也会设置对应的 memory.limit_in_bytes 为 128MiB。

实践意义:

  • 设置 requests 而不设置 limits:容器可以弹性使用尽可能多的空闲 CPU,但在竞争时享有保证的最低份额。适用于可以充分利用空闲资源但不需要严格限制的应用。
  • 设置 limits 而不设置 requestsrequests 会默认等于 limits。这保证了 Pod 的资源,但缺乏弹性。通常不建议,除非你明确希望如此。
  • 同时设置 requestslimits:这是最常见和推荐的做法。它既保证了 Pod 的调度和最小资源,又防止 bug 或异常导致单个 Pod 耗尽整个节点的资源( noisy neighbor 问题)。

因此,Kubernetes 通过将高级别的 requestslimits 概念映射到 Cgroups 底层的不同控制机制,实现了既灵活又严格的混合资源管理策略。

相关推荐
一叶龙洲7 小时前
wslg打开Ubuntu24.04默认打开图形界面
linux·服务器·数据库·ubuntu
敖行客 Allthinker8 小时前
Parallels Ubuntu虚拟机项目如何让手机访问?完整解决方案
linux·运维·ubuntu
keyipatience10 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
元Y亨H10 小时前
生产环境监控与故障应急处理(5-5-5 标准)指南
运维
j7~10 小时前
【Linux】二十二.《Linux 信号机制完全指南:表示、捕捉与处理》
linux·信号处理·volatile·可入重函数·保存信号
踏月的造梦星球10 小时前
达梦数据库执行计划与性能分析入门:EXPLAIN、AUTOTRACE 与 ET
服务器·数据库·oracle
heimeiyingwang11 小时前
【架构实战】可观测性三支柱:日志、指标、链路的融合
elasticsearch·架构·kubernetes
观山岳五楼11 小时前
Ubuntu 24 怎么使用Ubuntu 20 的镜像源
linux·运维·ubuntu
星夜夏空9911 小时前
网络编程(1)
服务器·网络
川石课堂软件测试11 小时前
安全测试|常见SQL注入攻击方式、实例及预防
服务器·数据库·sql·功能测试·测试工具·安全·单元测试