Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

资源配置与容量管理

本章详细说明 K3s 集群中 SessionWorker 容器的资源限制机制——CPU、内存、磁盘如何被分配和隔离,以及 Backend 如何配置和监控这些资源。

核心概念:K8s(Kubernetes,容器编排系统)通过 Linux cgroups(控制组)技术实现资源隔离。每个 Pod(容器组)运行在独立的 cgroup 中,操作系统内核负责强制执行资源上限,确保一个智能体容器不会影响宿主机或其他容器的正常运行。


1. 资源限制的底层原理:cgroups

1.1 什么是 cgroups

cgroups(Control Groups,控制组)是 Linux 内核提供的资源隔离机制。当 K3s 创建一个 SessionWorker Pod 时,containerd(容器运行时)会为该容器创建一个 cgroup,内核通过该 cgroup 控制容器可使用的资源上限。

graph TB
    subgraph HOST["用户本地机器"]
        KERNEL["Linux 内核<br/>cgroups 子系统"]
        subgraph CGROUP["cgroup: agent-worker-xxx"]
            CPU_CG["CPU 控制<br/>cpu.cfs_quota_us / cpu.cfs_period_us"]
            MEM_CG["内存控制<br/>memory.limit_in_bytes"]
            IO_CG["磁盘控制<br/>ephemeral-storage 监控"]
        end
        subgraph POD["SessionWorker Pod"]
            AC["agentcore 进程"]
        end
    end

    KERNEL --> CGROUP
    CGROUP --> POD
    AC -.->|"受 cgroup 限制"| CPU_CG
    AC -.->|"受 cgroup 限制"| MEM_CG
    AC -.->|"受 cgroup 限制"| IO_CG

    style HOST fill:#f5f5f5,stroke:#333
    style CGROUP fill:#fff3e0,stroke:#e65100
    style POD fill:#e8f4fd,stroke:#0969da

1.2 cgroups 如何控制 CPU

K8s 将 CPU requests/limits 转换为 cgroups v2 的以下参数:

K8s 配置cgroups 参数作用
requests.cpu: 500mcpu.weight(按比例分配)保证容器在 CPU 竞争时至少获得 0.5 核的计算时间
limits.cpu: 500mcpu.max = 50000 100000(50ms/100ms 周期)硬限制:每 100ms 周期内最多使用 50ms CPU 时间,即 0.5 核
  • 500m 表示 500 毫核(millicores),即 0.5 个 CPU 核心
  • 1000m = 1 = 1 个完整核心
  • 超过 limits 时:进程不会被杀死,而是被节流(throttled)——内核暂停进程直到下一个周期

1.3 cgroups 如何控制内存

K8s 配置cgroups 参数作用
requests.memory: 1Gi调度参考(保证节点有足够内存)K8s 调度器只把 Pod 放到有 >= 1Gi 可分配内存的节点上
limits.memory: 1Gimemory.max = 1073741824硬限制:容器总内存不超过 1Gi
  • 超过 limits 时:内核触发 OOM Killer(Out-Of-Memory 杀手),直接终止容器进程
  • 这比 CPU 严格得多——CPU 超限只是变慢,内存超限直接被杀
  • 因此 agentcore 需要控制自身内存使用,特别是处理大型上下文时

1.4 cgroups 如何控制磁盘

ephemeral-storage(临时存储)的限制方式与 CPU/内存不同:

K8s 配置机制作用
limits.ephemeral-storage: 4Gikubelet 周期性扫描容器写入量超过限额时驱逐(evict)Pod
  • K8s 不使用 cgroups 限制磁盘,而是通过 kubelet(节点代理程序)定期检查
  • 检查间隔默认约 10 秒
  • 超限后 Pod 被驱逐(不是进程被杀,而是整个 Pod 被删除重建)

2. Requests 与 Limits 的区别

这两个概念是理解 K8s 资源管理的关键:

概念含义类比
Requests(请求)容器运行的最低保障酒店预订:保证你有房间
Limits(限额)容器运行的最高上限自助餐上限:最多吃这么多
graph LR
    subgraph RANGE["资源使用范围"]
        R["Requests<br/>最低保障<br/>500m CPU"]
        L["Limits<br/>最高上限<br/>500m CPU"]
    end
    R -->|"实际使用在此范围内"| L

当前配置中 requests = limits(均为 500m CPU / 1Gi 内存),这意味着:

  • 容器获得固定资源配额,不多不少
  • 这种配置称为 Guaranteed QoS(保证型服务质量),是最稳定的模式
  • 适合本地部署(只有一台机器,资源管理要简单可控)

3. 当前资源配置

3.1 RuntimeProfile 配置文件

Backend 通过 runtime_profiles.yaml(运行时配置文件)定义不同的资源档位。每个智能体包可以指定使用哪个 profile:

