news 2026/10/21 23:42:50

aws-cdk-examples:用 Python CDK 为 Fargate 服务挂载 EFS 共享存储的完整实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
aws-cdk-examples:用 Python CDK 为 Fargate 服务挂载 EFS 共享存储的完整实战

【免费下载链接】aws-cdk-examples

Example projects using the AWS CDK

项目地址:https://gitcode.com/gh_mirrors/aw/aws-cdk-examples
点击查看免费下载

本篇基于aws-cdk-examples仓库中的python/ecs/fargate-service-with-efs示例,讲解如何用 AWS CDK 部署一个"公网 ALB 前置 + ECS Fargate 服务 + EFS 文件系统挂载"的完整架构。读完本文,你能掌握 EFS 访问点、EfsVolumeConfiguration与 IAM 任务角色的配置要点、Fargate 任务定义中卷与挂载点的接线方式,以及如何通过 ALB 与 CPU/内存双维自动扩缩容让这个带共享存储的服务可对外提供服务。该示例源自 AWS 官方博客关于 ECS 支持 EFS 的方案,演示的核心场景是:让无服务器化计算(Fargate)能够使用独立于计算节点的共享存储。

一、示例架构与资源全景

这个 CDK 应用由单个 Python 文件 app.py 构成,一次部署会创建以下资源:

  • 一个 VPC(max_azs=2,限制可用区数量以规避资源配额限制)
  • 一个 ECS 集群
  • 一个 EFS 文件系统及其 Access Point(访问点)
  • 一个 Fargate 任务定义,其中声明了 EFS 卷与容器挂载点
  • 一个由ApplicationLoadBalancedFargateService模式构造的、带公网 Application Load Balancer 的 Fargate 服务
  • 双向放通 2049 端口(NFS)的安全组规则
  • 基于 CPU 与内存利用率的 Application Auto Scaling 策略(1~20 个任务)

示例中所有资源使用统一的efs-sample-前缀命名,方便在 AWS 控制台中按名称检索:

PREFIX = 'efs-sample-' APP_PATH = '/var/www/' VOLUME_NAME = 'cdk-ecs-sample-efs-volume'

(以上常量定义见 app.py)

二、环境准备与部署步骤

该示例是标准的 Python CDK 项目布局:cdk.json 中通过"app": "python3 app.py"告诉 CDK Toolkit 如何执行应用,并配置了watch的包含/排除规则以及一组 CDK 上下文开关(如@aws-cdk/aws-efs:denyAnonymousAccess、@aws-cdk/aws-ecs:arnFormatIncludesClusterName等,用于保持与当前 aws-cdk-lib 行为一致)。依赖声明在 requirements.txt 中:

aws-cdk-lib>=2.262.0,<3.0.0 constructs>=10.5.0,<11.0.0

因此该示例面向 CDK v2(aws-cdk-lib 2.x),要求环境中已全局安装 CDK CLI。

完整的部署流程如下(继承自 README):

  1. 创建并激活虚拟环境。init 过程会在项目下创建.env目录存放虚拟环境,前提是 PATH 中有带venv包的python3(Windows 上为python)。自动创建失败时可手动创建:

    $ python3 -m venv .env

    激活方式,macOS/Linux:

    $ source .env/bin/activate

    Windows:

    % .env\Scripts\activate.bat
  2. 安装依赖:

    $ pip install -r requirements.txt
  3. 首次部署该账户/环境时,先执行 bootstrap 初始化 CDK 默认环境(用于放置 S3 资产桶等 CDK 基础设施):

    $ cdk bootstrap
  4. 部署 CloudFormation 模板:

    $ cdk deploy

三、基础设施源码剖析

3.1 VPC 与 ECS 集群

网络与集群的创建非常克制——VPC 通过max_azs=2限制可用区数量(EFS 挂载目标、NAT 网关等资源会随 AZ 数量线性增加),随后在该 VPC 上创建集群:

