AWS SAM 簡化了無伺服器應用程式的開發流程,讓開發者能更專注於業務邏輯。本文示範的派對規劃應用程式,利用 API Gateway 接收派對和嘉賓資訊,透過 Lambda 函式處理資料並儲存至 DynamoDB,同時利用排程的 Lambda 函式生成報告並儲存到 S3。這樣的架構展現了無伺服器應用程式的彈性和效率,也體現了 SAM 在定義、佈署和管理無伺服器資源方面的便捷性。透過 YAML 檔案,我們可以清晰地定義應用程式的基礎設施,並利用 SAM CLI 進行構建、佈署和測試。
使用 AWS SAM 開發第一個無伺服器應用程式
在現代雲端運算中,無伺服器架構已成為開發者們的重要選擇。AWS SAM(Serverless Application Model)是 AWS 提供的一個開源框架,用於構建無伺服器應用程式。本篇文章將介紹如何使用 AWS SAM 建立一個簡單的無伺服器應用程式。
應用程式設計
我們的應用程式被稱為「無伺服器派對規劃師」,其設計如圖所示:
此圖示展示了應用程式的工作流程:
- API Gateway 將包含派對和嘉賓資訊的有效載荷傳送到系統中。
- 註冊函式(Registration Function)會在「派對」(Parties)表中建立新的條目(如果該派對不存在),並儲存嘉賓資訊(如姓名和飲食限制)。
- 報告函式(Reporting Function)會檢查是否有未來的派對(即派對日期尚未過去)。
- 報告函式(作為一個排程任務)會取得嘉賓資訊並生成規劃報告。
- 報告函式將報告儲存在 S3 儲存桶中。
圖表翻譯:
此圖表展示了無伺服器派對規劃師的工作流程,包括 API Gateway、註冊函式、報告函式、DynamoDB 資料函式庫和 S3 儲存桶之間的互動。
建立應用程式
首先,我們需要建立專案結構:
$ mkdir registration reporting
$ touch template.yaml
template.yaml 檔案結構
Resources:
RegistrationFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: registration/
Events:
register:
Type: Api
Properties:
Path: /register
Method: post
定義資源
我們的應用程式需要以下資源:
- 兩個 Lambda 函式(註冊和報告)
- 一個 S3 儲存桶(報告)
- 兩個 DynamoDB 表(派對和嘉賓)
- 一個 API Gateway
DynamoDB 表定義
Resources:
PartiesTable:
Type: AWS::Serverless::SimpleTable
Properties:
PrimaryKey:
Name: PartyName
Type: String
GuestsTable:
Type: AWS::Serverless::SimpleTable
Properties:
PrimaryKey:
Name: GuestName
Type: String
組態 IAM 許可權
為了讓 Lambda 函式能夠存取 DynamoDB 表,我們需要新增相應的 IAM 許可權:
Resources:
RegistrationFunction:
Type: AWS::Serverless::Function
Properties:
# ...
Policies:
Statement:
- Effect: Allow
Action:
- dynamodb:PutItem
- dynamodb:GetItem
Resource:
- !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PartiesTable}"
- !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${GuestsTable}"
內容解密:
此段程式碼為註冊函式增加了存取 DynamoDB 表的許可權,允許它對 PartiesTable 和 GuestsTable 執行 PutItem 和 GetItem 操作。
建立 S3 儲存桶
我們需要一個 S3 儲存桶來儲存報告:
Resources:
ReportsBucket:
Type: AWS::S3::Bucket
組態報告函式
報告函式需要不同的 IAM 許可權:
Resources:
ReportingFunction:
# ...
Policies:
Statement:
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:Scan
Resource:
- !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PartiesTable}"
- !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${GuestsTable}"
- Effect: Allow
Action:
- s3:ListBucket
- s3:GetBucketAcl
- s3:PutObject
Resource:
- !GetAtt ReportsBucket.Arn
- !Sub "${ReportsBucket.Arn}/*"
內容解密:
此段程式碼為報告函式增加了存取 DynamoDB 表和 S3 儲存桶的許可權,允許它執行 GetItem、Scan、ListBucket、GetBucketAcl 和 PutObject 操作。
組態排程事件
我們需要為報告函式組態一個排程事件:
Resources:
ReportingFunction:
Type: AWS::Serverless::Function
Properties:
# ...
Events:
scheduled:
Type: Schedule
Properties:
Schedule: "rate(1 day)"
內容解密:
此段程式碼組態了一個排程事件,每天執行一次報告函式。
組態環境變數
我們需要在 Globals 部分組態環境變數:
Globals:
Function:
Timeout: 30
Runtime: python3.8
Handler: app.lambda_handler
Environment:
Variables:
PARTIES_TABLE: !Ref PartiesTable
GUESTS_TABLE: !Ref GuestsTable
REPORTS_BUCKET: !Ref ReportsBucket
內容解密:
此段程式碼組態了環境變數 PARTIES_TABLE、GUESTS_TABLE 和 REPORTS_BUCKET,分別指向對應的 DynamoDB 表和 S3 儲存桶。
建立測試事件
我們可以建立一個簡單的測試事件:
// events/event.json
{
"PartyName": "Birthday",
"PartyDate": "2020-01-01",
"GuestName": "John Doe",
"GuestDiet": "Vegan"
}
構建、封裝和佈署應用程式
$ sam build --use-container
$ sam deploy --stack-name party --capabilities CAPABILITY_IAM --resolve-s3
測試應用程式
我們可以使用 curl 命令測試註冊函式:
curl -X POST \
-d @events/event.json \
-H "Content-Type: application/json" \
https://tzsewdylmj.execute-api.eu-central-1.amazonaws.com/Prod/register
內容解密:
此命令向 API Gateway 傳送一個 POST 請求,包含測試事件的資料。
驗證結果
我們可以檢查 DynamoDB 控制檯,檢視是否成功建立了新的派對和嘉賓條目。
手動呼叫報告函式
$ aws lambda invoke --function-name party-ReportingFunction-17431GZNIJXPE --payload '{}' out.txt
內容解密:
此命令手動呼叫報告函式,並將結果輸出到 out.txt 檔案中。
基礎設施即程式碼(IaC)與AWS CloudFormation的發展
在前面的章節中,我們探討了AWS CloudFormation的功能、特性及其擴充套件應用。現在,讓我們放鬆一下,審視一下基礎設施即程式碼(IaC)和CloudFormation未來的發展趨勢。
基礎設施即程式碼的過去與未來
IaC的概念並非新興事物,其根源可追溯到90年代,當時系統管理員使用Perl和Shell指令碼來自動化日常工作。隨著2006年Amazon Web Services(AWS)的推出,IaC的發展迎來了新的轉折點。AWS使得在幾分鐘內啟動一組虛擬機器成為可能,但也帶來了擴充套件性和效能管理的挑戰。
組態管理工具的興起
早期,工程師很難使用高階程式語言開發自己的基礎設施管理工具。因此,組態管理工具如Chef、Puppet和Ansible應運而生。這些工具能夠提供基礎設施的狀態,但隨著管理的機器數量增加到數百甚至數千台,擴充套件性成為一大挑戰。
CloudFormation與Terraform的對比
2011年,AWS推出了CloudFormation,這是第一個能夠同時進行資源組態和組態管理的工具。儘管它是一個複雜的系統,但它徹底改變了我們進行基礎設施佈署的方式。2014年,HashiCorp推出了Terraform,這是CloudFormation的主要競爭對手。Terraform支援多個雲端服務提供商,如GCP和Azure,並且允許建立自定義提供者。
graph TD A["IaC 概念起源(90年代)"] --> B["AWS 推出(2006年)"] B --> C["組態管理工具出現(Chef, Puppet, Ansible)"] C --> D["CloudFormation 發布(2011年)"] D --> E["Terraform 發布(2014年)"] E --> F["多雲管理與 IaC 進一步發展"]
圖表翻譯: 此圖示展示了基礎設施即程式碼(IaC)從90年代至今的發展歷程。從最初的指令碼自動化到AWS的推出,再到組態管理工具的興起,以及CloudFormation和Terraform的發布,每一步都標誌著IaC技術的重大進步。
Cloud Development Kit(CDK)的價值
隨著雲端服務提供商的發展,「基礎設施」的概念已經遠遠超出了虛擬機器和資料函式庫的範疇。它現在是軟體業務和產品的基礎。將IaC應用於越來越多的服務中,並將其與軟體開發生命週期(SDLC)整合,帶來了新的挑戰。
構建工件與IaC的關係
我們需要思考什麼是構件(build artifact),以及它如何與IaC相關。IaC的構件是宣告檔案,指示服務提供者啟動特定資源嗎?還是它本身就是一個框架,或者是具有必要資源和端點的基礎設施狀態?
應用軟體工程實踐於IaC
我們需要將常見的軟體工程實踐,如單元測試和整合測試,應用於IaC。這樣可以確保基礎設施的變更不會破壞應用程式。
技術選型與未來趨勢
在選擇使用CloudFormation還是Terraform時,需要考慮多方面的因素。CloudFormation與AWS生態系統緊密整合,對於使用AWS服務的團隊來說,它是一個非常好的選擇。另一方面,Terraform的多雲支援使其成為需要跨多個雲端服務提供商工作的團隊的首選。
實踐建議
- 評估需求:根據您的具體需求選擇適合的IaC工具。如果您主要使用AWS服務,CloudFormation可能是最佳選擇。如果您需要在多個雲平台上工作,Terraform可能更適合。
- 實施測試:使用單元測試和整合測試來驗證您的IaC組態。這可以幫助您在佈署前發現並修復問題。
- 持續學習:IaC和相關技術不斷進步。持續學習最新的最佳實踐和新工具,可以幫助您保持競爭力。
進一步閱讀
問題與思考
- 是否可以使用AWS SAM建立非參考資源?
- 哪個命令可以啟動本地API閘道器?
- 是否可以使用SAM CLI刪除AWS SAM堆積疊?
- 是否可以使用AWS SAM在DynamoDB表中建立排序鍵?
參考程式碼
Resources:
MyTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub "my-table-${AWS::Region}"
AttributeDefinitions:
- AttributeName: id
AttributeType: S
- AttributeName: sortKey
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
- AttributeName: sortKey
KeyType: RANGE
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
內容解密:
此段程式碼定義了一個名為MyTable
的DynamoDB表,包含id
和sortKey
兩個屬性,並將id
設定為主鍵,sortKey
設定為排序鍵。該表的讀寫容量單位均設定為1。正確組態這些屬性對於確保表的正確功能和效能至關重要。
雲端自動化未來的基礎設施即程式碼
隨著雲端運算技術的快速發展,基礎設施即程式碼(Infrastructure as Code, IaC)已經成為現代IT架構不可或缺的一部分。過去,我們需要手動設定和管理伺服器、網路和儲存裝置等基礎設施。如今,透過IaC,我們可以使用程式碼來定義和佈署整個基礎設施,大大提高了效率和可靠性。
從虛擬機器到服務即一切
基礎設施已經從單純的虛擬機器演進到包含基礎設施即服務(IaaS)、平台即服務(PaaS)和軟體即服務(SaaS)在內的全面雲端服務。現在,我們可以簡單地下單所需的運算資源、儲存資源或其他服務,並立即獲得可用的端點進行工作。例如,與其自行建立NoSQL資料函式庫,不如直接建立一個DynamoDB表格,並立即開始使用,無需擔心底層基礎設施的冗餘性和效能問題。
基礎設施與應用程式的融合
在這種抽象層級下,我們開始注意到應用程式(例如一段軟體)和底層基礎設施之間的差異正在逐漸消失。這是否意味著我們可以開始將它們結合起來?
讓我們來看看這段虛擬碼:
from infrastructure import network, database, compute
from application import Application
import source_code
# 宣告執行應用程式所需的基礎設施
net = network.new(cidr="10.0.0.0/16",
subnets=3,
mask=24)
db = database.new(engine="mysql",
cpu=2,
mem=2048,
network=net)
node_cluster = compute.vm_cluster.new(count=3,
cpu=2,
mem=2048,
network=net)
# 宣告應用程式並掛載到基礎設施上
app = Application.new()
app.use_db(db)
app.run_on(node_cluster)
app.build.from_source(source_code)
內容解密:
這段虛擬碼展示瞭如何宣告基礎設施和應用程式,並將它們結合起來。首先,我們從infrastructure
模組匯入所需的資源,如網路、資料函式庫和運算資源。接著,宣告了一個網路資源,包含特定的CIDR區塊、子網路數量和子網路遮罩。然後,建立了一個MySQL資料函式庫,指定了CPU、記憶體和所屬網路。隨後,建立了一個由三台虛擬機器組成的叢集,同樣指定了CPU、記憶體和所屬網路。最後,宣告了一個應用程式例項,將資料函式庫掛載到應用程式上,並在虛擬機器叢集上執行,最後從原始碼構建應用程式。
工程角色的未來
儘管我們可以在同一段程式碼中結合實際應用程式和基礎設施,但工程角色的問題仍然存在。誰將成為維運人員?軟體工程師?系統工程師?DevOps工程師?還是Site-reliability工程師?
傳統的「煙囪模式」(silo model),即開發者和維運人員在不同的責任區工作並擁有不同的優先事項,正在逐漸消失。如今,開發者具備了對作業系統和電腦網路的深入理解,而系統工程師則具備了編寫程式碼的能力。行業正在朝著融合的方向發展,IaC很可能會成為未來的「程式碼」。