Profile 名称CPU(requests/limits)内存(requests/limits)临时存储(requests/limits)
codex-standard500m / 500m1Gi / 1Gi4Gi / 4Gi
codex-large500m / 500m1Gi / 1Gi4Gi / 4Gi
claude-code-standard500m / 500m1Gi / 1Gi4Gi / 4Gi
claude-code-large500m / 500m1Gi / 1Gi4Gi / 4Gi

当前状态:四个 profile 的资源配置完全相同。这是初始阶段的简化设计,未来可根据不同智能体的实际资源消耗进行差异化配置。

3.2 资源单位说明

单位含义换算
m(毫核)CPU 时间片,1000m = 1 个核心500m = 0.5 核
Mi / Gi内存,Mi = 1024*1024 字节1Gi = 1024Mi = 约 1.07 GB
Ki / Mi / Gi存储同上4Gi = 约 4.29 GB

3.3 资源在代码中的流转

graph TB
    YAML["runtime_profiles.yaml<br/>资源档位配置"] --> RS["ResourceSettings<br/>cpu/memory/ephemeral_storage"]
    RS --> RM["resource_map()<br/>转换为 K8s Quantity"]
    RM --> SPEC["Container.resources<br/>requests + limits"]
    SPEC --> K8S["K8s API Server"]
    K8S --> KUBELET["kubelet 节点代理"]
    KUBELET --> CG["创建 cgroup<br/>设置资源限制"]

    style YAML fill:#e8f4fd,stroke:#0969da
    style CG fill:#fff3e0,stroke:#e65100

ResourceSettings(资源设置)的 Rust 类型定义:

#![allow(unused)]
fn main() {
pub struct ResourceSettings {
    pub cpu: String,               // 如 "500m"
    pub memory: String,            // 如 "1Gi"
    pub ephemeral_storage: String, // 如 "4Gi"
}
}

resource_map() 方法将其转换为 K8s API 所需的 BTreeMap<String, Quantity>,requests 和 limits 设置为相同值。


4. 容器安全上下文

除了资源限制,K8s 还通过 SecurityContext(安全上下文)限制容器的系统权限:

4.1 Pod 级安全设置

securityContext:
  runAsNonRoot: true         # 禁止以 root 身份运行
  runAsUser: 1000            # 以 UID 1000 运行所有进程
  runAsGroup: 1000           # 以 GID 1000 运行
  fsGroup: 1000              # 挂载卷的文件组设为 1000
  seccompProfile:
    type: RuntimeDefault     # 启用 seccomp 系统调用过滤