vpc = ec2.Vpc( self, PREFIX + 'Vpc', max_azs=2 ) ecs_cluster = ecs.Cluster( self, PREFIX + 'Cluster', vpc=vpc, )

3.2 EFS 文件系统与 Access Point

文件系统的两个关键参数值得注意:

file_system = efs.FileSystem( self, PREFIX + 'EFS', vpc=vpc, lifecycle_policy=efs.LifecyclePolicy.AFTER_14_DAYS, performance_mode=efs.PerformanceMode.GENERAL_PURPOSE, ) access_point = efs.AccessPoint( self, PREFIX + 'AccessPoint', file_system=file_system, )
  • lifecycle_policy=AFTER_14_DAYS:14 天未被访问的文件会被自动分层到低频存储,降低存储成本;
  • performance_mode=GENERAL_PURPOSE:通用型性能模式(对应底层bursting吞吐量模式),适合多数共享存储场景;
  • 单独创建AccessPoint而非直接挂根路径,是 ECS 挂载 EFS 的推荐做法——访问点为挂载提供统一的"入口 + 权限位",配合 IAM 鉴权可以实现文件系统级别的细粒度访问控制。

3.3 卷配置:EfsVolumeConfiguration

这是把 EFS 与 ECS 任务"接线"的核心,app.py 中写为:

