指南:從EC2到Lambda的云架構落地與避坑)
簡介這是一部系統(tǒng)講解Amazon Web Services的實戰(zhàn)指南第三版面向云計算工程師、架構師及開發(fā)者適合希望從零搭建云架構、快速上手AWS核心服務的讀者。書中從計算、網(wǎng)絡、存儲到部署與安全管理覆蓋EC2、Lambda、VPC、CloudFormation、IAM等常用服務并給出了服務速查表與章節(jié)索引方便按業(yè)務場景快速定位同時配有可運行的練習代碼和架構示意圖幫助讀者在接近真實的環(huán)境中理解無服務器、容器編排、基礎設施即代碼等重點技術。書中還演示了如何組合這些服務構建高可用、可擴展的應用架構并給出成本估算與安全合規(guī)方面的實用建議。資源為單個PDF文件大小約35.27MB包含完整目錄與英文正文目錄層級分明適合按需精讀或系統(tǒng)學習。目前已有73人學習瀏覽內(nèi)容兼顧概念講解與動手實踐既可作為AWS入門路線圖也能為中級開發(fā)者補齊自動化部署、網(wǎng)絡安全組配置、成本控制等實踐細節(jié)是一份高信息密度的英文原版參考手冊。1. Amazon Web Services 在 2023 年這本英文實戰(zhàn)書到底教了什么拿到《Amazon Web Services in Action 3rd Edition》這個標題大部分人的第一反應是又一本 AWS 官方手冊我剛開始也這么以為直到照著目錄走了一遍才發(fā)現(xiàn)它跟你想象中的“文檔合集”完全是兩碼事。第三版更新了 2023 年前后 AWS 主推的服務形態(tài)從容器編排到無服務器再到基礎設施即代碼幾乎覆蓋了你在生產(chǎn)環(huán)境里真正會用到的那套東西。它不是給你背服務名而是帶著你從零把架構搭起來——EC2、VPC、負載均衡、Lambda每一步都有可執(zhí)行的命令和配置。適合誰適合已經(jīng)厭倦了“看文檔都會、一上手就廢”的開發(fā)者也適合準備從傳統(tǒng)機房遷移到云上、但不知道第一腳該往哪兒踩的運維。讀這本書的正確姿勢不是翻是照著敲。你能獲得的不是知識點是一條完整的、踩過坑的落地路徑。2. AWS 動手前的三件大事賬號體系、預算邊界和區(qū)域選型2.1 root 用戶和 IAM 的坑別用根賬號跑日常操作很多人注冊完 AWS 就拿著 root 賬號一路點下去圖省事。這在個人實驗環(huán)境里問題不大一旦進入團隊協(xié)作或生產(chǎn)環(huán)境root 賬號的權限大到?jīng)]有后悔藥——API key 泄露、誤刪資源、賬單爆炸全都跟它有關。第三版里強調的第一條安全實踐就是用 root 賬號只做一件事——創(chuàng)建 IAM 用戶然后鎖起來。# 用 AWS CLI 創(chuàng)建 IAM 用戶需要先配置好 root 的 access key aws iam create-user --user-name deployer # 給用戶附加托管策略這里是管理員權限實際生產(chǎn)建議按需給最小權限 aws iam attach-user-policy \ --user-name deployer \ --policy-arn arn:aws:iam::aws:policy/AdministratorAccess # 創(chuàng)建訪問密鑰輸出里的 AccessKeyId 和 SecretAccessKey 要保存好只顯示這一次 aws iam create-access-key --user-name deployer # 配置本地 CLI 使用該用戶 aws configure --profile deployer這段命令的邏輯是先建人再授權再發(fā)鑰匙。attach-user-policy掛的是 AWS 托管策略省去自己寫 JSON 權限文檔的麻煩但 AdministratorAccess 這種權限在生產(chǎn)環(huán)境要謹慎它意味著這個用戶能刪掉整個賬號下所有資源。實際項目中我一般會給不同的角色拆細粒度策略比如給 CI/CD 系統(tǒng)只掛AmazonEC2FullAccess和AmazonS3FullAccess不給全量權限。還有一個容易踩的細節(jié)IAM 用戶創(chuàng)建的 access key 不會二次顯示關閉終端就等于永久丟失只能刪了重建。所以保存密鑰這件事值得你用密碼管理器而不是記事本。2.2 預算告警讓 AWS 在你破產(chǎn)之前先通知你AWS 計費最大的特點就是后付費資源開著就計費關掉才停。新手最容易在 EC2 實例上翻車開了一臺m5.xlarge忘了關一個月下來幾百美金沒了。第三版里給的方案是 Billing Conductor 和 Cost Explorer其實最實用的還是 Budgets——它能做到接近實時的告警。# 創(chuàng)建月度預算金額設為 100 美元 aws budgets create-budget \ --account-id 123456789012 \ --budget { BudgetName: monthly-100, BudgetLimit: {Amount: 100, Unit: USD}, TimeUnit: MONTHLY, BudgetType: COST } # 配置告警閾值超過預算的 80% 就發(fā)郵件到你的郵箱 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這個參數(shù)——不要等 100% 才告警那時候你已經(jīng)超支了。我一般的做法是設兩道線80% 警告一次100% 再警告一次。另外NotificationType用ACTUAL表示實際產(chǎn)生費用時觸發(fā)還有一種是FORECASTED基于預測觸發(fā)適合對成本敏感的場景。預算告警不是可有可無的配置它是你所有實驗室操作的安全網(wǎng)。2.3 區(qū)域選型延遲、價格和功能三重博弈區(qū)域選擇是 AWS 實操里第一個真正影響架構的決策點。us-east-1便宜功能全新服務基本首發(fā)就是它ap-southeast-1新加坡離國內(nèi)近延遲低但部分服務價格貴 10%-20%eu-central-1法蘭克福適合歐洲業(yè)務合規(guī)要求多。第三版里的建議是把區(qū)域當成架構參數(shù)而不是隨意選項。# 查看當前區(qū)域的可用區(qū) aws ec2 describe-availability-zones --region us-east-1 # 查看某區(qū)域的具體價格以 t3.micro 為例 aws pricing get-products \ --service-code AmazonEC2 \ --filters [{Type: TERM_MATCH, Field: instanceType, Value: t3.micro}]describe-availability-zones告訴你有幾個可用區(qū)這在設計高可用架構時直接決定你能跨幾個故障域。get-products接口查價格但注意它返回的是列表價格實際賬單還要考慮 Savings Plans 和 Spot 折扣。選區(qū)域沒有銀彈我的習慣是面向全球用戶選us-east-1面向亞太選ap-southeast-1如果業(yè)務有合規(guī)要求直接查 AWS 的區(qū)域合規(guī)白皮書再定。別在這個問題上花太多時間選錯了后面可以通過多區(qū)域架構遷移但成本是實打實的。3. 用 EC2 和 VPC 搭最小可用架構命令行完整走一遍3.1 安全組設計出站入站規(guī)則里的大學問EC2 實例本身是個虛擬機但它的安全邊界完全由安全組Security Group決定。安全組是有狀態(tài)的——你允許了入站 80 端口那么從實例發(fā)出的響應流量會自動允許不用額外配出站規(guī)則。這是新手最容易忽略的點也是防火墻和它最大的區(qū)別。# 創(chuàng)建一個安全組指定 VPC 和描述 aws ec2 create-security-group \ --group-name web-sg \ --description Security group for web servers \ --vpc-id vpc-0a1b2c3d4e5f67890 # 允許 80 端口入站來源限定為本安全組即 SG 內(nèi)互相訪問 aws ec2 authorize-security-group-ingress \ --group-name web-sg \ --protocol tcp \ --port 80 \ --source-group sg-0a1b2c3d4e5f67890 # 允許 22 端口入站來源限定特定 IP——生產(chǎn)環(huán)境千萬別設 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 而是另一個安全組這樣后面新增實例只要掛同一個安全組就能互相訪問不用改規(guī)則另一個是 22 端口的 IP 白名單——用/32精確到單個 IP而不是/0開放所有來源。安全組規(guī)則是即時生效的改完不需要重啟實例這在排查問題時幫了大忙。要注意的是規(guī)則數(shù)量上限——單個安全組默認最多 60 條入站加 60 條出站超過就要拆分多個安全組。3.2 從 AMI 到實例User Data 和 Tag 的妙用選 AMIAmazon Machine Image是啟動實例最關鍵的一步。第三版里的建議相當樸素除非有特殊的內(nèi)核需求否則優(yōu)先選 Amazon Linux 2023因為它和 AWS 的集成度最高SSM 代理、CloudWatch 代理都是預裝的省去了手工安裝的環(huán)節(jié)。# 找到最新的 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 是很多新手看不懂的部分。它的作用是在實例第一次啟動時執(zhí)行一段 shell 腳本——安裝軟件、拉代碼、啟動服務全部自動完成。配合 AMI你能做到服務器一開機就處于可用狀態(tài)而不是手動 SSH 上去敲一串命令。Tag 是 AWS 的資源管理核心Name和Environment是約定俗成的必備鍵后續(xù)你用aws ec2 describe-instances --filters Nametag:Environment,Valuesprod就能把所有生產(chǎn)實例篩出來批量操作。沒有 Tag 的資源在 AWS 里就是黑匣子——賬單查不清楚資源找不著運維全靠猜。3.3 固定 IP 的三種方案Public IP、EIP 和負載均衡EC2 實例默認拿到的是動態(tài)公網(wǎng) IP——重啟就變這在測試環(huán)境還能忍生產(chǎn)環(huán)境絕對不行。第三版講了三種固定訪問的方式適用場景完全不同。第一種是 Elastic IPEIP一個靜態(tài)公網(wǎng) IP 綁到實例上。注意 EIP 是收費的——綁著運行的實例免費但綁著停機的實例或空置的 EIP 每小時收費。第二種是負載均衡器由 AWS 托管入口 IP后面掛多臺實例這個最貼近生產(chǎn)。第三種最容易被忽略——NAT Gateway 私有子網(wǎng)實例本身不暴露公網(wǎng) IP只通過 NAT 出站訪問互聯(lián)網(wǎng)。# 分配一個 Elastic IP aws ec2 allocate-address --domain vpc # 把它綁到實例上這里拿到的是 AllocationId aws ec2 associate-address \ --allocation-id eipalloc-0a1b2c3d4e5f67890 \ --instance-id i-0a1b2c3d4e5f67890 # 創(chuàng)建 Application Load Balancer綁定兩個子網(wǎng) aws elbv2 create-load-balancer \ --name prod-alb \ --subnets subnet-0a1b2c3d4e5f67891 subnet-0a1b2c3d4e5f67892 \ --security-groups sg-0a1b2c3d4e5f67890我的建議很簡單單機實驗用 EIP生產(chǎn)環(huán)境直接上 ALB。EIP 的坑在于它跟實例強綁定實例掛了 IP 也救不回來雖然可以重新關聯(lián)到新實例但中間有短暫空窗。ALB 是托管服務自動做健康檢查、流量分發(fā)、證書卸載你用它的理由不是省事而是高可用——掛一臺實例在 ALB 后面實例 3 分鐘內(nèi)被替換訪問不受影響。3.4 存儲選型EBS 的 io2 和 gp3 到底差在哪EBS 是 EC2 的塊存儲類似虛擬機磁盤。第三版給了三種主流卷類型的定位gp3是默認選擇性價比高io2是高性能場景主打極低延遲st1是冷數(shù)據(jù)存儲吞吐優(yōu)先。新手最常犯的錯誤是盲目選io1/io2以為 IOPS 越高越好結果賬單翻了幾倍性能卻沒什么差別。# 創(chuàng)建 100GB 的 gp3 卷默認 3000 IOPS 和 125 MB/s 吞吐 aws ec2 create-volume \ --volume-type gp3 \ --size 100 \ --availability-zone us-east-1a # 創(chuàng)建 100GB 的 io2 卷預置 10000 IOPS aws ec2 create-volume \ --volume-type io2 \ --size 100 \ --iops 10000 \ --availability-zone us-east-1agp3 最大的優(yōu)勢是 IOPS 和吞吐可以獨立調整——你把 IOPS 從 3000 調到 10000價格漲幅遠小于換類型。而 io2 的 IOPS 是預置的不管你用不用都計費。選型邏輯挺直接跑數(shù)據(jù)庫或延遲敏感應用選 io2普通 Web 服務選 gp3日志歸檔選 st1。另有個參數(shù)容易忽視——AvailabilityZone必須跟實例在同一個可用區(qū)否則掛載失敗。這不是 AWS 的限制所有云平臺的塊存儲都這樣跨可用區(qū)得用其他方案。4. 從服務器到無服務器Lambda 和 API Gateway 的真實落地路徑4.1 Lambda 函數(shù)的基本結構handler、事件和返回值Lambda 把服務器抽象掉了你不用管操作系統(tǒng)、補丁、擴容寫的代碼直接跑在 AWS 托管的運行時里。第三版花了相當篇幅講這個——不是因為 Lambda 是新東西而是因為它確實改變了應用的部署方式。用 Lambda 寫接口你的思維要從「啟動一個進程監(jiān)聽端口」切換到「一個函數(shù)被事件觸發(fā)然后結束」。// index.js — 一個最簡單的 Lambda 函數(shù) exports.handler async (event, context) { // 從 API Gateway 傳來的事件里取出查詢參數(shù) 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是輸入數(shù)據(jù)context是運行時信息返回值即響應。你不需要監(jiān)聽任何端口也不需要處理 TCP 連接——這些全部由 Lambda 運行時搞定。函數(shù)執(zhí)行完環(huán)境會凍結下次調用再解凍。理解了這個生命周期你就明白了為什么 Lambda 不適合跑長連接——你的代碼超過執(zhí)行超時就被殺掉默認 3 秒最長可以調到 15 分鐘。也明白了為什么冷啟動會成為性能瓶頸——第一次調用時環(huán)境要先初始化延遲會明顯變高。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 會讓你交互式確認參數(shù) sam build sam deploy --guided這段模板聲明了一個 Lambda 函數(shù)然后聲明了一個 API 事件——Path: /hello和Method: get意味著 API Gateway 會自動創(chuàng)建/hello的 GET 接口把請求轉給 Lambda。sam build負責把本地代碼打包成部署產(chǎn)物sam deploy負責創(chuàng)建所有云資源。這套模式最大的價值不是省那 20 分鐘而是可重復——你的基礎設施變成了一堆代碼環(huán)境的每次變更都有跡可循刪掉整套環(huán)境也是一條命令的事。還有一個細節(jié)sam deploy --guided會讓你設置堆棧名和確認 IAM 權限如果沒有加--capabilities CAPABILITY_IAM部署會失敗——這是 SAM 最常見的報錯之一新手遇到會以為是代碼問題其實只是缺了一個權限參數(shù)。4.3 API Gateway 的四個必調參數(shù)超時、限流、CORS 和二進制API Gateway 在無服務器架構里扮演入口角色但默認配置在生產(chǎn)環(huán)境基本不可用。第三版里點到幾個必調的參數(shù)我做 Lambda 接口時的經(jīng)驗也是圍繞這幾個坑展開的。第一個是超時。API Gateway 默認的集成超時是 29 秒如果你后面掛的 Lambda 運行超過這個時間返回 504。第二個是限流。不配限流意味著你的接口暴露在公網(wǎng)上被腳本刷一下就可能導致賬單飆升。第三個是 CORS跨域資源共享。前后端分離的項目里前端域名和 API 域名不一樣瀏覽器會攔截跨域請求。第四個是二進制負載。API Gateway 默認按文本處理請求上傳圖片或文件時要用binaryMediaTypes聲明。# 創(chuàng)建限流用的 usage plan每秒 10 個請求突發(fā) 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是每秒的穩(wěn)定速率burstLimit是瞬時爆發(fā)容量——這兩個值要按你的業(yè)務量評估設小了會誤殺正常用戶設大了等于沒設。CORS 配置在第三版里反復強調因為它的報錯信息相當迷惑——瀏覽器報「CORS policy: No Access-Control-Allow-Origin header」第一反應是后端代碼的問題實際上需要在 API Gateway 這邊配置響應頭。5. 避坑AWS 實戰(zhàn)里最容易翻車的 6 個細節(jié)5.1 數(shù)據(jù)持久化陷阱實例停機被終止數(shù)據(jù)全沒了現(xiàn)象一臺 EC2 實例關機再開機SSH 登錄上去發(fā)現(xiàn)/home下新裝的文件全沒了——不是被重置是整個實例被終止了。原因啟動實例時勾選了「Delete on Termination」屬性默認勾選意味著實例終止時根卷跟著銷毀。如果你用 Spot 實例這個風險還要再放大——Spot 實例被回收時會直接終止實例沒有「先通知后停機」的緩沖。解決把數(shù)據(jù)放在獨立 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 是有設計考量的——讓臨時服務器銷毀時不留殘留。但所有重要的數(shù)據(jù)、配置、日志放在根卷都是不安全的。第三版的建議是根卷只放操作系統(tǒng)應用和數(shù)據(jù)全部放在獨立卷或對象存儲里。5.2 跨區(qū)域折騰數(shù)據(jù)帶寬費比存儲費貴得多現(xiàn)象開了一個新區(qū)域想遷移數(shù)據(jù)把原來區(qū)域里的 S3 文件用aws s3 cp --recursive直接拷到新區(qū)域月底賬單驚掉下巴——傳輸費比存儲費貴了 3 倍。原因S3 的跨區(qū)域復制或手動傳輸會收取數(shù)據(jù)傳輸費大約 $0.02/GB出口到互聯(lián)網(wǎng)則更貴$0.09/GB。你沒做任何操作光從us-east-1傳到ap-southeast-1100GB就要花 2 美元——聽起來不多但 TB 級數(shù)據(jù)就是 20 美元的差距加上請求費用和 S3 自身的讀寫費用累計起來相當可觀。解決用 S3 的SameRegionReplication做同區(qū)域復制用 S3 Batch Operations 做批量遷移而不是腳本直傳。真正大規(guī)模跨區(qū)域遷移用 AWS DataSync 或 Snowball 設備。5.3 權限追蹤靠猜AWS 里最貴的一句話是「剛才誰動的」現(xiàn)象團隊里有人誤刪了生產(chǎn)數(shù)據(jù)庫問起來所有人都說「不是我」。原因沒開 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 是按掃描量計費的建議加上分區(qū)按年/月/日分區(qū)再建表不然全表掃描的費用也會成為新的賬單事故。5.4 IAM 策略太長導致「策略大小超出限制」現(xiàn)象寫了一個復雜的 IAM 策略應用時aws iam put-role-policy報錯PolicySizeExceededException。原因單個 IAM 策略的最大長度是 6144 字節(jié)托管策略最長 10240 字節(jié)。列了一堆資源 ARN 和條件關鍵字很容易超限。解決拆成多個策略。IAM 角色支持掛多個策略內(nèi)聯(lián)策略的大小限制比托管策略更嚴格所以優(yōu)先用托管策略。如果同一個角色要訪問多個服務的不同資源策略拆分是標準做法。# 創(chuàng)建一個精簡的 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 刪除堆棧時把數(shù)據(jù)也帶走了現(xiàn)象用 CloudFormation 部署了一套環(huán)境測試完覺得沒用了執(zhí)行刪除堆棧然后發(fā)現(xiàn) S3 桶里的歷史數(shù)據(jù)也全沒了——堆棧刪除默認會刪除桶里的所有對象而不是只刪桶本身。原因CloudFormation 刪除堆棧時對 S3 桶的默認行為是強制刪除——不管桶里有沒有數(shù)據(jù)直接清除。你以為是刪了個空桶實際上是連帶數(shù)據(jù)一起刪。解決給 S3 桶加DeletionPolicy: Retain或者設置DeletionPolicy: Snapshot適用于數(shù)據(jù)庫這樣堆棧刪了數(shù)據(jù)還在只是變成了孤兒資源需要手動清理。是麻煩但比數(shù)據(jù)永久消失強一萬倍。# template.yaml 片段保留 S3 桶數(shù)據(jù)不讓刪除堆棧時連帶刪掉 Resources: DataBucket: Type: AWS::S3::Bucket DeletionPolicy: Retain5.6 EC2 實例啟動慢其實是元數(shù)據(jù)服務在拖后腿現(xiàn)象同一套 AMI在us-east-1啟動只要 30 秒在某個區(qū)域要 3 分鐘網(wǎng)絡也時好時差。原因EC2 實例啟動時需要通過 Instance Metadata ServiceIMDS獲取密鑰、網(wǎng)絡配置等信息。某些區(qū)域 IMDS 的響應慢導致啟動流程卡住。解決改用 IMDSv2強制版本并給實例設置較長的恢復等待時間。如果是 T 系列實例t3/t4g查看是否觸發(fā)了 CPU 積分耗盡——積分用完性能直接掉到基準以下。# 查看實例的 CPU 積分余額 aws ec2 describe-instances \ --instance-id i-0a1b2c3d4e5f67890 \ --query Reservations[0].Instances[0].CpuOptions6. 把基礎設施寫成代碼用 CDK 管理這套環(huán)境的實戰(zhàn)技巧6.1 為什么用 CDK 而不是 CloudFormation YAML第三版從 CloudFormation 講到 CDK這個演進很多人還沒來得及接受。CloudFormation 用 YAML/JSON 描述資源工作了但體驗一般——YAML 沒有類型檢查、沒有自動補全、復用邏輯得靠嵌套模板或宏改一個參數(shù)要在多個文件里找。CDKCloud Development Kit允許你用 TypeScript/JavaScript/Python以及 Java、C# 等寫基礎設施本質上是把 CloudFormation 模板變成代碼生成器。有 IDE 補全和類型系統(tǒng)寫錯屬性名在編譯期就報錯不用等部署失敗可以用變量、循環(huán)、函數(shù)組合資源應付復雜的重復性資源提供構造庫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會默認創(chuàng)建包含兩個可用區(qū)的完整網(wǎng)絡環(huán)境——公有子網(wǎng)、私有子網(wǎng)、NAT 網(wǎng)關、路由表全部自動化。SecurityGroup的addIngressRule在 YAML 里對應好幾行配置這里一行就完成了。ec2.Instance則自動幫你創(chuàng)建實例、掛載安全組、分配存儲。6.2 本地模擬與快速驗證CDK 的 Test 功能不是擺設CDK 有一個被低估的能力——單元測試。它能把基礎設施的「預期狀態(tài)」寫進斷言在部署之前就驗證。第三版雖然沒有把這個當重點講但我實際操作下來這是防止生產(chǎn)事故最有效的工具。// 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這段測試的意義在于安全組規(guī)則、VPC 配置、實例類型——所有基礎設施的「關鍵參數(shù)」都變成了可斷言的代碼。當團隊里有人改了一個安全組規(guī)則或換了一個實例類型測試會立刻告訴你這違反了預期。我跟人協(xié)作 AWS 項目的習慣是所有資源變更必須帶著測試提交不然不管其他代碼測得多好上線大概率出問題。6.3 環(huán)境隔離用上下文參數(shù)切換 dev、test、prodCDK 在實踐中最容易翻車的場景是「測試環(huán)境跟生產(chǎn)環(huán)境混在一起」。有人圖省事所有環(huán)境都部署到同一個賬號沒有做隔離結果測試環(huán)境的告警和實驗數(shù)據(jù)污染了生產(chǎn)監(jiān)控甚至誤刪了生產(chǎn)資源。我的方案是用 CDK Context 區(qū)分環(huán)境不同環(huán)境用不同賬號 不同 VPC。// 在 cdk.json 里定義環(huán)境差異 { app: node bin/app.js, context: { dev: { instanceType: t3.micro, natGateways: 0 }, prod: { instanceType: m5.large, natGateways: 2 } } }// bin/app.js — 根據(jù)環(huán)境讀取不同配置 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 } });# 分別部署不同環(huán)境 ENVdev cdk deploy ENVprod cdk deploytryGetContext從cdk.json或命令行參數(shù)里讀取配置這樣同樣的代碼在不同的環(huán)境得到不同的基礎設施。dev 環(huán)境不需要 NAT 網(wǎng)關因為不需要訪問外部網(wǎng)絡用natGateways: 0能省掉一大筆費用prod 環(huán)境必須雙 NAT 保證高可用。這個模式下環(huán)境之間的差異被代碼顯式管理而不是靠「誰記得改了什么參數(shù)」——這是我做過太多環(huán)境混亂項目之后的血淚經(jīng)驗?;A設施沒有后悔藥可言但 CDK 的代碼化至少讓你知道「現(xiàn)在到底有什么、從哪來的、怎么拆掉它」。希望幫到你。本文還有配套的精品資源點擊獲取