AWS News Blog
在本地使用 AWS Emulator 测试你的应用程序
今天我们宣布推出 AWS Emulator,这是一个可在你的机器上运行的 Amazon Web Services(AWS)本地模拟器。AWS Command Line Interface(AWS CLI)、AWS SDK 以及你的编码代理通过本地 HTTPS 端点与它通信,使用它们将在云中使用的相同 AWS API,这一切都可以在你的笔记本电脑上完成。AWS Emulator 不收取额外服务费。你只需在 AWS 上部署时支付 AWS 资源费用。其源代码位于 GitHub。在 Linux 上,你可以从 RPM 或 Debian 包安装它;在 macOS 和 Windows 上,你可以在 Docker 中运行它。
工作原理:你安装模拟器、启动它,然后让工具指向本地端点。AWS Emulator 启动时,会生成自己的凭证、配置文件和证书,并将它们写入 ~/.aws/emulator/9297/。你设置环境变量,使 AWS SDK 与你的笔记本电脑通信而不是与 AWS 通信,而你的应用程序代码保持不变。
从那时起,你现有的测试、CLI 脚本和编码代理会继续以它们已有的方式工作。一个创建 Amazon DynamoDB 表、写入一个项目并读回它的单元测试还是同一个测试,它在你的机器上运行,无需部署。编码代理可以创建资源、检查结果并再次迭代,而无需等待在某个 Region 中部署。
该模拟器用 Rust 实现,因此它在笔记本电脑上保持较低的 CPU 和内存占用。它支持那些在 GitHub 上的 AWS API models 仓库中具有 API 模型的 AWS 服务的 API;由于它基于这些模型构建——也就是 AWS SDK 使用的同一批模型——你的请求和返回的错误与在 AWS 上具有相同的形态。
如果你是一名开发者,尤其是使用 Kiro 或 Claude Code 这类编码代理的开发者,你可以利用这个循环在本地测试真正复杂的 AWS 交互。
我们来试试。要开始,我在 Amazon Linux 2023 上安装了该包。该包将 aws-emulator 命令添加到 /usr/bin/,因此它在 PATH 中。
PKG=https://downloads.aws.com/aws-emulator/packages/aws-emulator/LTS/latest
sudo dnf install -y $PKG/aws-emulator-x86_64.rpm
aws-emulator -v
在 macOS 和 Windows 上,你根据文档中简短的 Dockerfile 构建 Docker 镜像,并在容器中运行模拟器。我们不发布现成的镜像。
我用 aws-emulator 启动了模拟器。它在 127.0.0.1:9297 上提供 HTTPS 服务,因此只有我自己的计算机可以访问它;它以 JSON 行格式写入日志,显示地址、配置文件和证书文件。
aws-emulator
在另一个终端中,我设置了将 AWS CLI 指向该模拟器的环境变量,并取消设置任何可能提供真实 AWS 凭证的变量。
export AWS_ENDPOINT_URL=https://127.0.0.1:9297
export AWS_SHARED_CREDENTIALS_FILE=~/.aws/emulator/9297/emulator_credentials
export AWS_CONFIG_FILE=~/.aws/emulator/9297/config
export AWS_EC2_METADATA_DISABLED=true
export AWS_DISABLE_HOST_PREFIX_INJECTION=true
export AWS_REGION=us-east-1
export AWS_DEFAULT_REGION=us-east-1
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_PROFILE
该模拟器每次启动时都会生成新密钥。其访问密钥 ID 以 EMULATOR 开头,因此你不会把它们误认为真实的 AWS 密钥;它会拒绝使用任何其他密钥签名的请求。为了确认我的 shell 正在与模拟器通信,我检查了健康端点和调用者身份。该模拟器使用单个账户 000000000000。
curl --cacert ~/.aws/emulator/9297/ca.pem https://127.0.0.1:9297/__admin/health
aws sts get-caller-identity
然后我创建了一个存储桶,复制进去一个小对象,并列出它。
$ aws s3 mb s3://local-getting-started
make_bucket: local-getting-started
$ echo "hello from the emulator" > hello.txt
$ aws s3 cp hello.txt s3://local-getting-started/
upload: ./hello.txt to s3://local-getting-started/hello.txt
$ aws s3 ls s3://local-getting-started/
我把 AWS CLI 指向我的笔记本电脑后,仍然使用自己已经在用的那些命令,只不过由一个本地端点来响应它们。
接下来,我想按我现在实际工作的方式来试试它,因此在模拟器仍在运行的情况下,我打开 Kiro,让它创建一个 Amazon DynamoDB 表、写入一个条目,再把它读回来,全部针对 AWS Emulator,而不是我的 AWS 账户。
kiro> Using the local AWS Emulator (the environment variables
are already set in this shell), create a DynamoDB table
"kiro-demo" with a string key "id", put an item
{id: "item-1", msg: "hello from kiro"}, then read it
back with get-item.
$ aws dynamodb create-table --table-name kiro-demo \
--attribute-definitions AttributeName=id,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
$ aws dynamodb put-item --table-name kiro-demo \
--item '{"id": {"S": "item-1"}, "msg": {"S": "hello from kiro"}}'
$ aws dynamodb get-item --table-name kiro-demo --key '{"id": {"S": "item-1"}}'
要把同样的设置用于现有测试套件,我会启动模拟器,在运行测试的脚本中设置相同的环境变量,然后照常运行测试。
在进程内使用模拟器 将模拟器作为本地进程运行会提供一个 HTTPS 端点,通过环境变量即可配合 AWS CLI 和 AWS SDK 使用。有些 SDK 需要额外设置才能信任模拟器证书,例如为 AWS SDK for Java 配置信任库。对于测试,还有第二种选择。AWS Emulator 提供嵌入式模式,你可以直接在测试进程中实例化它,并通过其 HTTP 客户端接入 SDK,而不是通过网络与单独的服务器通信。每个嵌入式实例都维护自己的状态,因此测试之间不会共享存储桶、表或队列,并且你可以并行运行多个实例。嵌入式模式适用于 AWS SDK for Rust。你需要把来自 GitHub 的 aws-emulator-embedded crate 添加到 Cargo.toml 文件的 [dev-dependencies] 部分。下面的示例创建一个 Amazon DynamoDB 表,写入一个条目,再将其读回,整个过程都在进程内完成。
use aws_emulator_embedded::{AwsEmulatorEmbedded, EmbeddedOptions};
use aws_sdk_dynamodb::types::{
AttributeDefinition, AttributeValue, BillingMode, KeySchemaElement, KeyType,
ScalarAttributeType,
};
#[tokio::test]
async fn put_then_get_returns_the_item() {
let emulator = AwsEmulatorEmbedded::new(EmbeddedOptions::default());
let config = aws_config::defaults(aws_config::BehaviorVersion::latest())
.http_client(emulator.http_client())
.region(aws_config::Region::new("us-east-1"))
.credentials_provider(emulator.aws_credentials_provider())
.load()
.await;
let ddb = aws_sdk_dynamodb::Client::new(&config);
ddb.create_table()
.table_name("emulator-demo-table")
.attribute_definitions(
AttributeDefinition::builder()
.attribute_name("id").attribute_type(ScalarAttributeType::S)
.build().unwrap())
.key_schema(
KeySchemaElement::builder()
.attribute_name("id").key_type(KeyType::Hash)
.build().unwrap())
.billing_mode(BillingMode::PayPerRequest)
.send().await.unwrap();
ddb.put_item()
.table_name("emulator-demo-table")
.item("id", AttributeValue::S("item-1".into()))
.item("msg", AttributeValue::S("hi".into()))
.send().await.unwrap();
let got = ddb.get_item()
.table_name("emulator-demo-table")
.key("id", AttributeValue::S("item-1".into()))
.send().await.unwrap();
assert_eq!(got.item().unwrap().get("msg").unwrap().as_s().unwrap(), "hi");
}
使用 AWS Emulator 在本地针对 AWS 测试你的应用
当模拟器作为本地进程运行时,它要求每个请求都使用 Signature Version 4(SigV4)签名,这与 AWS 的做法相同;它还在同一端口上提供 /__admin/health 端点,以便脚本或容器在运行测试前等待其就绪。默认情况下,它还会发送匿名的使用和错误数据,你可以将其关闭。
我们如何衡量保真度 模拟器只有在以下情况下才有用:针对它能够通过的测试,在 AWS 上也能通过;因此我们直接用保真度测试来衡量这一点。保真度测试是一段简短程序,它使用 AWS SDK 运行一个工作流,例如存储一个对象,然后读取并删除它,并断言 AWS 的行为方式。我们会针对真实 AWS 验证每个保真度测试。只有当模拟器在每次调用的响应上(包括状态码、响应体,以及确切的错误码和消息),以及在工作流创建的资源与数据上,都与 AWS 一致时,保真度测试才算通过。
每次发布时,我们都会以 k of n 的形式公布每个服务有多少保真度测试通过。例如,40 of 50 表示该服务的 50 个保真度测试中有 40 个通过。保真度测试集合在 GitHub 上的 aws-emulator-evaluation-suite 仓库中公开,包括尚未通过的那些,这样你可以看到我们验证了什么,并自己运行保真度测试。请把分数看作一个正在改进的产品的快照。当我们增加保真度测试时,即使模拟器变得更好,分数也可能下降。
如果模拟器尚未实现某个操作,它会返回 HTTP 501(Not Implemented),因此你的测试会立即失败。如果模拟器的行为与 AWS 不同,你可以通过在 GitHub 上的 AWS Emulator 仓库中提交 issue 来告诉我们。
模拟器是如何构建的 AWS Emulator 由智能体基于 AWS API 模型构建和维护,这些智能体使用 Amazon Bedrock AgentCore Runtime Instances、AWS CodePipeline 和 AWS CodeCommit,因此随着这些模型变化,它能与 AWS 保持同步。
一组智能体会寻找差距,既通过将模拟器响应与真实 AWS 比较,也通过将模拟器代码与已发布的 Smithy 模型进行静态比较,并为其发现的每个差距提交一个 issue。另一组会接手一个 issue,编写测试、实现行为,并从正确性、性能和安全性方面审查变更。当变更准备好后,它会被推送到源仓库,该推送会触发一次 AWS CodePipeline 运行,在变更发布到公共 GitHub 仓库之前运行保真度测试。
我们如何保证其安全 由于代码由智能体编写,一个独立的安全智能体会以对抗性方式审查变更:既在修复进行期间审查,也在发布流水线中再次审查,作为任何内容发布前的最终检查。
你自己使用时的安全仍然是一项共同责任。我们构建模拟器,使其能在你的机器上安全运行:默认情况下它只在你自己的计算机上监听,并拒绝未使用它自己的密钥签名的请求。由你决定它在哪里运行、向其中放入什么数据,以及在生产前如何测试。不要用模拟器测试你的应用是否安全。它不会像 AWS 那样评估 AWS Identity and Access Management (IAM) 策略和基于资源的策略,因此 AWS 拒绝的请求可能会在模拟器中成功。不要让真实凭证出现在测试任务的环境中,并在生产前在 AWS 上测试你的安全设置和整个应用。
AWS Emulator 现已推出,并于今日正式可用。它不收取额外服务费。在 AWS 上部署时,你只需为 AWS 资源付费。你可以通过 Linux 上的 RPM 或 Debian 包安装它,在 macOS 和 Windows 上通过 Docker 运行它,或从源代码构建;设置环境变量后,它可与 AWS SDKs 和 AWS CLI 配合使用。在发布时,它有一些限制。它不会像 AWS 那样评估 IAM 策略,并且每个模拟器都作为单一账户运行,不具备跨账户或跨区域行为。它与 AWS 的接近程度因服务和功能而异。要了解模拟器对你所用服务的覆盖程度,请查看 AWS Emulator 文档中的保真度评分。
如果你想查看区域可用性,请访问 AWS Builder Center 中的 AWS Capabilities by Region 页面。如果你想调用 API、搜索文档、查找区域可用性,并查看有关此新功能的故障排除信息,请尝试在你偏好的 AI 工具中使用 AWS MCP Server 和插件。
要开始使用,请访问 GitHub 上的 AWS Emulator 仓库并查看 AWS Emulator 文档。
2026 年 11 月 12 日更新:添加了指向 GitHub 上 AWS Emulator 仓库的链接。
资源
- 入门
- 官方 AWS 播客
- 案例研究
关注
- 电子邮件更新