efs_volume_configuration = ecs.EfsVolumeConfiguration( file_system_id=file_system.file_system_id, # The logical ID of the Access Point to use. # This is a string, not an ARN. authorization_config=ecs.AuthorizationConfig( access_point_id=access_point.access_point_id, iam='ENABLED', ), transit_encryption='ENABLED', )

三个要点:

  1. file_system_id传的是文件系统ID 字符串;access_point_id同样是字符串而非 ARN(源码注释也特别强调了这一点),这是 CloudFormationEFSVolumeConfiguration的原生要求;
  2. authorization_config中iam='ENABLED'表示启用 IAM 授权,此时访问控制由任务角色的 EFS 客户端权限决定;
  3. transit_encryption='ENABLED'强制 NFS 数据在传输过程中加密(要求客户端支持 TLS 挂载,Fargate 原生支持)。

3.4 任务角色与 IAM 策略

Fargate 任务要挂载 EFS,任务角色必须持有 EFS 客户端权限。示例先创建了一个带信任条件限制的 IAM 角色(app.py):

task_role = iam.Role( self, PREFIX + 'EcsTaskRole', assumed_by=iam.ServicePrincipal('ecs-tasks.amazonaws.com').with_conditions({ "StringEquals": { "aws:SourceAccount": Stack.of(self).account }, "ArnLike": { "aws:SourceArn": "arn:aws:ecs:" + Stack.of(self).region + ":" + Stack.of(self).account + ":*" }, }), )

aws:SourceAccount/aws:SourceArn条件用于防止"凭证混淆"攻击——只允许本账户、本区域的 ECS 服务使用该角色。随后附加的内联策略分两段:

iam.PolicyStatement( effect=iam.Effect.ALLOW, resources=['*'], actions=[ "ecr:GetAuthorizationToken", "ec2:DescribeAvailabilityZones" ] ), iam.PolicyStatement( sid='AllowEfsAccess', effect=iam.Effect.ALLOW, resources=['*'], actions=[ 'elasticfilesystem:ClientRootAccess', 'elasticfilesystem:ClientWrite', 'elasticfilesystem:ClientMount', 'elasticfilesystem:DescribeMountTargets' ] )

前两条是 Fargate 拉取镜像、解析可用区的基础权限;AllowEfsAccess四条Client*权限则是 EFS 挂载的最小权限组合(ClientRootAccess授予根目录访问,ClientMount+ClientWrite允许挂载与写入,DescribeMountTargets让任务发现挂载点位置)。

3.5 任务定义:卷、挂载点与容器

task_definition = ecs.FargateTaskDefinition( self, PREFIX + 'FargateTaskDef', task_role=task_role, ) task_definition.add_volume( name=VOLUME_NAME, efs_volume_configuration=efs_volume_configuration, ) mount_point = ecs.MountPoint( container_path=APP_PATH + VOLUME_NAME, source_volume=VOLUME_NAME, read_only=False, ) port_mapping = ecs.PortMapping( container_port=80, host_port=80, protocol=ecs.Protocol.TCP, ) container = ecs.ContainerDefinition( self, 'ecs-cdk-sample-container', task_definition=task_definition, image=ecs.ContainerImage.from_registry('amazon/amazon-ecs-sample'), logging=ecs.LogDrivers.aws_logs( stream_prefix='cdk-ecs-sample', log_retention=logs.RetentionDays.ONE_MONTH, ) ) container.add_mount_points(mount_point) container.add_port_mappings(port_mapping)

要点解读:

  • add_volume声明任务级卷,卷名cdk-ecs-sample-efs-volume是后续挂载点引用的键;
  • 容器路径为APP_PATH + VOLUME_NAME,即容器内 EFS 内容出现在/var/www/cdk-ecs-sample-efs-volume,read_only=False表示可写——这正是"共享存储"的价值:多个 Fargate 任务实例读写同一份数据;
  • 容器使用官方演示镜像amazon/amazon-ecs-sample(返回简单 JSON 的健康检查负载),监听 80 端口,日志走 CloudWatch Logs 并保留一个月。

3.6 服务编排:ApplicationLoadBalancedFargateService 模式

fargate_service = ecs_patterns.ApplicationLoadBalancedFargateService( self, PREFIX + 'Service', cluster=ecs_cluster, desired_count=1, task_definition=task_definition, task_subnets=ec2.SubnetSelection( subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS, ), platform_version=ecs.FargatePlatformVersion.LATEST, public_load_balancer=True, enable_execute_command=True, enable_ecs_managed_tags=True, )

这里复用了自定义任务定义(而不是通过task_image_options让模式新建),因为 EFS 卷必须预先声明在任务定义中。参数含义:

  • task_subnets限定任务只调度到私有子网(带 NAT 出口),保持 ECS 最佳实践——计算节点不直接暴露公网,入口流量由 ALB 承接;
  • public_load_balancer=True创建公网 ALB 并自动完成监听器、目标组、健康检查与容器端口的对接(对应前文的 80 端口映射);
  • enable_execute_command=True开启 ECS Exec,可远程进入容器调试挂载问题;
  • enable_ecs_managed_tags=True开启 ECS 托管标签。

3.7 安全组与自动扩缩容

EFS 挂载依赖 NFS 协议,默认端口 2049/TCP,因此需要双向放通(app.py):

# 允许 ECS 服务访问 EFS fargate_service.service.connections.allow_from(file_system, ec2.Port.tcp(2049)) # 允许 EFS 访问 ECS 服务 fargate_service.service.connections.allow_to(file_system, ec2.Port.tcp(2049))

最后配置应用自动扩缩容:

scalable_target = fargate_service.service.auto_scale_task_count( min_capacity=1, max_capacity=20, ) scalable_target.scale_on_cpu_utilization("CpuScaling", target_utilization_percent=50) scalable_target.scale_on_memory_utilization("MemoryScaling", target_utilization_percent=50)

服务维持在 1~20 个任务之间,当任务集平均 CPU 或内存任一维度超过 50% 时扩容,低于目标时缩容。这与仓库内姊妹示例 fargate-service-with-autoscaling 的扩缩容思路一致,可对照学习。

四、部署后验证

部署成功后可按 README 的验证清单在控制台核对三类资源(<Unique ID>为 CDK 为每个资源生成的唯一后缀,与 Stack ID 后缀一致):

  1. ECS 集群:名称形如AWS-CDK-Fargate-efssampleCluster<Unique ID>;
  2. EFS 文件系统:名称形如AWS-CDK-Fargate-/efs-sample-EFS(<Unique ID>);
  3. Application Load Balancer:名称形如AWS-CD-efssa--<Unique ID>。

拿到 ALB 的 DNS 名称后直接访问,amazon/amazon-ecs-sample镜像会返回一段 JSON 负载,证明"公网 ALB → Fargate 任务 → 80 端口容器"链路连通;进一步可在容器内执行ls /var/www/cdk-ecs-sample-efs-volume验证 EFS 挂载生效,并在多个任务实例间互相写入文件以确认共享语义。

五、适用前提与关键结论

从 requirements.txt 与 cdk.json 看,该示例要求 CDK v2 环境(aws-cdk-lib 2.x、constructs 10.x),部署前需完成cdk bootstrap。这个样本浓缩了 Fargate + EFS 集成的最小可行骨架,核心链路为:

FileSystem + AccessPoint → EfsVolumeConfiguration(IAM 鉴权 + 传输加密)→ 任务定义 add_volume → 容器 MountPoint → 2049 端口安全组 → ALB 前置的 Fargate 服务 → CPU/内存双指标扩缩容。

理解这条链路后,即可将其替换为自己的业务镜像与容器路径,落地"无服务器计算 + 共享存储"的组合;若还需控制 EFS 的访问权限边界,可参考 cdk.json 中已启用的@aws-cdk/aws-efs:denyAnonymousAccess等上下文开关所对应的安全默认行为。

【免费下载链接】aws-cdk-examples

Example projects using the AWS CDK

项目地址:https://gitcode.com/gh_mirrors/aw/aws-cdk-examples
点击查看免费下载
上一篇:Scrapegraph-AI项目中的Ollama模型上下文长度配置优化
下一篇:all-in-rag 菜谱数据实战:香煎五花肉的标准化菜谱结构与 RAG 数据预处理解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/21 6:13:45

市面上有哪些是真正无痕改写的降AI率平台(规避AIGC机器检测)

本篇结合全网实测数据&#xff0c;精选千笔AI、笔捷 AI、豆包、DeepSeek、QuillBot、StealthWriter共 6 款主流工具&#xff0c;重点对比降 AI 率真实效果、降重能力、学术合规、免费权益、适配场景&#xff0c;附完整对比表格&#xff0c;告诉你哪些是真好用、哪些是智商税&am…

作者头像 李华
网站建设 2026/10/21 9:27:34

属于一个人的数字管家:个人生活自动化脚本工具包全景复盘

十月十四日的夜色深沉&#xff0c;秋虫在窗台外发出细微的鸣唱。我端着一杯温热的麦茶&#xff0c;在终端里敲下一条命令&#xff1a;tree ~/scripts -L 1。 屏幕上整整齐齐地列出了七个小巧的 Python 脚本文件。没有复杂的工程脚手架&#xff0c;没有深不见底的依赖树&#xf…

作者头像 李华
网站建设 2026/10/20 22:26:55

RealVNC嵌入式远程调试实战:低延迟Framebuffer直通与无GUI部署

简介&#xff1a;本资源为RealVNC远程连接工具Windows平台部署包&#xff0c;面向IT运维人员、远程办公用户及系统管理员&#xff0c;解决跨设备桌面控制、远程技术支持与多系统协同管理等实际问题。压缩包共2个文件&#xff08;1个ZIP安装包 1个HTM说明文档&#xff09;&…

作者头像 李华
网站建设 2026/10/20 17:53:22

软考 系统架构设计师历年真题集萃(66)

接前一篇文章:软考 系统架构设计师系列知识点之杂项集萃(65) 第106题 一般说来,SoC称为系统级芯片,也称片上系统,它是一个有专用目标的集成电路产品。以下关于SoC不正确的说法是()。 A. SoC是一种技术,是以实际的、确定的系统功能开始,到软/硬件划分,并完成设计的…

作者头像 李华