说实话Google 最近这一波操作挺值得玩味的。他们把 Kubernetes 这套容器编排体系直接搬过来当成 AI Agent 的“管理底座”来用。乍一听像个噱头但如果你真正上手折腾过 Agent 的生产部署就会发现这套逻辑其实非常顺——Agent 本质上就是一个有状态、有工具调用能力、需要被调度被观测的“特殊服务”而 Kubernetes 恰好就是那个被过去十几年互联网业务验证过的、最擅长管这类服务的系统。这篇文章我就顺着这个思路拆一拆 Google 为什么选 Kubernetes、Kubernetes 和 Agent 是怎么一一对应的、以及如果你想自己动手把 Agent 放到 K8s 里跑具体该怎么落地、会遇到哪些坑。无论你是刚开始接触 Agent 开发还是已经在生产环境里被 Agent 的状态管理搞到头秃这篇应该都能给你一些可以直接抄走的思路。1. Google 把 Kubernetes 搬来管 Agent背后的核心思路是什么1.1 不是“K8s 管 Agent”而是“用运维服务的方式运维 Agent”很多人听到“Google 把 Kubernetes 搬来管 Agent”的第一反应是难道要写一堆 CRD 去描述 Agent 的逻辑其实不是。Google 真正在做的事情是把 Kubernetes 对容器服务的整套运维理念——声明式期望状态、自动调度、弹性扩缩、自愈恢复、健康检查、多租户隔离——完整地迁移到 Agent 的生命周期管理上来。这个思路的本质是Agent 不再被当成一个“调用一下就跑的函数”而是被当成一个长期存活、持续提供服务、需要稳定运行的生产服务。你想想一个 Agent 要对外提供对话能力要处理多轮上下文要动态调用工具要按请求量伸缩副本这些需求和传统后端服务几乎没有本质区别。既然没区别那直接用 K8s 这套经过大规模考验的体系来兜底是成本最低、风险最小的选择。Google 在 Cloud Next 2025 上发布的基于 GKE 的 Agent Engine就是把这种思路产品化开发者把一个 Agent 打包成容器镜像剩下的——部署、伸缩、证书、外部流量接入、可观测性——全部交给 GKE。说白了Agent 开发者不用再自己造一套“Agent 运维平台”Kubernetes 就是那个现成的平台。1.2 为什么是 Kubernetes而不是自研一套 Agent 编排系统这里有一个很现实的问题Agent 的运维需求和传统服务的运维需求高度重叠而 Kubernetes 生态在过去十几年里已经把“如何在分布式环境里稳定地跑一组服务”这件事啃得透透的。与其从零去写一个调度器、一套自愈机制、一套弹性伸缩策略不如直接在既有生态上做适配和扩展。而且 Kubernetes 生态的可扩展性足够强。如果你觉得默认的 Deployment 描述不了 Agent 的特殊状态可以写自定义 CRD 或 Operator 去扩展如果你觉得 HPA 的指标不够细可以接 Prometheus 自定义 metrics如果你觉得网络策略不够严可以用 NetworkPolicy 加 Istio 做服务网格。所有你能想到的“Agent 特有需求”K8s 的机制都留着口子让你自己填。还有一个很关键的考量是没人愿意被绑定。K8s 是开源中立的Google 虽然推了 Agent Engine但你完全可以自己在任意一个 K8s 集群里复现同样的架构。对比一下那些闭源的 Agent 托管平台K8s 这套方案的迁移成本、生态成熟度、人才储备都明显更有优势。1.3 这套组合能解决 Agent 生产落地的哪些痛点先说资源利用率。Agent 的推理负载波动极大——白天上班时间对话请求密集晚上可能几乎空闲。如果没有弹性伸缩你就只能按峰值留资源成本几乎要翻倍。K8s 的 HPAHorizontal Pod Autoscaler天然就是干这个的按 QPS、CPU、GPU 利用率自动扩缩容省下的推理成本是实打实的。再说稳定性。Agent 跑长了必然会出现 OOM、死锁、模型推理卡死这类问题。过去你只能手动重启现在 K8s 的存活探针和重启策略可以直接帮你完成检测和恢复。如果一个副本连续几次健康检查失败K8s 会杀掉它、重新创建一个新副本这个过程对用户来说几乎是透明的。还有多租户和资源隔离。你在同一个集群里跑多个 Agent比如一个客服 Agent、一个数据分析 Agent如果它们共享同一批 GPU 资源怎么保证某个 Agent 的突发流量不会把其他人的资源吃光K8s 的 ResourceQuota 和 LimitRange 就是干这个的每个 Agent 分配好上限谁也不能抢谁的。2. Kubernetes 概念和 Agent 场景的核心映射2.1 Pod 就是 Agent 实例Deployment 就是 Agent 的“期望状态”在容器世界里Pod 是最小调度单位。放到 Agent 场景里一个 Pod 就是一个 Agent 实例——里面跑着 Agent 主进程可能还有几个 sidecar 容器比如日志采集、指标上报、模型代理。旁边挂着的 ConfigMap 可以往里注入 System Prompt 和工具配置Secret 可以注入 API Key 和数据库密码。Deployment 的价值在于声明“我要多少个 Agent 实例长期存在”。你不需要关心某个实例挂了怎么处理Deployment 的控制器会持续对比“当前副本数”和“期望副本数”发现少了就自动补。这个机制对应到 Agent 运维上就是天然的故障自愈一个 Agent 实例因为未知原因崩溃了Deployment 马上创建一个新实例顶上会话状态靠外部存储兜底用户不会感觉到服务中断。你在给 Agent 配置副本数的时候要特别注意一点不是越多越好。Agent 实例是会占用显存和推理资源的如果副本数超过 GPU 显存容量新实例根本调度不起来。我一般建议按单实例显存占用和总显存容量来倒推副本数留 20% 余量给突发。2.2 Service 和 Ingress把 Agent 的能力“发布”出去Agent 要对外提供服务必须有一个稳定的访问入口。Pod 的 IP 是会漂移的直接暴露 Pod IP 等于给自己埋雷。Service 在这中间做了一个稳定抽象不管后面 Agent 实例怎么重启、怎么扩缩Service 的虚拟 IP 和 DNS 名称永远不变。这里面有两个细节值得展开。一是 Service 的 selector 要精准。如果你有多个不同类型的 Agent 在同一个命名空间里label 一旦写宽了流量就可能被转发到错误的 Agent 实例上。我习惯把 agent-type、agent-version、environment 三组 label 写全宁可多几个标签也不要模棱两可。二是外部流量入口。Agent 服务通常要暴露给外部调用方比如 IM 应用、Web 前端这时候 Ingress 或者 Gateway API 就派上用场了。你可以为每个 Agent 配一条独立的路由规则路径前缀对应不同的 Agent 服务。TLS 证书的自动轮换也交给 Ingress Controller 做省得自己手动处理证书过期这种低级事故。2.3 探针怎么判断一个 Agent 是“活着”还是“能用”启动探针Startup Probe解决的是“这个 Agent 什么时候算跑起来了”。Agent 的启动过程比普通 Web 服务要慢——它要加载模型、初始化记忆库连接、预热工具调用链。如果你用默认的 readiness 探针去探测可能在 Agent 还没准备好时就给它打流量导致大量 5xx 错误。所以我习惯给 Agent 单独配一个 startupProbe给足启动时间比如 60 秒甚至 90 秒探测通过之后再启用 readiness 检查。就绪探针Readiness Probe解决的是“这个 Agent 现在能不能接新请求”。注意存活探针和就绪探针要区分开。存活探针失败K8s 会杀掉并重建 Pod就绪探针失败K8s 只是把 Pod 从 Service 的端点列表里摘掉并不重启。Agent 的某个依赖比如向量数据库出现暂时性抖动你肯定不想每次都重启 Agent这时候就绪探针能帮你优雅地隔离问题实例。我在生产环境里给 Agent 的 readiness 探针通常不会直接打 Agent 的对话接口——一旦对话接口本身有问题探针会发现不了。更稳妥的做法是单独暴露一个轻量的 /healthz 端点内部去检查和核心依赖模型服务、记忆库、工具网关的连接状态把健康判断逻辑自己掌控。2.4 HPA 自动扩缩按什么指标来扩 Agent 副本数HPA 支持按 CPU、内存这些资源指标扩缩也支持按 Prometheus 里的自定义指标扩缩。对 Agent 来说单纯的 CPU 使用率并不完全准确——Agent 的主要负载在推理和内存访问上CPU 指标往往表现滞后。我个人更推荐按“对话中的活跃会话数”或者“每秒推理请求数”来自定义扩缩。这个指标的语义更贴近 Agent 的真实负载活跃会话多了就加副本少了就缩。如果暂时不想接 Prometheus那退一步按内存使用率来配 HPA 也是可行的因为 Agent 的内存占用和并发会话量的相关性非常高。这个方案胜在简单不需要额外组件。HPA 的冷却机制值得单独提醒扩缩太频繁会导致副本状态颠簸反而拉低稳定性。我给 Agent 设置的基本上是 scale-down 的稳定窗口长于 scale-up 的稳定窗口——比如扩容 60 秒内不重复判断缩容 300 秒内不重复判断。这样即使负载出现短暂毛刺也不会引发副本数反复横跳。3. 实操把一个 Agent 服务完整部署到 Kubernetes3.1 先设计 Agent 的容器镜像在写 yaml 之前先把 Agent 的镜像设计好。一个标准的生产级 Agent 镜像里主进程就是 Agent 服务本体它会加载配置、连接外部依赖模型 API、向量库、记忆库、工具服务然后对外暴露 HTTP/gRPC 接口。我建议把 model 配置、system prompt、工具列表这些环境相关的内容全部放到 ConfigMap 里不要在镜像里写死。这样同一份镜像可以在测试、预发、生产环境里用不同的配置跑不需要频繁重新打包。常见做法是这样FROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY src/ ./src/ EXPOSE 8080 CMD [python, -m, src.main]镜像保持精简有几个好处构建时间短、安全漏洞面小、镜像仓库存储成本低。不要图省事把整个模型文件也打进去模型体积太大镜像拉取时间会拖慢弹性扩缩的速度。模型单独放对象存储或者模型服务里加载Agent 镜像只留推理 client。3.2 Deployment 配置关键字段逐个拆解这里给一份我实际用过的 Agent Deployment yaml省去敏感信息核心结构可以直接抄apiVersion: apps/v1 kind: Deployment metadata: name: support-agent namespace: agent-prod labels: agent-type: customer-service environment: production spec: replicas: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0 selector: matchLabels: app: support-agent template: metadata: labels: app: support-agent agent-type: customer-service spec: containers: - name: agent image: registry.example.com/support-agent:v1.4.2 ports: - containerPort: 8080 name: http envFrom: - configMapRef: name: support-agent-config - secretRef: name: agent-secrets resources: requests: memory: 1Gi cpu: 500m limits: memory: 2Gi cpu: 2 startupProbe: httpGet: path: /healthz port: 8080 periodSeconds: 5 failureThreshold: 20 readinessProbe: httpGet: path: /readyz port: 8080 periodSeconds: 10 failureThreshold: 3 livenessProbe: httpGet: path: /livez port: 8080 periodSeconds: 20 failureThreshold: 3 lifecycle: preStop: exec: command: [sh, -c, sleep 10]逐个解释几个关键点。replicas 设 3是因为三个副本可以保证滚动更新时至少有两个可用副本不会出现服务空窗。升级策略用的是 RollingUpdatemaxUnavailable 设为 0——这意味着在滚动升级期间永远不会出现没有可用 Agent 的时刻。maxSurge 为 1 表示可以先多创建一个新副本再把旧副本摘掉保证升级期间容量不降。resources.limits里的内存上限要特别小心。Agent 的实际内存占用受会话上下文长度影响很大如果 limits 卡得太紧一个长对话请求进来就可能触发 OOMKilled。我在生产环境里给 limits 留了大约两倍余量宁可在资源统计上多付一点虚拟成本也不愿意在高峰期被内核 OOM 杀掉。lifecycle.preStop里的 10 秒 sleep 很多人会忽略但对 Agent 来说很关键。K8s 在终止 Pod 时会先发 SIGTERM然后等待 grace period。如果你的 Agent 正在处理一个异步工具调用直接被 SIGTERM 杀掉会丢掉用户请求。sleep 10 是为了给 K8s 从 Service 端点列表摘除该 Pod 留出时间同时让 Agent 进程把当前请求处理完再退出。3.3 Service 和 HPA 配置Service 这部分相对标准需要注意的就是端口命名和 selector 的对应关系apiVersion: v1 kind: Service metadata: name: support-agent namespace: agent-prod spec: selector: app: support-agent ports: - name: http port: 80 targetPort: httpHPA 这里如果后端已经接了 Prometheus我建议直接按自定义指标走。比如按“每副本的活跃对话数”扩缩apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: support-agent-hpa namespace: agent-prod spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: support-agent minReplicas: 2 maxReplicas: 10 behavior: scaleDown: stabilizationWindowSeconds: 300 scaleUp: stabilizationWindowSeconds: 60 metrics: - type: Pods pods: metric: name: agent_active_sessions target: type: AverageValue averageValue: 20这个配置的语义是当每个 Agent 实例的平均活跃会话数超过 20就触发扩容低于 20缩容。minReplicas 设 2 是保底避免深夜流量低谷时缩到只剩一个副本——万一那个副本恰好被调度到故障节点上整个服务就不可用了。maxReplicas 设 10 是成本上限防止某个异常流量打进来时无限扩容。还有一个我在实战中发现的问题HPA 配合 GPU 资源时指标不能只看显存。HPA 默认的 GPU 指标采集会导致扩容滞后因为显存利用率上去之后真正能调度成功的 GPU 节点可能已经不够了。所以如果 Agent 用 GPU 推理我建议把 HPA 的指标改成“排队中的请求数”——因为负载上涨的早期信号是请求排队而不是 GPU 利用率。这个信号提前量能帮你更早扩容。3.4 会话状态和记忆怎么在 K8s 里持久化说到 Agent绕不开记忆和会话状态。我在引入 K8s 之后坚决把 Agent 的会话状态放在外部存储里而不是本地磁盘或内存。原因很简单K8s 里的 Pod 随时可能被销毁重建如果状态存在 Pod 本地Pod 一死用户在对话里交代的上下文全没了。会话状态的存储选择我在生产环境里用的是 Redis Cluster理由是两个一是延迟低二是 TTL 机制天然适合会话过期清理。每个会话的上下文按 session_id 存成一个哈希结构TTL 设为 30 分钟用户连续对话就刷新 TTL空闲超时就自动清理。这套逻辑在 K8s 里部署 Redis 也简单直接跑一个 StatefulSet 就行。长期记忆比如用户画像、历史偏好我用的是向量数据库。K8s 里跑 Milvus 或者 Qdrant 都很成熟直接用 Helm Chart 装。要注意给向量数据库单独配持久化卷和存储类不要把数据存在容器本地否则数据库实例一重启全库数据就没了。还有一个小技巧Agent 的上下文窗口大小是有限的你在应用层最好做上下文裁剪。把超过窗口上限的旧消息压缩成摘要只保留摘要加最近几轮完整对话这个摘要也可以顺带存到 Redis。这套设计让 Agent 能在有限资源里处理长会话也避免了请求体过大引发的各种超时问题。4. Agent 安全、工具调用与多 Agent 编排的 K8s 落地4.1 用 K8s 原生的安全机制保护 AgentAgent 的安全性是个大话题但在 K8s 部署这个层面有几个基础安全项是必须先做扎实的。密钥管理。Agent 要调用各种外部 API手里握着一堆密钥这些绝不能以明文形式出现在镜像或环境变量里。在生产环境我用的方案是Secret 对象里存真实密钥并开启 etcd 加密Pod 通过 secretRef 注入环境变量如果 K8s 版本允许再配合外部密钥管理服务比如云厂商的 KMS做静态加密。这里还是要强调Secret 的访问权限要尽量收窄用 RBAC 控制谁有权限读某个 Secret别图省事给所有服务同一个权限。网络隔离。多个 Agent 跑在同一个集群里如果一个 Agent 被攻破攻击者很可能通过内网横向移动访问其他 Agent 的数据。NetworkPolicy 是阻断横移的关键手段默认拒绝所有非必要流量只放行被明确允许的路径。我习惯给每一个 Agent 都配一套 NetworkPolicy只允许从自己的 Ingress Controller 过来的流量只允许访问自己依赖的 Redis、向量库、模型服务的 IP 或标签。审计与观测。Agent 的工具调用行为应该是可追踪的。我建议在 Agent 框架层做一次详细的请求日志谁在什么时间调了哪个工具、传入参数是什么、返回结果是什么。日志打到标准输出K8s 里的 filebeat/fluentbit 采集后送进 Elasticsearch 或 Loki方便事后排查和安全审计。这套链路搭起来之后你就能回答“Agent 为什么做了这个决定”这类问题——这在排查线上事故时非常有用。4.2 工具调用和 MCP 在 K8s 里怎么接入Agent 的工具调用是它能力的核心。在 K8s 环境下工具调用有两种常见接入方式。第一种是“标准 HTTP 工具网关”所有外部工具统一走一个工具网关服务Agent 通过 HTTP 协议调用网关负责鉴权、限流、转发和日志记录。这个方案的优势是统一治理所有工具的调用情况都集中可见。第二种方式是近段时间很火的 Model Context ProtocolMCP。MCP 在 K8s 里的部署思路是把各个 MCP Server 也跑成集群里的独立服务Agent 通过 MCP 客户端协议连接这些 Server。我在实验环境里试过把数据库查询、搜索引擎、内部知识库都封装成 MCP Server 跑在 K8s 里Agent 主服务不再管各个工具的具体实现只通过 MCP 协议去发现和调用。要注意的是工具网关和 MCP Server 都是 Agent 的关键依赖它们的可用性直接影响 Agent 的主流程。我在 K8s 里会给这些依赖服务单独配 HPA并且在 Agent 的 readiness 探针里增加对工具网关的连通性检查。当工具网关挂掉时Agent 会立刻进入“不接收新请求”的状态而不是带着一个坏依赖硬扛这样下游调用方就不会受到二次故障的影响。4.3 多 Agent 协作架构怎么用 K8s 编排当你的业务里有多个 Agent 协作时比如一个主控 Agent 调度多个专家 AgentK8s 的架构优势会更加明显。每个 Agent 都是独立 Deployment各自有独立环境变量、独立配置、独立扩缩容策略而 Agent 之间的调用走 Service DNS 名称。主控 Agent 的调度逻辑里对专家 Agent 的调用全部走 Service 地址比如http://data-agent.agent-prod.svc.cluster.local:80/run。这样两个团队可以分别迭代各自的 Agent——数据团队只动>
