部署与安全
你把 Agent SDK 写好了,本地跑得好好的。但生产环境不是你的开发机——Agent 可以执行任意命令、访问文件、调用外部 API。如果没有适当的隔离和防护,一个处理恶意内容的 Agent 可能泄露用户数据、消耗系统资源、甚至被利用来攻击其他服务。如何让 Agent 在生产环境安全高效地运行,是这篇文章要解决的核心问题。
本文你会学到:
- Agent SDK 的架构特点(长运行进程)对部署的影响
- 四种部署模式及各自的适用场景
- 沙箱提供商的选择与对比
- 安全威胁模型和纵深防御策略
- 隔离技术(Sandbox、Docker、gVisor、Firecracker)的对比
- 凭证管理和文件系统配置的最佳实践
理解 SDK 架构对部署的影响¶
Agent SDK 和传统的无状态 LLM API 有本质区别。传统 API 是"请求-响应"模式,每次调用互不相关。而 Agent SDK 作为**长运行进程**运行,它会在持久化的 shell 环境中执行命令、在工作目录中管理文件、并携带先前交互的上下文来处理工具调用。
这意味着你不能像部署普通 Web API 那样简单地水平扩容——每个 Agent 实例是有状态的,需要持久化的工作目录和 shell 环境。
系统要求¶
每个 SDK 实例需要:
| 项目 | 要求 |
|---|---|
| 运行时 | Python 3.10+(Python SDK)或 Node.js 18+(TypeScript SDK) |
| CLI 二进制 | SDK 包自带,无需单独安装 Claude Code |
| 资源(推荐) | 1 GiB RAM、5 GiB 磁盘、1 CPU(根据任务调整) |
| 网络 | 出站 HTTPS 到 api.anthropic.com,可选访问 MCP 服务器或外部工具 |
沙箱提供商选项¶
几个云服务商专门为 AI 代码执行提供了安全容器环境:
| 提供商 | 特点 |
|---|---|
| Modal Sandbox | Serverless,按需启动,适合临时任务 |
| Cloudflare Sandboxes | 边缘计算,低延迟 |
| E2B | 专为 AI Agent 设计的沙箱环境 |
| Fly Machines | 容器化,支持持久化实例 |
| Vercel Sandbox | 与 Vercel 生态集成 |
| Daytona | 开发环境管理 |
对于自托管场景,可以使用 Docker、gVisor 或 Firecracker 进行隔离(见下文「隔离技术对比」)。
四种部署模式¶
根据你的应用场景,选择合适的部署模式:
临时会话¶
为每个用户任务创建一个新容器,任务完成后销毁。
适合一次性任务,用户可能在任务进行中与 AI 交互,但完成后容器即销毁:
- Bug 调查和修复
- 发票处理和数据提取
- 文档翻译
- 图像/视频处理
长运行会话¶
为长期任务维护持久化容器实例。通常在容器内按需运行**多个** Agent 进程。
适合主动型 Agent(无用户输入也能自主行动)或高频交互场景:
- 邮件代理:自动监控、分类、响应
- 网站构建器:每个用户独立容器,支持实时编辑
- 高频聊天机器人:处理 Slack 等平台的连续消息流
混合会话¶
临时容器 + 状态补充(来自数据库或 SDK 的会话恢复功能)。
适合间歇性交互场景——启动工作、完成后关闭,但可以恢复继续:
- 个人项目管理器
- 深度研究任务(跨多小时)
- 客户支持代理(跨多轮交互的工单)
单容器多进程¶
在一个全局容器中运行多个 Agent SDK 进程。
适合 Agent 之间需要紧密协作的场景,但需要防止相互覆盖,通常是**最不推荐**的模式:
- 多 Agent 模拟(如视频游戏中的 NPC)
安全威胁模型¶
Agent 的行为可能被它处理的内容所影响——仓库中的 README、网页内容、用户输入中的恶意指令,这就是所谓的 Prompt Injection。例如,如果某个项目的 README 包含异常指令,Agent 可能会将这些指令纳入其操作中,以操作者未预期的方式行动。
Claude 模型本身设计为能够抵御此类攻击,但纵深防御仍然是良好的实践。即使 Agent 被诱导执行恶意操作,网络控制也可以完全阻断对外通信。
内置安全功能¶
Claude Code 自带几项安全特性:
- 权限系统:每个工具和 bash 命令都可以配置为 allow、block 或需要用户批准。支持 glob 模式匹配规则(如"允许所有 npm 命令"或"禁止任何带 sudo 的命令")
- 命令解析:执行 bash 命令前,Claude Code 会将其解析为 AST 并与权限规则匹配。无法解析的命令或不在 allow 规则中的命令需要显式批准。
eval等危险构造始终需要批准 - 网页搜索摘要:搜索结果以摘要形式传递而非原始内容,降低恶意网页内容注入的风险
- Sandbox 模式:bash 命令可以在受限制的沙箱环境中运行
安全原则¶
对于需要超越默认安全配置的部署,以下三个原则指导所有可用选项。
最小权限¶
限制 Agent 只拥有完成特定任务所需的最小能力:
| 资源 | 限制方式 |
|---|---|
| 文件系统 | 只挂载必要的目录,优先只读 |
| 网络 | 通过代理限制到特定端点 |
| 凭证 | 通过代理注入,不直接暴露 |
| 系统能力 | 在容器中 drop Linux capabilities |
安全边界¶
安全边界将不同信任级别的组件隔离开。对于高安全场景,将敏感资源(如凭证)放在 Agent 边界之外。即使 Agent 环境出了问题,边界外的资源仍然受保护。
例如,不给 Agent 直接访问 API key,而是在 Agent 环境外部运行一个代理,由代理在转发请求时注入 key。Agent 可以发 API 请求,但永远看不到凭证本身。
纵深防御¶
对于高安全环境,分层叠加多种控制提供额外保护:
- 容器隔离
- 网络限制
- 文件系统控制
- 代理层请求验证
隔离技术对比¶
不同隔离技术在安全性、性能和运维复杂度之间有不同的权衡:
| 技术 | 隔离强度 | 性能开销 | 运维复杂度 |
|---|---|---|---|
| Sandbox runtime | 良好(安全默认值) | 非常低 | 低 |
| Docker 容器 | 取决于配置 | 低 | 中 |
| gVisor | 优秀(正确配置时) | 中/高 | 中 |
| 虚拟机(Firecracker、QEMU) | 优秀(正确配置时) | 高 | 中/高 |
Sandbox runtime¶
轻量级隔离,无需容器。使用 OS 原语(Linux 上是 bubblewrap,macOS 上是 sandbox-exec)在操作系统层面限制文件系统和网络访问。
配置方式:
| 安装 sandbox-runtime | |
|---|---|
通过 JSON 配置文件指定允许的路径和域名。优点是无需 Docker 配置、容器镜像或网络设置,代理和文件系统限制内置。
安全注意事项:
- 与 VM 不同,沙箱进程共享宿主机内核。内核漏洞理论上可能被利用来逃逸。如果需要内核级隔离,使用 gVisor 或 VM
- 代理基于客户端提供的 hostname 做域名白名单,不终止或检查加密流量。沙箱内的代码理论上可以通过 domain fronting 等技术访问白名单外的主机。如果需要更强的保证,配置 TLS 终止代理
Docker 容器¶
容器通过 Linux namespace 提供隔离。每个容器有独立的文件系统、进程树和网络栈视图,但共享宿主机内核。
一个安全加固的容器配置:
各选项的作用:
| 选项 | 作用 |
|---|---|
--cap-drop ALL |
移除所有 Linux capabilities(如 NET_ADMIN、SYS_ADMIN),防止权限提升 |
--security-opt no-new-privileges |
阻止进程通过 setuid 二进制获取额外权限 |
--security-opt seccomp=... |
限制可用系统调用,Docker 默认阻止约 44 个,自定义 profile 可以阻止更多 |
--read-only |
容器根文件系统不可变,Agent 无法持久化修改 |
--tmpfs /tmp:... |
提供可写的临时目录,容器停止后自动清除 |
--network none |
移除所有网络接口,Agent 只能通过挂载的 Unix socket 通信 |
--memory 2g |
限制内存使用,防止资源耗尽 |
--pids-limit 100 |
限制进程数量,防止 fork 炸弹 |
--user 1000:1000 |
以非 root 用户运行 |
-v ...:/workspace:ro |
代码目录只读挂载,Agent 可以分析但不能修改 |
-v .../proxy.sock:... |
挂载连接到宿主机代理的 Unix socket |
--network none 是关键:容器没有任何网络接口,唯一与外部通信的方式是通过挂载的 Unix socket 连接到宿主机上的代理。代理可以执行域名白名单、注入凭证、记录所有流量。即使 Agent 被 prompt injection 攻陷,也无法将数据泄露到任意服务器。
gVisor¶
标准容器的系统调用直接到达宿主机内核,内核漏洞可能导致容器逃逸。gVisor 在用户空间拦截系统调用,实现自己的兼容层处理大多数系统调用,减少对真实内核的访问。
使用 gVisor 需要安装 runsc 运行时:
| 使用 gVisor 运行容器 | |
|---|---|
性能开销取决于工作负载类型:
| 工作负载 | 开销 |
|---|---|
| CPU 密集计算 | 约 0%(无系统调用拦截) |
| 简单系统调用 | 约 2 倍变慢 |
| 文件 I/O 密集 | 最高可达 10-200 倍变慢(大量 open/close 操作) |
对于多租户环境或处理不可信内容,额外隔离通常值得这个开销。
虚拟机¶
VM 通过 CPU 虚拟化扩展提供硬件级隔离。每个 VM 运行自己的内核,创建强边界。Firecracker 专为轻量级微 VM 设计,启动时间低于 125ms,内存开销不到 5 MiB。
VM 没有外部网络接口,而是通过 vsock(虚拟 socket)通信。所有流量通过 vsock 路由到宿主机上的代理,代理执行白名单并注入凭证后再转发。
凭证管理¶
Agent 经常需要凭证来调用 API、访问仓库或交互云服务。核心挑战是:提供访问能力但不暴露凭证本身。
Proxy 模式¶
推荐方式:在 Agent 安全边界**外部**运行一个代理,由代理将凭证注入出站请求。
这个模式的好处:
- Agent 永远看不到实际凭证
- 代理可以执行允许访问的端点白名单
- 代理可以记录所有请求用于审计
- 凭证集中存储,而非分发到每个 Agent
配置 Agent 使用代理¶
Claude Code 支持两种代理配置方式:
方式一:ANTHROPIC_BASE_URL(简单,仅适用于采样 API 请求)
| 通过 ANTHROPIC_BASE_URL 路由采样请求 | |
|---|---|
Claude Code 和 Agent SDK 会将采样请求发送到你的代理而非直接发送到 Claude API。代理接收明文 HTTP 请求,可以检查和修改(包括注入凭证),然后转发到真实 API。
方式二:HTTP_PROXY / HTTPS_PROXY(系统级,所有流量)
| 通过 HTTP_PROXY 路由所有流量 | |
|---|---|
所有 HTTP 流量都会通过代理。但对于 HTTPS 流量,代理只能创建加密的 CONNECT 隧道,无法查看或修改请求内容(除非配置 TLS 终止)。
其他服务的凭证访问¶
Agent 除了调用 Claude API,通常还需要访问 Git 仓库、数据库和内部 API 等。两种主要方式:
自定义工具:通过 MCP server 或自定义工具提供访问。Agent 调用工具,但实际的认证请求在 Agent 安全边界外执行。优点是无需 TLS 中间人拦截,凭证完全在 Agent 外部。
流量转发:对于 HTTPS 服务,通过 TLS 终止代理解密、检查/修改、再加密转发。需要在 Agent 的信任存储中安装代理的 CA 证书,并配置 HTTP_PROXY/HTTPS_PROXY。注意不是所有程序都尊重这些变量(如 Node.js 的 fetch() 默认忽略,Node 24+ 可设置 NODE_USE_ENV_PROXY=1)。
文件系统配置¶
文件系统控制决定 Agent 可以读写哪些文件。
只读挂载¶
当 Agent 需要分析代码但不能修改时,使用只读挂载:
| 只读挂载代码目录 | |
|---|---|
即使是只读访问,也可能暴露凭证。以下文件在挂载前应排除或清理:
| 文件 | 风险 |
|---|---|
.env、.env.local |
API key、数据库密码等敏感信息 |
~/.git-credentials |
明文 Git 凭证 |
~/.aws/credentials |
AWS 访问密钥 |
~/.config/gcloud/application_default_credentials.json |
Google Cloud 凭证 |
~/.azure/ |
Azure CLI 凭证 |
~/.docker/config.json |
Docker 镜像仓库认证 token |
~/.kube/config |
Kubernetes 集群凭证 |
.npmrc、.pypirc |
包仓库 token |
*-service-account.json |
GCP 服务账号密钥 |
*.pem、*.key |
私钥 |
可写位置¶
如果 Agent 需要写入文件,根据持久化需求选择方案:
- 临时工作区:使用
tmpfs挂载,仅存在于内存中,容器停止后清除 - 需要审查的修改:使用 overlay 文件系统,Agent 的写入存储在独立层,可以检查、应用或丢弃
- 完全持久化:挂载专用 volume,与敏感目录分离
| 临时可写目录配置 | |
|---|---|
常见问题¶
Agent 会话在超时前可以运行多久?
Agent 会话本身不会超时,但建议设置 maxTurns 属性防止 Agent 陷入无限循环。
多久更新一次 CLI? CLI 使用 semver 版本控制,破坏性变更会有版本号变更。关注 release notes 即可。
空闲容器应该保持还是关闭? 取决于你的用户交互模式。不同沙箱提供商支持不同的空闲超时配置,根据用户响应频率调整。容器最低运行成本约每小时 5 美分。
如何与容器内的 Agent 通信? 在容器中暴露端口,应用为外部客户端提供 HTTP/WebSocket 端点,SDK 在容器内部运行。
如何监控容器健康和 Agent 性能? 容器本质上就是服务器,你现有的日志基础设施可以直接使用。结合「监控与成本」中的 OpenTelemetry 集成可以获得更详细的洞察。