AgentCore 混合部署模式
📅 编写日期: 2026-04-18 | ⏱️ 阅读时间: 约 15 分钟
概述
Bedrock AgentCore 是一个强大的托管 Agent 平台,但在企业 环境中通常需要与自托管基础设施相结合。本文档提供了一个结合 AgentCore 的无服务器优势与基于 EKS 的自托管基础设施灵活性的决策框架和经过验证的模式目录,用于设计最优的混合架构。
前置文档
阅读本文档前,请先参考以下文档:
- AWS Native 平台 — AgentCore 7 项服务概述(避免重复)
- 基于 EKS 的开放架构 — 自托管技术栈配置
- AI 平台选择指南 — 托管 vs 开源决策
- SageMaker-EKS 集成 — 混合 VPC/IAM 参考
混合部署动机
单一方案的局限
仅使用 AgentCore 的约束:
- 以 Bedrock GA 100+ 模型为中心(无法托管自定义 Fine-tuned SLM)
- 基于 Token 计费(高频简单任务成本增加)
- 与本地数据源的延迟
- MCP 服务器位于 VPC 内部时需要复杂的 PrivateLink 配置
仅使用 EKS 自托管的约束:
- Agent Runtime 基础设施运维负担(Kagent Pod + Redis State Store)
- 相比无服务器扩展的复杂自动扩缩容(基于 KEDA Queue)
- 缺乏托管内存管理(需自行实现)
- 需自行构建多 Agent 编排框架
混合架构的核心价值
成本损益平衡点计算
| 月推理量 | 仅 AgentCore | 仅 EKS 自托管 | 混合(Cascade) | 最优方案 |
|---|---|---|---|---|
| ~10 万次 | $300-500 | $800-1,200 | $400-700 | 仅 AgentCore |
| ~50 万次 | $1,500-2,000 | $1,200-1,800 | $800-1,200 | 混合起点 |
| ~150 万次 | $4,500-6,000 | $2,500-3,500 | $2,000-2,800 | 必选混合 |
| ~500 万次+ | $15,000+ | $3,500-5,000 | $4,000-6,000 | EKS 为主混合 |
损益平衡点
月推理量超过 50 万次时混合方案具有成本效益。详细计算公式请参考编码工具成本分析。
决策矩阵: Agent 部署位置
通过 8 个核心维度评估来决定 Agent 部署位置。
| 评估维度 | AgentCore | EKS Kagent | 混合 | 判断标准 |
|---|---|---|---|---|
| 推理延迟 | 中等(50-200ms) | 低(10-50ms) | 低 | VPC 内部工具调用 → EKS |
| 成本 | 高频时高 | 高频时低 | 最优 | 简单=EKS, 复杂=AgentCore |
| PII 处理 | VPC 外部(受限) | VPC 内部(有利) | 灵活 | 敏感数据 → EKS MCP |
| 模型定制 | 仅 Bedrock 模型 | 自由(Qwen3, 自定义) | 自由 | Fine-tuned 模型 → EKS |
| 工具链 | REST→MCP 转换 | K8s 原生 | 两者 | 外部 SaaS → AgentCore Gateway |
| 会话长度 | 最大 8 小时 | 无限制 | 无限制 | 长时间对话 → EKS State |
| 审计要求 | CloudTrail 自动 | 需自行实现 | CloudTrail + 自定义 | 合规 → 优先 AgentCore |
| 团队能力 | 无需 Kubernetes | 必须 Kubernetes | 可选 | K8s 新手 → AgentCore 为主 |
决策流程图
数据引力与工具共址模式
什么是数据引力(Data Gravity)?
将计算资源部署在数据密集区域可最小化网络延迟和成本。
典型场景:
- EKS VPC 内部有 Milvus 向量数据库(数 GB~TB 规模)
- AgentCore Runtime 在 VPC 外部(Bedrock 服务账号)
- Agent 为进行 RAG 检索查询 Milvus 时需经 PrivateLink → 延迟增加 + 复杂度增加
反向调用模式
AgentCore Runtime 调用 EKS VPC 内部 MCP 服务器的架构。
PrivateLink 配置
# privatelink-mcp-endpoint.yaml
apiVersion: v1
kind: Service
metadata:
name: mcp-server-nlb
namespace: mcp-system
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
service.beta.kubernetes.io/aws-load-balancer-internal: "true"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"
spec:
type: LoadBalancer
selector:
app: mcp-server
ports:
- port: 443
targetPort: 8080
protocol: TCP
---
# 创建 VPC Endpoint Service(AWS Console 或 Terraform)
# 1. 确认 NLB ARN
# 2. 创建 VPC Endpoint Service(Acceptance required: No)
# 3. 为 AgentCore IAM Role 添加 Endpoint 访问权限
S3+KMS 边界设置
通过 S3 + KMS 加密在 AgentCore 和 EKS 间安全共享敏感数据。
# secure_artifact_manager.py
import boto3
import json
class SecureArtifactManager:
def __init__(self, bucket: str, kms_key_id: str):
self.s3 = boto3.client('s3')
self.kms = boto3.client('kms')
self.bucket = bucket
self.kms_key_id = kms_key_id
def store_sensitive_result(self, agent_id: str, session_id: str, data: dict) -> str:
"""将敏感结果加密存储到 S3"""
key = f"agentcore/{agent_id}/{session_id}/result.json"
self.s3.put_object(
Bucket=self.bucket,
Key=key,
Body=json.dumps(data),
ServerSideEncryption='aws:kms',
SSEKMSKeyId=self.kms_key_id,
Metadata={'pii': 'true', 'agent-session': session_id}
)
return f"s3://{self.bucket}/{key}"
def load_from_eks(self, s3_uri: str) -> dict:
"""从 EKS Pod 加载 S3 对象(通过 Pod Identity 进行 KMS 解密)"""
bucket, key = s3_uri.replace('s3://', '').split('/', 1)
response = self.s3.get_object(Bucket=bucket, Key=key)
return json.loads(response['Body'].read())
IAM 策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT:role/AgentCoreExecutionRole"
},
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::my-secure-artifacts/agentcore/*",
"Condition": {
"StringEquals": {"s3:x-amz-server-side-encryption": "aws:kms"}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::ACCOUNT:role/EKSPodRole"
},
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::my-secure-artifacts/agentcore/*"
}
]
}
切换模式目录
模式 (a): Router-front(AgentCore Gateway→自托管)
AgentCore Gateway 分析请求后路由到 AgentCore Agent 或 EKS 自托管 Agent。
分类标准:
| 复杂度得分 | 路由目标 | 示例任务 |
|---|---|---|
| 0.0-0.3 | EKS Qwen3-4B | 代码补全、翻译、摘要 |
| 0.3-0.7 | AgentCore Claude Haiku | 基础分析、简单推理 |
| 0.7-1.0 | AgentCore Claude Sonnet | 架构审查、复杂推理 |
实现:
# classifier_router.py
from strands import Agent
from strands.models import BedrockModel
import boto3
bedrock_runtime = boto3.client('bedrock-agent-runtime')
class HybridRouter:
def __init__(self):
self.classifier = Agent(
model=BedrockModel(model_id="anthropic.claude-haiku-20250320"),
system_prompt="""你是一个请求复杂度分类器。
请评估复杂度为 0.0-1.0 之间并以 JSON 格式响应。
{"complexity": 0.0-1.0, "reason": "原因"}"""
)
def route(self, user_request: str) -> dict:
classification = self.classifier(f"请求: {user_request}")
complexity = classification['complexity']
if complexity < 0.3:
return self._route_to_eks(user_request)
elif complexity < 0.7:
return self._route_to_agentcore(user_request, model='haiku')
else:
return self._route_to_agentcore(user_request, model='sonnet')
def _route_to_eks(self, request: str) -> dict:
"""路由到 EKS Kagent"""
import requests
response = requests.post(
"http://kagent-service.agents.svc.cluster.local/invoke",
json={"prompt": request, "model": "qwen3-4b"}
)
return {"response": response.json(), "routed_to": "eks-kagent"}
def _route_to_agentcore(self, request: str, model: str) -> dict:
"""路由到 AgentCore"""
response = bedrock_runtime.invoke_agent(
agentId='AGENT123',
agentAliasId='ALIAS456',
sessionId='session-' + str(hash(request)),
inputText=request
)
return {"response": response, "routed_to": f"agentcore-{model}"}