ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Kubernetes管Agent:云原生编排智能工作负载的工程实践

Kubernetes管Agent:云原生编排智能工作负载的工程实践 过去一年跟不少做 AI 应用的朋友聊天大家早就很少再吹“提示词写得好”了开口闭口全是部署、编排、扩缩容、成本控制。前几天看到“Google 把 Kubernetes 搬来管 Agent 了”这个说法我第一反应是Kubernetes 终于要从“管容器的平台”变成“管 Agent 的平台”了。这不是科幻趋势而是这半年我实打实看到的工程变化——越来越多 Agent 服务开始以 Deployment、Job、CRD 的形式跑进 K8s 集群由调度器统一分配算力由 Namespace 隔离权限由探针和资源配额来兜底质量。如果你对 Kubernetes 只有个模糊概念我先把话说白K8s 本质是一套“以 API 为中心”的编排系统它最擅长的事情不是跑某个具体软件而是把一堆服务当成资源来管——部署、扩容、重启、限流、监控、权限隔离全都能做。而现在所谓的“管 Agent”本质上也是同一套思路Agent 不再是某个人的实验脚本而是一类需要长期运行、反复执行、动态变配的生产工作负载。当这种需求出现“Google 把 Kubernetes 搬来管 Agent”这个说法就自然成了圈内对基础设施演进的一种浓缩表达。这篇文章我想拆两层先讲清楚为什么 Agent 需要 Kubernetes 这种“搬家公司”再讲实际操作里怎么把 Agent 当工作负载跑起来。适合正在做 Agent 工程化、准备把多个 Agent 推上线、或者刚接触云原生的朋友参考。我不会只给你一堆概念还会给出可以直接抄的部署示例和踩坑记录。1. 为什么大家开始把 Agent 交给 Kubernetes 管1.1 Agent 从“玩具”变成“生产负载”需求全变了以前我们聊 Agent聊的是“它能不能自己规划任务、调工具、翻资料”本质是在聊模型能力。但一旦 Agent 要真正解决业务问题比如自动处理售后工单、定时生成分析报告、在线上环境里调用内部系统问题就变了多个 Agent 同时跑谁来分配资源一个 Agent 卡死在循环里怎么及时发现模型接口突然超时Agent 要不要重试Prompt 更新了几十个实例怎么同步这些问题的共同点是它们不属于模型层而属于“基础设施层”。传统的做法是给每个 Agent 写一个 Python 脚本再用 systemd 或者裸 cron 跑着出问题人工盯着。一开始确实能跑但只要 Agent 数量上来这种模式立刻崩盘——因为你没有统一视图你不知道哪个 Agent 在干什么哪个 Agent 占了太多资源哪个 Agent 在偷偷调用敏感工具。Kubernetes 解决的就是这些“脏活累活”。它的调度器知道集群里有多少 CPU、多少内存、多少 GPUAgent 需要多少就申请多少不够就排队它的探针能检查 Agent 是不是还活着卡死了自动重启它的 HPA 可以根据请求量自动扩缩容流量高峰期弹性加副本闲下来自动回收。这些能力不需要你重新发明全是 yaml 里写几行就能用的。1.2 Kubernetes 那套设计恰好是 Agent 治理缺的那层Kubernetes 早期解决的问题是把微服务“容器化”但它沉淀下来的设计思想远比容器本身重要声明式状态、控制器模式、资源抽象、身份与权限模型。Agent 这类应用看起来和微服务完全不同——它有上下文、有记忆、会调用工具、输出还不确定——但只要换一个视角把 Agent 当“一个有状态或半有状态的计算单元”K8s 的抽象就完全能套上去。举个例子。一个 Agent 实例要跑需要三样东西模型访问凭证、系统提示词、工具调用链。对应到 K8s 里就是 Secret、ConfigMap、Service。 Agent 实例本身可以建模成 Pod 或 Deployment一次性的分析任务可以建模成 Job每天定时跑的周报 Agent 可以建模成 CronJob多副本且需要共享聊天记录的 Agent 可以建模成 StatefulSet。这不是硬套而是从资源调度的角度它们是同一类东西一段程序、一组配置、一堆依赖需要被可靠地跑起来。传统微服务和 Agent 工作负载之间还有几个关键差异我列个表对比一下方便大家理解为什么不能继续用老办法裸奔。维度传统微服务Agent / LLM 应用单元性质确定性接口输入输出可预期非确定性行为有自由度主要依赖数据库、中间件、网络模型服务、工具调用、上下文状态典型故障高延迟、宕机、连接池耗尽token 截断、工具挂起、推理循环、费用失控状态特征通常无状态状态放 DB会话上下文、记忆、工具会话状态资源特征CPU / 内存为主CPU GPU、模型缓存、向量索引、token 配额这张表不是要说明 Agent 更高级而是提醒我们Agent 负载比传统微服务更难预测更需要基础设施提供“兜底机制”。而 Kubernetes 恰好就是一套把“兜底”做得很成熟的系统。1.3 Google 那句“搬”实际是让 Agent 长在云原生底座上很多人看到“Google 把 Kubernetes 搬来管 Agent”会以为是某个具体产品。其实更准确的理解是Google 生态在把 AI 负载往 Kubernetes 原生方向推于是大家用一句口语把这件事概括了。背后的信号很明确——Agent 的编排和治理应该站在 K8s 这套开放、可移植、经过大规模验证的基础设施之上而不是各家公司再搞一套私有的调度集群。这个方向是有长远价值的。Kubernetes 的 API 是标准化的不管你的 Agent 用的是 LangChain、Anthropic 还是自研框架底层调度都可以统一到 K8s 上。今天用 A 云明天迁到 B 云或者从本地开发环境直接推到线上集群交付方式不会变。这就是把 Agent“搬”进 K8s 的核心意义你不再为 Agent 单独造一套轮子而是复用整个云原生生态。2. 把 Agent 映射到 Kubernetes 的底层模型2.1 Agent 不是一个容器而是 Pod 编排对象有个新手常犯的误解以为“把 Agent 容器化”就是把模型装进容器里。其实模型通常跑在独立的推理服务上Agent 只是一个调用模型的客户端程序它的职责是决定下一步调用什么、什么时候调用工具、如何把结果拼接给用户。所以当你把一个 Agent 部署到 K8s 里你部署的是一个“逻辑大脑”的载体。这个载体需要连接模型服务、需要访问工具、需要读写状态。最最基本的做法就是把它做成 Deployment每个 Agent 副本就是一个 Pod。Pod 是 K8s 里最小的调度单位有独立的网络命名空间、存储挂载和资源配额天然适合承载 Agent 运行时。我从实际经验里给出的建议是如果你只有一个 Agent先别急着设计复杂的 CRD直接用 Deployment 跑起来把模型地址和 API Key 通过环境变量注入把健康检查做好这就已经比裸跑脚本强十倍。等 Agent 数量多了、形态复杂了再往抽象层走。2.2 声明式 Agent 编排用 CRD 表达“想要什么样的 Agent”当你要同时管理一大批 Agent比如客服 Agent、数据分析 Agent、代码审查 Agent每个 Agent 有不同的系统提示、模型配置、工具列表和并发数最优雅的做法是引入 Kubernetes 的“自定义资源”CRD——把 Agent 抽象成一种新的资源类型。我自己在实验环境里会定义类似这样的资源apiVersion: agent.example.com/v1 kind: AgentSet metadata: name: customer-support-agent spec: replicas: 3 model: provider: openai-compatible name: gpt-4o-mini endpoint: http://model-gateway.default.svc:8000/v1 profile: customer_support tools: - order.lookup - refund.apply - ticket.create maxRounds: 12 memory: enabled: true size: 1Gi这份 YAML 描述的是“我期望有 3 个副本的客服 Agent用某个模型带上某些工具最多执行 12 轮推理开启 1Gi 的本地记忆”。接下来你需要一个叫 Operator 的控制器它监听这个 CRD一旦发现 AgentSet 被创建就自动生成对应的 Deployment、Service、Secret 等基础资源如果副本数从 3 改成 5它会自动扩容。这个模式的好处是把“Agent 配置”和“底层实现”解耦了。团队里谁部署 Agent不用再学一整套 K8s 细节只需要填一份 AgentSet YAML。运维视角也能统一看资源列表就能知道现在有哪些 Agent、各占多少资源。社区里已经有一些类似实现的 Agent Operator 项目思路基本都是这个方向。2.3 工具、记忆与权限把 K8s 抽象映射到 Agent 世界Agent 的能力来源是工具和记忆这两样东西在 Kubernetes 里也有非常清晰的对应物工具调用Agent 要调用的外部 API可以建模为 Service。K8s 内部通过 Service DNS 名称访问工具外部工具则通过 Ingress / Gateway 暴露。用 NetworkPolicy 控制“哪个 Agent 能调哪个工具”比在代码里写一堆 if 判断要可靠得多。记忆和会话状态长期记忆适合放对象存储或向量数据库短期会话状态可以借助 Redis。K8s 侧为这些中间件准备 PVC持久卷或直接连接外部托管服务。不要让对话上下文只留在 Pod 内存里Pod 一重启全没了。密钥和配置模型 API Key 放到 Secret 里系统提示词和工具配置放到 ConfigMap 里。更新提示词不需要重新构建镜像改一下 ConfigMap滚动重启 Pod 就行。把 Agent 世界和 Kubernetes 世界的概念对齐是我认为最重要的一步因为一旦对齐你就能直接借用 K8s 的成熟能力。我整理了一张对应表平时给人讲就靠它Kubernetes 概念Agent 世界里的对应Pod / DeploymentAgent 实例 / 执行单元Job / CronJob一次性数据处理 / 定时任务StatefulSet有稳定身份和存储的 AgentService / Ingress工具注册中心 / 对外 APIConfigMap / Secret系统提示词 / 模型凭证CRD OperatorAgent 定义 / 编排控制逻辑HPA / KEDA按请求量或队列长度扩缩NetworkPolicy工具调用白名单ResourceQuotaAgent 费用与资源上限这张表可能就是你真正要的“Kubernetes 详解”——它不是讲某个命令而是告诉你抽象之间如何映射。3. 从 Google 的动作看 Agent 编排的“标准件”思路3.1 可移植编排避免为每个 Agent 重造调度轮子Google 生态在这一轮最值得关注的动作不是因为 Google 独家发明了什么而是它一直在推动“开放标准 云原生底座”的组合。Kubernetes 本身就是这种思路的成功案例不管底层是哪个云厂商用户面对的都是一套不变的标准 API。Agent 生态太年轻、太分裂如果每家都搞自己的私有编排协议行业只会碎片化得更严重。把同样的逻辑搬到 Agent 上就是大家说的“把 Kubernetes 搬来管 Agent”的核心主张Agent 的编排层应该建立在通用的基础设施上而不是绑定在某一个厂商的 Agent 框架里。你可以在本地用 kind 起一个 K8s 集群做开发推到云上直接跑生产中间不需要重写部署方式这对小团队来说非常友好。3.2 算力、模型、数据一起调度才是 Agent 的大后台Agent 跑起来以后真正的资源瓶颈往往不在 Agent 程序本身而在背后的模型服务和数据访问。一个 Agent 可能在推理时短暂调用 GPU也可能滑动扩展去查向量库这些差异化需求在 K8s 里都能表达GPU 由 Device Plugin 暴露给调度器模型网关作为普通 Service 接入向量数据库用 StatefulSet 跑数据访问通过 PVC 挂载。Kubernetes 的调度器天然把算力、模型、数据看成“可调度资源”这一点和 Agent 的复杂需求正好匹配。Google 在这套体系里做了不少基础工作比如 Kubernetes 上的批量调度工具 Queue 管理、面向 AI 工作负载的队列调度以及把一批 AI 基础设施能力往 CNCF 生态里推。这些动作放在一起输出的其实是一句话你想跑好 Agent不一定需要猎奇的新系统把标准云原生底座用好就够了。3.3 开放协议补齐“Agent 之间怎么说话”的短板现在行业里有两个协议特别值得关注一个是 MCP模型上下文协议解决 Agent 怎么调用工具另一个是 A2AAgent2Agent2025 年已经开放这类方向解决 Agent 之间怎么在开放协议下互相协作。这两个协议的出现让 Agent 编排的“最后一公里”开始标准化了。对 K8s 来说协议标准化意味着不管 Agent 内部用什么框架对外都能以标准方式暴露工具和能力。以后你在集群里跑十个不同厂商的 Agent它们之间不需要知道彼此的实现细节只通过协议互调。这就像微服务时代大家都走 HTTP/REST 一样协议一统一基础设施才能真正做深。Kubernetes 在其中扮演的是“运输层”角色它不关心 Agent 说什么语言只管把消息可靠地从 A 运到 B把出错的实例及时重启把过载的流量弹性替补上去。4. 实操把最小 Agent 编排在本地跑起来4.1 环境准备先有一个能用的 K8s 集群纸上谈兵没意思我直接给你一套可以复现的最小操作路径。第一步准备一个本地 K8s 环境。我用的是 kind它对本机部署比较友好一条命令就能起集群kind create cluster如果你更习惯 minikube也可以本质区别不大。接下来检查一下 kubectl 是否正常kubectl cluster-info kubectl get nodes看到节点 Ready就说明本地集群已经就绪。接下来要准备一个模型服务的访问地址。生产场景里通常是一个内部网关开发阶段可以直接用一个本地模型服务或者一个 OpenAI 兼容的 API 地址。4.2 写一个极简 Agent Server然后部署成 Deployment为了演示我写一个非常小的 Agent 服务它本身不实现复杂的规划逻辑只负责接收消息、调用模型、返回结果。这个服务可以视为 Agent 的“最小容器化形态”。from fastapi import FastAPI, Request from openai import OpenAI app FastAPI() client OpenAI( base_urlhttp://model-gateway.default.svc:8000/v1, api_keyEMPTY, ) app.post(/agent/chat) async def chat(req: Request): body await req.json() messages body.get(messages, []) resp client.chat.completions.create( modelqwen2.5:7b, messagesmessages, ) return {reply: resp.choices[0].message.content} app.get(/healthz) async def healthz(): return {status: ok}这个服务监听 8080 端口提供/agent/chat和/healthz两个接口。健康检查接口很重要K8s 探针会定期探测它一旦服务失联就会重启。然后把它打成镜像推到本地镜像仓库。接着写 DeploymentapiVersion: apps/v1 kind: Deployment metadata: name: support-agent namespace: agents spec: replicas: 1 selector: matchLabels: app: support-agent template: metadata: labels: app: support-agent spec: containers: - name: agent image: registry.example.com/support-agent:1.0.0 ports: - containerPort: 8080 env: - name: OPENAI_BASE_URL value: http://model-gateway:8000/v1 - name: OPENAI_API_KEY valueFrom: secretKeyRef: name: llm-credentials key: api-key resources: requests: cpu: 200m memory: 512Mi limits: cpu: 2 memory: 2Gi readinessProbe: httpGet: path: /healthz port: 8080这里有两个细节我想单独强调一是资源规格一定要写别嫌麻烦。Agent 推理过程中内存波动很大不设 Request / Limit 的话一小撮 Agent 就能打满整台节点。二是 API Key 必须走 Secret不要直接写在 YAML 里任何人只要kubectl get能看到明文等于把模型预算交出去了。创建一个 Secretkubectl create secret generic llm-credentials \ --from-literalapi-keyYOUR_SECRET_KEY \ -n agents然后部署kubectl apply -f deployment.yaml kubectl get pods -n agents看到 Pod Running 并且 Ready说明 Agent 服务已经起来了。4.3 用 CronJob 跑定时 Agent最实用的生产场景我实际接触的 Agent 项目里有很大比例不是传统意义上的“对话机器人”而是定时任务型 Agent每天早上拉取销售数据、生成一段分析摘要、推送报告。这非常适合用 CronJob 实现。apiVersion: batch/v1 kind: CronJob metadata: name: daily-report-agent spec: schedule: 0 9 * * * jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: reporter image: registry.example.com/daily-report-agent:1.0.0CronJob 的好处是天然具备“跑完就退出”的语义。它每次调度都会创建一个 JobJob 里的 Pod 跑完任务就进入 Completed 状态不会一直占着资源。配合restartPolicy: OnFailure任务失败时会自动重试。这是裸写 cron 脚本完全比不上的体验——因为重试、日志保留、并发策略全都由 K8s 接管了。4.4 进阶路径什么时候该上 CRD 和 Operator当你从 1 个 Agent 变成 10 个 Agent且每个 Agent 的模型配置、工具列表、提示词版本各不相同纯手写 Deployment 就变得非常痛苦。这时候就该考虑用 CRD 把 Agent 抽象出来。但我要泼一盆冷水经验不足的团队一上来就写 Operator很容易把大量时间耗在控制器里Agent 本身的业务反而没进展。我的建议是分三步走第一步全部用 Deployment Service CronJob把运行问题暴露出来第二步把公共配置抽到 ConfigMap把凭证抽到 Secret部署方式先稳定住第三步等你真的需要“一个按钮创建多类型 Agent”的时候再引入 CRD 和 Operator。循序渐进比一步到位稳妥得多。5. 常见问题与排查心得5.1 Agent 实例重启对话上下文全没了这是最典型的坑。Agent 有上下文你把它做成无状态 Deployment只要 Pod 一重启内存里的对话历史就没了。用户会明显感觉到“刚才还聊得好好的突然失忆了”。解决办法有两条路一是用外部存储把会话状态写到 Redis 或数据库里每次请求都从外部加载上下文二是用 StatefulSet 给每个 Pod 一个稳定的身份和存储卷。我的建议是优先选外部存储因为分布式环境里会话数据本来就不该只躺在某一台机器上。如果只是单机实验StatefulSet 也够用。5.2 Agent 调工具时挂起Pod 卡好久不结束Agent 调工具是最容易出问题的环节第三方 API 超时、工具返回异常数据、Agent 陷入循环反复调用这些都会导致 Pod 长时间不结束。你可以在代码层给工具调用设置超时但更稳妥的是在 K8s 层加防护设置 Pod 的activeDeadlineSeconds给 Job 设置backoffLimit给 Deployment 的探针设置更短的周期和超时时间。我遇到过最离谱的情况是 Agent 在循环里“看似活着”健康检查一直通过实际上就是在空转浪费 token。后来我在工具调用层加了轮次上限和单次耗时统计才把这个成本漏洞堵上。这个问题靠 K8s 不太够必须业务层和基础设施层一起兜。5.3 多个 Agent 同时上线集群资源被打满Agent 不像普通接口那么稳定模型推理高峰和低谷差异很大。多个 Agent 同时跑起来CPU 和内存很容易超预算。这种事情防不胜防但可以用 ResourceQuota 给每个 Agent 的 Namespace 设置硬上限。apiVersion: v1 kind: ResourceQuota metadata: name: agent-quota namespace: agents spec: hard: requests.cpu: 4 requests.memory: 8Gi limits.cpu: 8 limits.memory: 16Gi这样即使某个 Agent 失控最多影响它自己所在的 Namespace不会拖垮整个集群。我会建议再配合模型网关的限流双保险。至于弹性伸缩CPU 指标对 Agent 不是特别敏感更好的做法是用 KEDA 按队列长度或者自定义指标扩缩。5.4 Agent 日志看不懂出问题要翻半天Agent 的日志量很大里面有 planning、tool call、model response混在一起基本没法排查。解决思路是“结构化日志 链路追踪”。让 Agent 每轮执行都输出标准 JSON 日志包含 request id、trace id、tool 名称、耗时、token 数。接入 OpenTelemetry 以后一个 trace 能从用户请求追到模型调用、工具调用和最终回复。还有一个容易被忽略的点K8s 本身的事件也会提供重要线索。kubectl describe pod可以看到 OOMKilled、镜像拉取失败、探针失败等事件kubectl logs --previous可以看到上一次崩溃的日志。排查 Agent 问题不要只盯业务日志基础设施日志和事件同样关键。5.5 Agent 调用工具的权限边界Agent 在生产环境里调用内部系统权限必须收敛到最小。K8s 的 NetworkPolicy 可以限制 Agent Pod 只访问特定的工具 ServiceServiceAccount 可以让 Agent 带着特定身份访问集群内资源Secret 配合 RBAC 可以防止模型凭证被无关人员读走。问题现象解决思路会话丢失Pod 重启后用户上下文没了外部 Redis / DB 存储会话状态工具挂起Agent 长时间不返回结果业务层设轮次上限K8s 设 activeDeadlineSeconds资源打满一个 Agent 拖垮节点ResourceQuota 模型网关限流日志难排查全链路日志混杂JSON 结构化日志 OpenTelemetry权限过大Agent 能访问无关服务NetworkPolicy 最小 ServiceAccount这张表我建议直接存下来上线前对照一遍能避开大部分真实的坑。6. 最后想说的几点实操体会我自己落地这个思路的顺序和大家预想的可能不太一样不是先写 Operator而是先压掉认知门槛。第一个 Agent 直接上 Deployment把健康检查、资源限制、日志采集做好第二个 Agent 用 CronJob 跑定时任务第三个开始做会话状态外部化。等到某天你发现“部署新的 Agent 只改配置不用改代码”时你才真正体会到“把 Kubernetes 搬来管 Agent”是什么意思。有一个小技巧我觉得非常值得分享把 Agent 的系统提示词、工具 schema 全部放到 ConfigMap而不是写死在代码里。这样你改提示词、调工具参数只需要kubectl apply一个新 ConfigMap再滚动重启 Pod几十个 Agent 实例能同时切换新配置。这个体验用裸脚本跑 Agent 是完全做不到的。“Google 把 Kubernetes 搬来管 Agent”这个说法还会演化但从工程角度看方向已经很清楚Agent 会变成 K8s 上一类普通的工作负载有命名空间、有配额、有探针、有审计日志。你现在越早把 Agent 当“正经服务”来治理后面规模上来的时候就越从容。
返回列表