AWS CDK应用程序
使用AWS CDK创建ECS基础设施项目的Github模板
先决条件
AWS CDK项目在合成或部署之前需要一些引导。 请查看 bootstapping文档 在开发之前。
\[!注意\] Sage IT在我们的AWS组织中创建每个AWS帐户时都会部署此CDK引导程序。
开发容器
此存储库提供 dev容器 包括所有工具 需要开发此AWS CDK应用程序。
在开发容器中打开项目
使用VS代码:
- 克隆此仓库
- 文件>打开文件夹。..
- 提示应邀请您在开发容器中打开项目。如果没有,打开VS Code
命令面板并选择“开发容器:打开容器中的文件夹…”
使用GitHub代码空间:
- 在该存储库的主页上,单击按钮“代码”>代码空间>单击
按钮“创建代码空间”
就是这样!现在,您已进入开发容器,可以访问所有开发工具。
发展
在dev容器内开发时提供所有开发工具 (见上文)。这些工具包括Python、AWS CLI、AWS CDK CLI等。这些工具 还包括一个Python虚拟环境,其中需要所有Python包 已安装。
如果您决定在开发容器之外进行开发 可以通过运行以下命令安装工具:
./tools/setup.sh开发需要激活Python虚拟环境:
$ source .venv/bin/activate此时,您现在可以合成此代码的CloudFormation模板。
$ cdk synth要添加其他依赖项,例如其他CDK库,只需添加 他们给你 setup.py 文件并重新运行 pip install -r requirements.txt 命令。
有用的命令
cdk ls列出应用程序中的所有堆栈cdk synth发出合成的CloudFormation模板cdk deploy将此堆栈部署到默认的AWS帐户/区域cdk diff将部署的堆栈与当前状态进行比较cdk docs打开CDK文档
测试
静态分析
作为预部署步骤,我们对CDK-json、yaml和 python文件 预承诺.
请安装预提交,安装后文件验证将 每次提交时自动运行。或者,您可以手动 通过运行以下命令执行验证 pre-commit run --all-files.
通过运行\[CDK synth\]验证CDK到Cloudformation的转换:
cdk synth --context env=dev云信息输出保存到 cdk.out 文件夹
单元测试
测试位于Tests文件夹中。执行以下操作以运行测试:
python -m pytest tests/ -s -v环境
跑步时 cdk 命令,您必须指定哪个环境 配置使用。这是通过将上下文变量传递给 CDK,加载特定于环境的参数。
在中创建配置文件 config文件夹 对于每种环境 (例如。, dev.yaml, prod.yaml).支持yaml和json文件。 支持的环境是dev、stage和prod。
使用 prod 环境配置:
cdk synth --context env=prod还有一个始终加载的可选基本配置文件 并与传入的环境配置之一合并。
特定于环境的配置文件中的值将 如果存在冲突,请覆盖基本配置文件中的那些。 例如,如果两个文件都定义 TAGS,价值来自 dev.yaml 将优先考虑。
\[!注意\] 确保 VPC_CIDR 在您的AWS组织中是独一无二的。必需的AWS机密
在部署synapse mcp服务之前,您必须在AWS secrets Manager中创建以下机密:
- synapse mcp/oauth客户端密钥
- 包含Synapse OAuth客户端密钥 - 创建方式: aws secretsmanager create-secret --name synapse-mcp-{env}/oauth-client-secretval --secret-string "your-client-secret"
这些秘密会自动作为环境变量注入(SYNAPSE_OAUTH_CLIENT_SECRET)进入ECS容器。
\[!重要\] 确保这些机密存在于部署堆栈的同一AWS区域中。
Valkey基础设施
该基础设施包括用于Valkey的AWS ElastiCache无服务器(兼容Redis),用于:
- 客户端注册表:OAuth客户端注册(MCP客户端,如Claude Desktop、VS Code)
- 会话存储:用户身份验证令牌和会话
Valkey配置
Valkey无服务器设置在配置文件中按环境配置:
- 引擎版本:Valkey 8.2(最新版本)
- 容量:通过可配置的最大ECPU和存储自动扩展
- dev/state/prod:当前设置为最低1000 ECPU/秒,1 GB存储
主要特点:
- 无服务器:根据需求自动扩展容量
- 加密:启用了传输中的TLS和静态加密
- 每日快照:实现数据持久性的自动化每日快照
- 安全:仅限专用子网,只能从ECS任务访问
- 连接:通过自动配置
REDIS_URL环境变量
Valkey连接URL存储在AWS Systems Manager参数存储中 /synapse-mcp/{environment}-redis/redis-url 并自动注入ECS容器。 请参阅我们的 指导 在选择唯一的CIDR块时。
证书
应在AWS证书管理器中手动创建用于设置HTTPS连接的证书。 由于AWS要求手动验证域所有权,因此这不是自动化的。 创建后,获取证书的ARN,并在environment_variables中设置该ARN。
秘密
可以在中手动创建秘密 AWS机密管理器. 命名秘密时,请确保秘密不会以匹配的模式结尾 -??????,这将导致AWS CDK查找机密的方式出现问题。
要将机密传递给容器,请设置机密管理器 container_secrets 当创建a ServiceProp 对象。您将创建一个列表 ServiceSecret 物体:
from src.service_props import ServiceProps, ServiceSecret
app_service_props = ServiceProps(
ecs_task_cpu=256,
ecs_task_memory=512,
container_name="app",
container_port=443,
container_location="ghcr.io/sage-bionetworks/app:v1.0",
container_secrets=[
ServiceSecret(
secret_name="app/dev/DATABASE",
environment_key="NAME_OF_ENVIRONMENT_VARIABLE_SET_FOR_CONTAINER",
),
ServiceSecret(
secret_name="app/dev/PASSWORD",
environment_key="SINGLE_VALUE_SECRET",
)
]
)例如,KVs app/dev/DATABASE 可以是:
{
"DATABASE_USER": "maria",
"DATABASE_PASSWORD": "password"
}以及价值 app/dev/PASSWORD 可以是: password
在应用程序(Python)代码中,可以使用以下代码将机密加载到字典中:
import json
import os
all_secrets_dict = json.loads(os.environ["NAME_OF_ENVIRONMENT_VARIABLE_SET_FOR_CONTAINER"])对于单个值,您可以加载该值,如下所示:
import os
my_secret = os.environ.get("SINGLE_VALUE_SECRET", None)\[!注意\] 检索机密需要访问AWS机密管理器
域名系统
DNS CNAME必须在初始设置后在组织结构中创建 部署应用程序,使应用程序在所需的时间可用 URL。CDK应用程序导出应用程序负载平衡器的DNS名称 在组织结构中被消耗。 PR设置CNAME的示例.
登录AWS云信息控制台并导航到已部署的堆栈 app-load-balancer 然后单击 Outputs tab。在键为的行上 LoadBalancerDNS 寻找 价值在 Export Name 例如。, app-dev-load-balancer-dns. Cloudformation Load Balancer
现在使用名称 TargetHostName 定义,例如:
TargetHostName: !CopyValue [!Sub 'app-dev-load-balancer-dns', !Ref DnTDevAccount](您也可以替换 DnTDevAccount 使用部署应用程序的帐户名称。)
\[!注意\] DNS名称的设置应在本次基础设施设置的最后完成
调试
通常,CDK部署将在CDK部署期间创建云形成事件。 这些事件可以在AWS控制台的cloudformation服务页面下查看。 查看这些事件将有助于解决部署过程中的错误。以下是案例 由于错误误导或错误不足,可能难以调试 来自AWS的消息
失踪的秘密
每个新环境(dev/ststage/prod/等)都可能需要添加机密。如果 没有为环境创建secret,您可能会遇到以下错误 堆栈跟踪。.
Resource handler returned message: "Error occurred during operation 'ECS Deployment Circuit Breaker was triggered'." (RequestToken: d180e115-ba94-d8a2-acf9-abe17a3aaed9, HandlerErrorCode: GeneralServiceException)
new BaseService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs/lib/base/base-service.js:1:3583)
\_ new FargateService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs/lib/fargate/fargate-service.js:1:967)
\_ new ApplicationLoadBalancedFargateService (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/jsii-kernel-4PEWmj/node_modules/aws-cdk-lib/aws-ecs-patterns/lib/fargate/application-load-balanced-fargate-service.js:1:2300)
\_ Kernel._create (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:9964:29)
\_ Kernel.create (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:9693:29)
\_ KernelHost.processRequest (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11544:36)
\_ KernelHost.run (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11504:22)
\_ Immediate._onImmediate (/private/var/folders/qr/ztb40vmn2pncyh8jpsgfnrt40000gp/T/tmpqkmckdm2/lib/program.js:11505:46)
\_ processImmediate (node:internal/timers:464:21)部署
独自创立
在部署应用程序之前,需要手动引导一些项目。
- 将机密添加到AWS机密管理器
- 创建一个 申请ACM证书 使用AWS证书管理器
- 更新中的environment_variables app.py 每个环境都有特定的变量。
- 更新对docker镜像的引用 app.py
(即。 ghcr.io/sage-bionetworks/app-xxx:)
- (可选)更新
ServiceProps对象在 app.py 具有特定参数
每个集装箱。
使用AWS CLI登录
\[!注意\] 本节和以下部分假设您在AWS帐户中工作org-sagebase-itsandbox随着角色Developer并且您正在部署 到us-east-1区域。如果这个假设是正确的,你应该能够 只需复制粘贴以下命令,否则调整 配置应该很简单。
如果配置文件还不存在,请创建它。
mkdir ~/.aws && touch ~/.aws/config作为Sage IT Sandbox AWS帐户的开发人员,请将以下配置文件添加到配置文件中。
[profile itsandbox-dev]
sso_start_url = https://d-906769aa66.awsapps.com/start
sso_region = us-east-1
sso_account_id = XXXXXXXXX
sso_role_name = Developer使用AWS CLI登录:
aws --profile itsandbox-dev sso login部署
部署需要设置 AWS配置文件 然后执行以下命令:
AWS_PROFILE=itsandbox-dev AWS_DEFAULT_REGION=us-east-1 cdk deploy --context env=dev --all强制新部署
AWS_PROFILE=itsandbox-dev AWS_DEFAULT_REGION=us-east-1 aws ecs update-service \
--cluster \
--service \
--force-new-deployment从ECS上运行的容器执行命令
一旦容器成功部署,就可以使用 ECS执行命令
让交互式shell运行到容器中的示例:
AWS_PROFILE=itsandbox-dev AWS_DEFAULT_REGION=us-east-1 aws ecs execute-command \
--cluster AppEcs-ClusterEB0386A7-BygXkQgSvdjY \
--task a2916461f65747f390fd3e29f1b387d8 \
--container app-mariadb \
--command "/bin/sh" --interactiveCI工作流
此仓库已设置为使用Github Actions CI持续部署应用程序。
持续集成的工作流程:
- 从git dev分支创建PR
- PR经过审查和批准
- PR已合并
- CI将更改部署到AWS开发帐户中的开发环境(dev.app.io)。
- 更改被提升(或合并)到git stage分支。
- CI将更改部署到AWS prod帐户中的暂存环境(stage.app.io)。
- 更改被提升(或合并)到git prod分支。
- CI将更改部署到AWS prod帐户中的prod环境(prod.app.io)。