设置作用安全意义
runAsNonRoot强制非 root 运行即使镜像 Dockerfile 指定 root,K8s 也会拒绝启动
runAsUser: 1000固定 UIDagentcore 以普通用户身份运行,无法访问系统文件
fsGroup: 1000挂载卷文件组确保 agentcore 可以读写挂载的 workspace 目录
seccompProfile系统调用白名单阻止容器执行危险的系统调用(如 mountreboot

4.2 容器级安全设置

securityContext:
  allowPrivilegeEscalation: false  # 禁止提权
  capabilities:
    drop: ["ALL"]                  # 丢弃所有 Linux capabilities
  readOnlyRootFilesystem: false    # 允许写入(agentcore 需要临时文件)
设置作用
allowPrivilegeEscalation: false阻止通过 setuid/setgid 提升权限
capabilities.drop: ALL移除所有特殊权限(网络配置、进程管理等)
readOnlyRootFilesystem: falseagentcore 需要写入临时文件和日志

4.3 其他安全设置

automountServiceAccountToken: false   # 不挂载 K8s 服务账号令牌
terminationGracePeriodSeconds: 30     # 优雅关闭等待 30 秒
  • automountServiceAccountToken: false:防止容器内进程访问 K8s API,消除容器逃逸风险
  • terminationGracePeriodSeconds: 30:给 agentcore 30 秒时间保存状态后退出

5. 空闲回收策略(WorkerIdlePolicy)

SessionWorker 采用 Deployment 长驻模式,需要主动回收空闲资源:

5.1 策略参数

参数类型默认值说明
idle_ttl_secondsu64(必填)300(5 分钟)Worker 空闲多久后自动关闭
max_lifetime_secondsOption(可选)3600(1 小时)Worker 最长存活时间,无论是否空闲

5.2 回收流程

graph TD
    IDLE["Worker 进入 IDLE 状态"] --> TIMER["启动空闲计时器"]
    TIMER --> CHECK{"idle_ttl_seconds 到期?"}
    CHECK -->|"否, 收到新消息"| RESET["重置计时器"]
    RESET --> IDLE
    CHECK -->|"是"| DRAIN["进入 DRAINING 状态"]
    DRAIN --> SAVE["通过 WS 通知 Backend"]
    SAVE --> CLOSE["发送 WS Close 帧"]
    CLOSE --> EXIT["进程退出"]
    EXIT --> K8S["K8s 检测到 Pod 退出"]
    K8S --> DELETE["Deployment 缩容 / 删除"]

    IDLE --> MAX{"max_lifetime_seconds 到期?"}
    MAX -->|"是"| DRAIN
    MAX -->|"否"| IDLE

6. 节点健康监控

Backend 通过 K8s API 实时监控本地 K3s 节点的健康状态。

6.1 监控的指标

指标名含义健康值
Ready节点是否正常运行True
MemoryPressure节点内存是否紧张False
DiskPressure节点磁盘是否紧张False
PIDPressure节点进程数是否过多False
NetworkUnavailable节点网络是否不可用False

6.2 ClusterNodeStatus

Backend 将 K8s 节点状态转换为 ClusterNodeStatus(集群节点状态)供 Helper 展示:

#![allow(unused)]
fn main() {
pub struct ClusterNodeStatus {
    pub name: String,                    // 节点名称
    pub conditions: Vec<NodeCondition>,  // 上述 5 项指标
    pub allocatable: ResourceSummary,    // 可分配资源总量
    pub capacity: ResourceSummary,       // 资源总容量
}
}

Helper 通过 GET /api/v1/cluster/status 获取该信息,显示在右侧状态面板。


7. 容量规划指南

7.1 单个 Worker 的资源消耗

资源配额用途说明
CPU500m(0.5 核)主要消耗在 agentcore 推理框架、工具执行、文本处理
内存1Gi上下文缓存、推理中间状态、checkpoint 数据库缓存
磁盘4Giworkspace 文件、checkpoint 数据库、临时文件、日志

7.2 宿主机资源建议

场景最小配置推荐配置
1 个智能体同时运行2 核 / 4Gi 内存4 核 / 8Gi 内存
2-3 个智能体同时运行4 核 / 8Gi 内存8 核 / 16Gi 内存
4-6 个智能体同时运行8 核 / 16Gi 内存16 核 / 32Gi 内存

注意:上述配置需要为宿主机系统、K3s 组件、Backend 服务预留约 1-2 核 CPU 和 2-4Gi 内存。

7.3 磁盘空间规划

组件典型大小说明
K3s 系统约 500MiK3s 二进制 + 系统容器
容器镜像缓存约 1-5Gi取决于使用的智能体镜像数量
每个 Worker workspace最大 4Giephemeral-storage limits
checkpoint 数据库通常 < 100Mi / 会话取决于对话轮次和工具调用复杂度

8. 资源超限行为汇总

当容器超过资源限制时,K8s 的处理方式因资源类型而异:

资源超限行为严重程度恢复方式
CPU进程被节流(throttled),变慢但不被杀等待下一个 CPU 周期自动恢复
内存OOM Killer 终止进程,Pod 可能重启K8s 自动重启 Pod(受 restartPolicy 控制)
磁盘Pod 被驱逐(evicted),需要重新调度Backend 检测到 Pod 丢失,可能需要重建 Worker

9. 资源配置调优建议

9.1 CPU 调优

  • 当前 500m 适合大多数场景(agentcore 主要等待大模型 API 响应,CPU 实际使用率较低)
  • 如果智能体需要执行 CPU 密集型工具(如代码编译、数据处理),可提高到 1000m2000m
  • 通过 kubectl top pod 观察实际 CPU 使用率来决定

9.2 内存调优

  • 1Gi 适合一般对话场景
  • 处理长上下文(> 100k tokens)或大文件分析时,可能需要 2Gi 或更多
  • 内存超限后果严重(OOM Kill),建议 limits 设为实际峰值使用量的 1.5 倍

9.3 磁盘调优

  • 4Gi 足够大多数场景
  • 如果智能体需要下载大型数据集或生成大量文件,可提高到 8Gi16Gi
  • 注意:ephemeral-storage 是容器可写层 + emptyDir 的总和

10. 诊断命令

当需要排查资源问题时,可在本地终端执行以下命令:

命令用途
kubectl top nodes查看节点 CPU / 内存使用率
kubectl top pods -n agent-sandbox查看各 Pod 的 CPU / 内存实时使用
kubectl describe pod <pod-name> -n agent-sandbox查看 Pod 的资源请求、限制、事件(含 OOMKilled 记录)
kubectl get events -n agent-sandbox --sort-by=.metadata.creationTimestamp查看最近事件(驱逐、重启等)
kubectl describe node查看节点可分配资源和已分配量

下一步

了解了资源管理后,请继续阅读: