拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

AWS实战指南:从EC2到Lambda的云架构落地与避坑

AWS实战指南:从EC2到Lambda的云架构落地与避坑 简介这是一部系统讲解Amazon Web Services的实战指南第三版面向云计算工程师、架构师及开发者适合希望从零搭建云架构、快速上手AWS核心服务的读者。书中从计算、网络、存储到部署与安全管理覆盖EC2、Lambda、VPC、CloudFormation、IAM等常用服务并给出了服务速查表与章节索引方便按业务场景快速定位同时配有可运行的练习代码和架构示意图帮助读者在接近真实的环境中理解无服务器、容器编排、基础设施即代码等重点技术。书中还演示了如何组合这些服务构建高可用、可扩展的应用架构并给出成本估算与安全合规方面的实用建议。资源为单个PDF文件大小约35.27MB包含完整目录与英文正文目录层级分明适合按需精读或系统学习。目前已有73人学习浏览内容兼顾概念讲解与动手实践既可作为AWS入门路线图也能为中级开发者补齐自动化部署、网络安全组配置、成本控制等实践细节是一份高信息密度的英文原版参考手册。1. Amazon Web Services 在 2023 年这本英文实战书到底教了什么拿到《Amazon Web Services in Action 3rd Edition》这个标题大部分人的第一反应是又一本 AWS 官方手册我刚开始也这么以为直到照着目录走了一遍才发现它跟你想象中的“文档合集”完全是两码事。第三版更新了 2023 年前后 AWS 主推的服务形态从容器编排到无服务器再到基础设施即代码几乎覆盖了你在生产环境里真正会用到的那套东西。它不是给你背服务名而是带着你从零把架构搭起来——EC2、VPC、负载均衡、Lambda每一步都有可执行的命令和配置。适合谁适合已经厌倦了“看文档都会、一上手就废”的开发者也适合准备从传统机房迁移到云上、但不知道第一脚该往哪儿踩的运维。读这本书的正确姿势不是翻是照着敲。你能获得的不是知识点是一条完整的、踩过坑的落地路径。2. AWS 动手前的三件大事账号体系、预算边界和区域选型2.1 root 用户和 IAM 的坑别用根账号跑日常操作很多人注册完 AWS 就拿着 root 账号一路点下去图省事。这在个人实验环境里问题不大一旦进入团队协作或生产环境root 账号的权限大到没有后悔药——API key 泄露、误删资源、账单爆炸全都跟它有关。第三版里强调的第一条安全实践就是用 root 账号只做一件事——创建 IAM 用户然后锁起来。# 用 AWS CLI 创建 IAM 用户需要先配置好 root 的 access key aws iam create-user --user-name deployer # 给用户附加托管策略这里是管理员权限实际生产建议按需给最小权限 aws iam attach-user-policy \ --user-name deployer \ --policy-arn arn:aws:iam::aws:policy/AdministratorAccess # 创建访问密钥输出里的 AccessKeyId 和 SecretAccessKey 要保存好只显示这一次 aws iam create-access-key --user-name deployer # 配置本地 CLI 使用该用户 aws configure --profile deployer这段命令的逻辑是先建人再授权再发钥匙。attach-user-policy挂的是 AWS 托管策略省去自己写 JSON 权限文档的麻烦但 AdministratorAccess 这种权限在生产环境要谨慎它意味着这个用户能删掉整个账号下所有资源。实际项目中我一般会给不同的角色拆细粒度策略比如给 CI/CD 系统只挂AmazonEC2FullAccess和AmazonS3FullAccess不给全量权限。还有一个容易踩的细节IAM 用户创建的 access key 不会二次显示关闭终端就等于永久丢失只能删了重建。所以保存密钥这件事值得你用密码管理器而不是记事本。2.2 预算告警让 AWS 在你破产之前先通知你AWS 计费最大的特点就是后付费资源开着就计费关掉才停。新手最容易在 EC2 实例上翻车开了一台m5.xlarge忘了关一个月下来几百美金没了。第三版里给的方案是 Billing Conductor 和 Cost Explorer其实最实用的还是 Budgets——它能做到接近实时的告警。# 创建月度预算金额设为 100 美元 aws budgets create-budget \ --account-id 123456789012 \ --budget { BudgetName: monthly-100, BudgetLimit: {Amount: 100, Unit: USD}, TimeUnit: MONTHLY, BudgetType: COST } # 配置告警阈值超过预算的 80% 就发邮件到你的邮箱 aws budgets create-notification \ --account-id 123456789012 \ --budget-name monthly-100 \ --notification {NotificationType: ACTUAL, ComparisonOperator: GREATER_THAN, Threshold: 80, ThresholdType: PERCENTAGE} \ --subscribers [{SubscriptionType: EMAIL, Address: youexample.com}]这段命令值钱的地方在于Threshold: 80这个参数——不要等 100% 才告警那时候你已经超支了。我一般的做法是设两道线80% 警告一次100% 再警告一次。另外NotificationType用ACTUAL表示实际产生费用时触发还有一种是FORECASTED基于预测触发适合对成本敏感的场景。预算告警不是可有可无的配置它是你所有实验室操作的安全网。2.3 区域选型延迟、价格和功能三重博弈区域选择是 AWS 实操里第一个真正影响架构的决策点。us-east-1便宜功能全新服务基本首发就是它ap-southeast-1新加坡离国内近延迟低但部分服务价格贵 10%-20%eu-central-1法兰克福适合欧洲业务合规要求多。第三版里的建议是把区域当成架构参数而不是随意选项。# 查看当前区域的可用区 aws ec2 describe-availability-zones --region us-east-1 # 查看某区域的具体价格以 t3.micro 为例 aws pricing get-products \ --service-code AmazonEC2 \ --filters [{Type: TERM_MATCH, Field: instanceType, Value: t3.micro}]describe-availability-zones告诉你有几个可用区这在设计高可用架构时直接决定你能跨几个故障域。get-products接口查价格但注意它返回的是列表价格实际账单还要考虑 Savings Plans 和 Spot 折扣。选区域没有银弹我的习惯是面向全球用户选us-east-1面向亚太选ap-southeast-1如果业务有合规要求直接查 AWS 的区域合规白皮书再定。别在这个问题上花太多时间选错了后面可以通过多区域架构迁移但成本是实打实的。3. 用 EC2 和 VPC 搭最小可用架构命令行完整走一遍3.1 安全组设计出站入站规则里的大学问EC2 实例本身是个虚拟机但它的安全边界完全由安全组Security Group决定。安全组是有状态的——你允许了入站 80 端口那么从实例发出的响应流量会自动允许不用额外配出站规则。这是新手最容易忽略的点也是防火墙和它最大的区别。# 创建一个安全组指定 VPC 和描述 aws ec2 create-security-group \ --group-name web-sg \ --description Security group for web servers \ --vpc-id vpc-0a1b2c3d4e5f67890 # 允许 80 端口入站来源限定为本安全组即 SG 内互相访问 aws ec2 authorize-security-group-ingress \ --group-name web-sg \ --protocol tcp \ --port 80 \ --source-group sg-0a1b2c3d4e5f67890 # 允许 22 端口入站来源限定特定 IP——生产环境千万别设 0.0.0.0/0 aws ec2 authorize-security-group-ingress \ --group-name web-sg \ --protocol tcp \ --port 22 \ --cidr 203.0.113.0/32这里有两个关键设计一个是 80 端口的安全组嵌套——来源不是 IP 而是另一个安全组这样后面新增实例只要挂同一个安全组就能互相访问不用改规则另一个是 22 端口的 IP 白名单——用/32精确到单个 IP而不是/0开放所有来源。安全组规则是即时生效的改完不需要重启实例这在排查问题时帮了大忙。要注意的是规则数量上限——单个安全组默认最多 60 条入站加 60 条出站超过就要拆分多个安全组。3.2 从 AMI 到实例User Data 和 Tag 的妙用选 AMIAmazon Machine Image是启动实例最关键的一步。第三版里的建议相当朴素除非有特殊的内核需求否则优先选 Amazon Linux 2023因为它和 AWS 的集成度最高SSM 代理、CloudWatch 代理都是预装的省去了手工安装的环节。# 找到最新的 Amazon Linux 2023 AMI ID aws ec2 describe-images \ --owners amazon \ --filters Namename,Valuesal2023-ami-2023.*-x86_64 \ --query sort_by(Images, CreationDate)[-1].ImageId \ --output text # 启动实例挂载安全组注入 User Data aws ec2 run-instances \ --image-id ami-0abcdef1234567890 \ --instance-type t3.micro \ --key-name my-keypair \ --security-group-ids sg-0a1b2c3d4e5f67890 \ --subnet-id subnet-0a1b2c3d4e5f67890 \ --user-data file://user-data.sh \ --tag-specifications ResourceTypeinstance,Tags[{KeyName,Valueweb-server-1},{KeyEnvironment,Valueprod}]User Data 是很多新手看不懂的部分。它的作用是在实例第一次启动时执行一段 shell 脚本——安装软件、拉代码、启动服务全部自动完成。配合 AMI你能做到服务器一开机就处于可用状态而不是手动 SSH 上去敲一串命令。Tag 是 AWS 的资源管理核心Name和Environment是约定俗成的必备键后续你用aws ec2 describe-instances --filters Nametag:Environment,Valuesprod就能把所有生产实例筛出来批量操作。没有 Tag 的资源在 AWS 里就是黑匣子——账单查不清楚资源找不着运维全靠猜。3.3 固定 IP 的三种方案Public IP、EIP 和负载均衡EC2 实例默认拿到的是动态公网 IP——重启就变这在测试环境还能忍生产环境绝对不行。第三版讲了三种固定访问的方式适用场景完全不同。第一种是 Elastic IPEIP一个静态公网 IP 绑到实例上。注意 EIP 是收费的——绑着运行的实例免费但绑着停机的实例或空置的 EIP 每小时收费。第二种是负载均衡器由 AWS 托管入口 IP后面挂多台实例这个最贴近生产。第三种最容易被忽略——NAT Gateway 私有子网实例本身不暴露公网 IP只通过 NAT 出站访问互联网。# 分配一个 Elastic IP aws ec2 allocate-address --domain vpc # 把它绑到实例上这里拿到的是 AllocationId aws ec2 associate-address \ --allocation-id eipalloc-0a1b2c3d4e5f67890 \ --instance-id i-0a1b2c3d4e5f67890 # 创建 Application Load Balancer绑定两个子网 aws elbv2 create-load-balancer \ --name prod-alb \ --subnets subnet-0a1b2c3d4e5f67891 subnet-0a1b2c3d4e5f67892 \ --security-groups sg-0a1b2c3d4e5f67890我的建议很简单单机实验用 EIP生产环境直接上 ALB。EIP 的坑在于它跟实例强绑定实例挂了 IP 也救不回来虽然可以重新关联到新实例但中间有短暂空窗。ALB 是托管服务自动做健康检查、流量分发、证书卸载你用它的理由不是省事而是高可用——挂一台实例在 ALB 后面实例 3 分钟内被替换访问不受影响。3.4 存储选型EBS 的 io2 和 gp3 到底差在哪EBS 是 EC2 的块存储类似虚拟机磁盘。第三版给了三种主流卷类型的定位gp3是默认选择性价比高io2是高性能场景主打极低延迟st1是冷数据存储吞吐优先。新手最常犯的错误是盲目选io1/io2以为 IOPS 越高越好结果账单翻了几倍性能却没什么差别。# 创建 100GB 的 gp3 卷默认 3000 IOPS 和 125 MB/s 吞吐 aws ec2 create-volume \ --volume-type gp3 \ --size 100 \ --availability-zone us-east-1a # 创建 100GB 的 io2 卷预置 10000 IOPS aws ec2 create-volume \ --volume-type io2 \ --size 100 \ --iops 10000 \ --availability-zone us-east-1agp3 最大的优势是 IOPS 和吞吐可以独立调整——你把 IOPS 从 3000 调到 10000价格涨幅远小于换类型。而 io2 的 IOPS 是预置的不管你用不用都计费。选型逻辑挺直接跑数据库或延迟敏感应用选 io2普通 Web 服务选 gp3日志归档选 st1。另有个参数容易忽视——AvailabilityZone必须跟实例在同一个可用区否则挂载失败。这不是 AWS 的限制所有云平台的块存储都这样跨可用区得用其他方案。4. 从服务器到无服务器Lambda 和 API Gateway 的真实落地路径4.1 Lambda 函数的基本结构handler、事件和返回值Lambda 把服务器抽象掉了你不用管操作系统、补丁、扩容写的代码直接跑在 AWS 托管的运行时里。第三版花了相当篇幅讲这个——不是因为 Lambda 是新东西而是因为它确实改变了应用的部署方式。用 Lambda 写接口你的思维要从「启动一个进程监听端口」切换到「一个函数被事件触发然后结束」。// index.js — 一个最简单的 Lambda 函数 exports.handler async (event, context) { // 从 API Gateway 传来的事件里取出查询参数 const name event.queryStringParameters?event.queryStringParameters.name : World; // 返回值就是 HTTP 响应的样子 return { statusCode: 200, headers: {Content-Type: application/json}, body: JSON.stringify({ message: Hello, ${name}! }) }; };这个 handler 的结构是 AWS Lambda 的固定约定event是输入数据context是运行时信息返回值即响应。你不需要监听任何端口也不需要处理 TCP 连接——这些全部由 Lambda 运行时搞定。函数执行完环境会冻结下次调用再解冻。理解了这个生命周期你就明白了为什么 Lambda 不适合跑长连接——你的代码超过执行超时就被杀掉默认 3 秒最长可以调到 15 分钟。也明白了为什么冷启动会成为性能瓶颈——第一次调用时环境要先初始化延迟会明显变高。4.2 用 SAM 模板把 Lambda 部署到线上一条命令的事写 Lambda 只是开始要把它变成一个真正的 HTTP 接口需要 API Gateway、IAM 角色、日志权限——手动在控制台点要 20 分钟用 AWS SAMServerless Application Model可以压缩到一条命令。# template.yaml — SAM 模板定义 Lambda 和 API Gateway AWSTemplateFormatVersion: 2010-09-09 Transform: AWS::Serverless-2016-10-31 Resources: HelloFunction: Type: AWS::Serverless::Function Properties: CodeUri: ./ Handler: index.handler Runtime: nodejs20.x Events: HelloApi: Type: Api Properties: Path: /hello Method: get# 用 SAM 构建并部署--guided 会让你交互式确认参数 sam build sam deploy --guided这段模板声明了一个 Lambda 函数然后声明了一个 API 事件——Path: /hello和Method: get意味着 API Gateway 会自动创建/hello的 GET 接口把请求转给 Lambda。sam build负责把本地代码打包成部署产物sam deploy负责创建所有云资源。这套模式最大的价值不是省那 20 分钟而是可重复——你的基础设施变成了一堆代码环境的每次变更都有迹可循删掉整套环境也是一条命令的事。还有一个细节sam deploy --guided会让你设置堆栈名和确认 IAM 权限如果没有加--capabilities CAPABILITY_IAM部署会失败——这是 SAM 最常见的报错之一新手遇到会以为是代码问题其实只是缺了一个权限参数。4.3 API Gateway 的四个必调参数超时、限流、CORS 和二进制API Gateway 在无服务器架构里扮演入口角色但默认配置在生产环境基本不可用。第三版里点到几个必调的参数我做 Lambda 接口时的经验也是围绕这几个坑展开的。第一个是超时。API Gateway 默认的集成超时是 29 秒如果你后面挂的 Lambda 运行超过这个时间返回 504。第二个是限流。不配限流意味着你的接口暴露在公网上被脚本刷一下就可能导致账单飙升。第三个是 CORS跨域资源共享。前后端分离的项目里前端域名和 API 域名不一样浏览器会拦截跨域请求。第四个是二进制负载。API Gateway 默认按文本处理请求上传图片或文件时要用binaryMediaTypes声明。# 创建限流用的 usage plan每秒 10 个请求突发 20 个 aws apigateway create-usage-plan \ --name basic-plan \ --throttle {burstLimit: 20, rateLimit: 10} # 开启 CORS允许所有来源允许常用方法 aws apigateway update-stage \ --rest-api-id a1b2c3d4e5 \ --stage-name prod \ --patch-operations \ opreplace,path/settings/propagationEnabled,valuetrue限流的rateLimit是每秒的稳定速率burstLimit是瞬时爆发容量——这两个值要按你的业务量评估设小了会误杀正常用户设大了等于没设。CORS 配置在第三版里反复强调因为它的报错信息相当迷惑——浏览器报「CORS policy: No Access-Control-Allow-Origin header」第一反应是后端代码的问题实际上需要在 API Gateway 这边配置响应头。5. 避坑AWS 实战里最容易翻车的 6 个细节5.1 数据持久化陷阱实例停机被终止数据全没了现象一台 EC2 实例关机再开机SSH 登录上去发现/home下新装的文件全没了——不是被重置是整个实例被终止了。原因启动实例时勾选了「Delete on Termination」属性默认勾选意味着实例终止时根卷跟着销毁。如果你用 Spot 实例这个风险还要再放大——Spot 实例被回收时会直接终止实例没有「先通知后停机」的缓冲。解决把数据放在独立 EBS 卷实例和卷分开管理或 S3 里。EBS 卷默认不随实例删除但需要专门把DeleteOnTermination设为 false。# 查看根卷的删除属性 aws ec2 describe-instances \ --instance-id i-0a1b2c3d4e5f67890 \ --query Reservations[0].Instances[0].BlockDeviceMappings # 修改根卷的 DeleteOnTermination 为 false先分离再修改最后重新挂载 aws ec2 modify-instance-attribute \ --instance-id i-0a1b2c3d4e5f67890 \ --block-device-mappings [{DeviceName: /dev/xvda, Ebs: {DeleteOnTermination: false}}]这是一个老生常谈但永远有人踩的坑。根卷的DeleteOnTermination默认 true 是有设计考量的——让临时服务器销毁时不留残留。但所有重要的数据、配置、日志放在根卷都是不安全的。第三版的建议是根卷只放操作系统应用和数据全部放在独立卷或对象存储里。5.2 跨区域折腾数据带宽费比存储费贵得多现象开了一个新区域想迁移数据把原来区域里的 S3 文件用aws s3 cp --recursive直接拷到新区域月底账单惊掉下巴——传输费比存储费贵了 3 倍。原因S3 的跨区域复制或手动传输会收取数据传输费大约 $0.02/GB出口到互联网则更贵$0.09/GB。你没做任何操作光从us-east-1传到ap-southeast-1100GB就要花 2 美元——听起来不多但 TB 级数据就是 20 美元的差距加上请求费用和 S3 自身的读写费用累计起来相当可观。解决用 S3 的SameRegionReplication做同区域复制用 S3 Batch Operations 做批量迁移而不是脚本直传。真正大规模跨区域迁移用 AWS DataSync 或 Snowball 设备。5.3 权限追踪靠猜AWS 里最贵的一句话是「刚才谁动的」现象团队里有人误删了生产数据库问起来所有人都说「不是我」。原因没开 CloudTrail 或开了但不看日志。CloudTrail 默认记录过去 90 天的管理事件但如果你在控制台手动关闭过这段历史就没了。解决立刻开启 CloudTrail 并配置日志投递到 S3用 Athena 查日志。-- 用 Athena 查过去 24 小时的 DeleteDBInstance 操作 SELECT eventTime, userIdentity.userName, eventName, errorMessage FROM cloudtrail_logs WHERE eventName DeleteDBInstance AND eventTime date_add(day, -1, now()) ORDER BY eventTime DESC;这一招在「事故复盘」时价值千金。CloudTrail 日志默认存在 S3 里直接查没法查——因为它是 JSON 格式得先用 Athena 建表。Athena 是按扫描量计费的建议加上分区按年/月/日分区再建表不然全表扫描的费用也会成为新的账单事故。5.4 IAM 策略太长导致「策略大小超出限制」现象写了一个复杂的 IAM 策略应用时aws iam put-role-policy报错PolicySizeExceededException。原因单个 IAM 策略的最大长度是 6144 字节托管策略最长 10240 字节。列了一堆资源 ARN 和条件关键字很容易超限。解决拆成多个策略。IAM 角色支持挂多个策略内联策略的大小限制比托管策略更严格所以优先用托管策略。如果同一个角色要访问多个服务的不同资源策略拆分是标准做法。# 创建一个精简的 S3 访问策略避免把所有桶都写进一个策略 aws iam create-policy \ --policy-name app-s3-access \ --policy-document { Version: 2012-10-17, Statement: [ {Effect: Allow, Action: s3:GetObject, Resource: arn:aws:s3:::app-assets/*}, {Effect: Allow, Action: s3:ListBucket, Resource: arn:aws:s3:::app-assets} ] }5.5 一键删除的幻觉CloudFormation 删除堆栈时把数据也带走了现象用 CloudFormation 部署了一套环境测试完觉得没用了执行删除堆栈然后发现 S3 桶里的历史数据也全没了——堆栈删除默认会删除桶里的所有对象而不是只删桶本身。原因CloudFormation 删除堆栈时对 S3 桶的默认行为是强制删除——不管桶里有没有数据直接清除。你以为是删了个空桶实际上是连带数据一起删。解决给 S3 桶加DeletionPolicy: Retain或者设置DeletionPolicy: Snapshot适用于数据库这样堆栈删了数据还在只是变成了孤儿资源需要手动清理。是麻烦但比数据永久消失强一万倍。# template.yaml 片段保留 S3 桶数据不让删除堆栈时连带删掉 Resources: DataBucket: Type: AWS::S3::Bucket DeletionPolicy: Retain5.6 EC2 实例启动慢其实是元数据服务在拖后腿现象同一套 AMI在us-east-1启动只要 30 秒在某个区域要 3 分钟网络也时好时差。原因EC2 实例启动时需要通过 Instance Metadata ServiceIMDS获取密钥、网络配置等信息。某些区域 IMDS 的响应慢导致启动流程卡住。解决改用 IMDSv2强制版本并给实例设置较长的恢复等待时间。如果是 T 系列实例t3/t4g查看是否触发了 CPU 积分耗尽——积分用完性能直接掉到基准以下。# 查看实例的 CPU 积分余额 aws ec2 describe-instances \ --instance-id i-0a1b2c3d4e5f67890 \ --query Reservations[0].Instances[0].CpuOptions6. 把基础设施写成代码用 CDK 管理这套环境的实战技巧6.1 为什么用 CDK 而不是 CloudFormation YAML第三版从 CloudFormation 讲到 CDK这个演进很多人还没来得及接受。CloudFormation 用 YAML/JSON 描述资源工作了但体验一般——YAML 没有类型检查、没有自动补全、复用逻辑得靠嵌套模板或宏改一个参数要在多个文件里找。CDKCloud Development Kit允许你用 TypeScript/JavaScript/Python以及 Java、C# 等写基础设施本质上是把 CloudFormation 模板变成代码生成器。有 IDE 补全和类型系统写错属性名在编译期就报错不用等部署失败可以用变量、循环、函数组合资源应付复杂的重复性资源提供构造库Construct Library封装高层模式比如「一个负载均衡 两个 EC2」这种代码写成一行// cdk-app.ts — 用 TypeScript 定义一个包含 VPC、EC2、安全组的应用 import * as cdk from aws-cdk-lib; import * as ec2 from aws-cdk-lib/aws-ec2; export class MyStack extends cdk.Stack { constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { super(scope, id, props); const vpc new ec2.Vpc(this, MyVpc, { maxAzs: 2, natGateways: 1 }); const securityGroup new ec2.SecurityGroup(this, WebSG, { vpc, description: Allow web traffic, allowAllOutbound: true }); securityGroup.addIngressRule( ec2.Peer.anyIpv4(), ec2.Port.tcp(80), Allow HTTP from anywhere ); const instance new ec2.Instance(this, WebServer, { vpc, instanceType: ec2.InstanceType.of(ec2.InstanceClass.T3, ec2.InstanceSize.MICRO), machineImage: ec2.MachineImage.latestAmazonLinux2023(), securityGroup }); } } const app new cdk.App(); new MyStack(app, MyCdkStack);# 部署 CDK 应用 cdk bootstrap cdk deployCDK 代码里最重要的几个对象Vpc会默认创建包含两个可用区的完整网络环境——公有子网、私有子网、NAT 网关、路由表全部自动化。SecurityGroup的addIngressRule在 YAML 里对应好几行配置这里一行就完成了。ec2.Instance则自动帮你创建实例、挂载安全组、分配存储。6.2 本地模拟与快速验证CDK 的 Test 功能不是摆设CDK 有一个被低估的能力——单元测试。它能把基础设施的「预期状态」写进断言在部署之前就验证。第三版虽然没有把这个当重点讲但我实际操作下来这是防止生产事故最有效的工具。// test/my-stack.test.ts — 用 CDK 断言验证资源属性 import { Template } from aws-cdk-lib/assertions; test(Security group allows inbound HTTP, () { const app new cdk.App(); const stack new MyStack(app, TestStack); const template Template.fromStack(stack); template.hasResourceProperties(AWS::EC2::SecurityGroup, { SecurityGroupIngress: [ { IpProtocol: tcp, FromPort: 80, ToPort: 80, CidrIp: 0.0.0.0/0 } ] }); });# 跑测试 npm test这段测试的意义在于安全组规则、VPC 配置、实例类型——所有基础设施的「关键参数」都变成了可断言的代码。当团队里有人改了一个安全组规则或换了一个实例类型测试会立刻告诉你这违反了预期。我跟人协作 AWS 项目的习惯是所有资源变更必须带着测试提交不然不管其他代码测得多好上线大概率出问题。6.3 环境隔离用上下文参数切换 dev、test、prodCDK 在实践中最容易翻车的场景是「测试环境跟生产环境混在一起」。有人图省事所有环境都部署到同一个账号没有做隔离结果测试环境的告警和实验数据污染了生产监控甚至误删了生产资源。我的方案是用 CDK Context 区分环境不同环境用不同账号 不同 VPC。// 在 cdk.json 里定义环境差异 { app: node bin/app.js, context: { dev: { instanceType: t3.micro, natGateways: 0 }, prod: { instanceType: m5.large, natGateways: 2 } } }// bin/app.js — 根据环境读取不同配置 const env process.env.ENV || dev; const config app.node.tryGetContext(env); new MyStack(app, MyStack-${env}, { instanceType: config.instanceType, natGateways: config.natGateways, env: { account: config.account, region: config.region } });# 分别部署不同环境 ENVdev cdk deploy ENVprod cdk deploytryGetContext从cdk.json或命令行参数里读取配置这样同样的代码在不同的环境得到不同的基础设施。dev 环境不需要 NAT 网关因为不需要访问外部网络用natGateways: 0能省掉一大笔费用prod 环境必须双 NAT 保证高可用。这个模式下环境之间的差异被代码显式管理而不是靠「谁记得改了什么参数」——这是我做过太多环境混乱项目之后的血泪经验。基础设施没有后悔药可言但 CDK 的代码化至少让你知道「现在到底有什么、从哪来的、怎么拆掉它」。希望帮到你。本文还有配套的精品资源点击获取
返回列表