Secrets Manager Agent 升级:预取密钥 + IAM 角色切换,冷启动延迟直降 90%
"Lambda 冷启动 800ms,其中 600ms 在等 Secrets Manager 返回数据库密码。"
如果你的应用在启动时需要从 Secrets Manager 拉密钥,大概率踩过这个坑——API 调用延迟在冷启动路径上特别刺眼。正常运行时 Secrets Manager 响应几十毫秒不是问题,但冷启动时累积三四个密钥请求就是大几百毫秒。
亚马逊云科技上周给 Secrets Manager Agent 加了两个新能力:
- Pre-fetching — Agent 启动时预加载你配置好的密钥,应用启动时密钥已在本地缓存
- IAM Role Assumption — Agent 可以 assume 不同的 IAM 角色去拉不同作用域的密钥
这两个功能组合起来,解决了密钥获取在延迟敏感场景下的性能问题。
Secrets Manager Agent 是什么
先说背景。Secrets Manager Agent 是一个轻量级本地进程,跑在你的计算实例上(EC2、ECS、EKS Pod),充当应用和 Secrets Manager 服务之间的代理层。
它的核心价值:
- 本地缓存:密钥拉一次缓存在内存里,不用每次都调 API
- 自动轮转:密钥更新时自动刷新缓存
- HTTP 接口:应用通过
http://localhost:2773拉密钥,不用集成 AWS SDK
之前的限制:Agent 启动后要等第一次请求才去拉密钥(被动缓存)。现在有了 pre-fetching,变成主动预加载。
Pre-fetching 配置
基本配置
# /etc/secrets-manager-agent/config.yaml
cache:
ttl: 300 # 缓存 5 分钟
max_size: 100
# 新增:预取配置
prefetch:
enabled: true
secrets:
- secret_id: "prod/database/mysql"
- secret_id: "prod/api-keys/stripe"
- secret_id: "prod/api-keys/sendgrid"
- secret_id: "arn:aws:secretsmanager:us-east-1:123456789:secret:prod/redis-abc123"
server:
port: 2773
bind: "127.0.0.1"
效果对比
# 不用 Pre-fetching(老方式):
# App 启动 → 请求 Secret A → 等 API 返回 (80ms)
# → 请求 Secret B → 等 API 返回 (75ms)
# → 请求 Secret C → 等 API 返回 (90ms)
# 总延迟: ~245ms
# 用 Pre-fetching(新方式):
# Agent 启动 → 后台并行预取 A/B/C (一次性 ~100ms)
# App 启动 → 请求 Secret A → 本地缓存命中 (< 1ms)
# → 请求 Secret B → 本地缓存命中 (< 1ms)
# → 请求 Secret C → 本地缓存命中 (< 1ms)
# App 可见延迟: < 3ms
从 245ms 降到 3ms,延迟降了 90%+。
在 ECS Task Definition 中使用
{
"containerDefinitions": [
{
"name": "secrets-agent",
"image": "public.ecr.aws/aws-secrets-manager/secrets-manager-agent:latest",
"essential": true,
"portMappings": [
{"containerPort": 2773, "protocol": "tcp"}
],
"environment": [
{"name": "SECRETS_MANAGER_AGENT_CONFIG", "value": "/config/config.yaml"}
],
"mountPoints": [
{"sourceVolume": "agent-config", "containerPath": "/config"}
]
},
{
"name": "my-app",
"image": "my-app:latest",
"dependsOn": [
{"containerName": "secrets-agent", "condition": "HEALTHY"}
],
"environment": [
{"name": "SECRETS_ENDPOINT", "value": "http://localhost:2773"}
]
}
]
}
关键点:dependsOn + HEALTHY 确保 Agent 完成预取后应用才启动。
IAM Role Assumption
之前 Agent 只能用宿主实例的 IAM 角色拉密钥。如果一台机器跑多个微服务,每个服务需要不同密钥(不同权限边界),就得跑多个 Agent 实例。
现在可以配置多个角色:
# 多角色配置
roles:
- name: "payments-role"
role_arn: "arn:aws:iam::123456789:role/payments-secrets-reader"
session_name: "payments-agent"
secrets:
- "prod/payments/stripe-key"
- "prod/payments/bank-credentials"
- name: "notifications-role"
role_arn: "arn:aws:iam::123456789:role/notifications-secrets-reader"
session_name: "notifications-agent"
secrets:
- "prod/notifications/ses-credentials"
- "prod/notifications/push-certs"
- name: "analytics-role"
role_arn: "arn:aws:iam::987654321:role/cross-account-analytics"
external_id: "analytics-2026"
secrets:
- "prod/analytics/redshift-password"
跨账号场景
数据团队的密钥在账号 B,应用在账号 A:
import requests
# 应用代码不变,Agent 自动 assume 对应角色
# 请求带上角色标识
response = requests.get(
'http://localhost:2773/secretsmanager/get',
params={
'secretId': 'prod/analytics/redshift-password',
'role': 'analytics-role' # 指定用哪个角色
},
headers={'X-Aws-Parameters-Secrets-Token': os.environ['SECRETS_TOKEN']}
)
secret = response.json()['SecretString']
IAM 策略示例
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowAgentToAssumeRoles",
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": [
"arn:aws:iam::123456789:role/payments-secrets-reader",
"arn:aws:iam::123456789:role/notifications-secrets-reader",
"arn:aws:iam::987654321:role/cross-account-analytics"
]
}
]
}
完整实战:EKS Pod 中使用
# Kubernetes Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
template:
spec:
serviceAccountName: order-service-sa # IRSA 绑定 IAM Role
initContainers:
- name: secrets-agent-init
image: public.ecr.aws/aws-secrets-manager/secrets-manager-agent:latest
command: ["sh", "-c", "secrets-manager-agent --prefetch --wait-ready"]
volumeMounts:
- name: agent-socket
mountPath: /var/run/secrets-agent
containers:
- name: order-service
image: order-service:latest
env:
- name: DB_HOST
value: "prod-mysql.xxx.us-east-1.rds.amazonaws.com"
- name: DB_PASSWORD_SECRET
value: "prod/orders/db-password"
- name: SECRETS_ENDPOINT
value: "http://localhost:2773"
- name: secrets-agent
image: public.ecr.aws/aws-secrets-manager/secrets-manager-agent:latest
ports:
- containerPort: 2773
volumeMounts:
- name: agent-config
mountPath: /config
volumes:
- name: agent-config
configMap:
name: secrets-agent-config
- name: agent-socket
emptyDir: {}
性能数据
根据官方公告和实测估算:
| 场景 | 无 Agent | Agent(无预取) | Agent(预取) |
|---|---|---|---|
| 首次获取密钥 | 80-120ms | 80-120ms | < 1ms |
| 后续获取 | 80-120ms | < 1ms | < 1ms |
| 冷启动 3 密钥 | ~300ms | ~300ms | < 3ms |
| P99 延迟 | 200ms | 5ms | 2ms |
我的判断
这个更新看起来不起眼,但对延迟敏感的应用来说是实打实的改进。
之前的最佳实践是在应用代码里自己做预加载(启动时主动调 Secrets Manager API),但这意味着每个应用都要写一遍这个逻辑。现在 Agent 层面解决了,应用代码可以更干净。
IAM 角色切换也是个实用功能——之前一台机器跑多个服务要么共享一个大权限角色(安全风险),要么跑多个 Agent(资源浪费)。现在一个 Agent 支持多角色,最小权限原则落地更自然了。
唯一要注意的:Agent 本身变成了关键路径。如果 Agent 挂了,所有依赖它的应用都拉不到密钥。建议配合健康检查和自动重启策略。
相关链接:
- Secrets Manager Agent 更新公告:https://aws.amazon.com/about-aws/whats-new/2026/05/secrets-manager-agent-prefetch-and-role-assumption/
- Secrets Manager Agent 文档:https://docs.aws.amazon.com/secretsmanager/latest/userguide/secrets-manager-agent.html
- AWS Secrets Manager 产品页:https://aws.amazon.com/secrets-manager/

浙公网安备 33010602011771号