

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 將 Lambda 搭配基礎設施即程式碼 (IaC)
<a name="foundation-iac"></a>

Lambda 函數很少單獨執行。相反，它們通常是具有其他資源 (例如資料庫、佇列和儲存體) 的無伺服器應用程式的一部分。使用 [基礎設施即程式碼 (IaC)](https://aws.amazon.com/what-is/iac/)，您可以自動化部署程序，以快速且重複地部署並更新涉及許多不同 AWS 資源的整個無伺服器應用程式。這種方法可加快您的開發週期，使組態管理更加輕鬆，並確保您的資源每次都以相同的方式部署。

## 用於 Lambda 的 IaC 工具
<a name="foundation-iac-tools"></a>

**CloudFormation**  
CloudFormation 是來自 AWS 的基礎 IaC 服務。可以使用 [YAML 或 JSON 範本](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-guide.html)來建模和佈建整個 AWS 基礎設施，包括 Lambda 函數。CloudFormation 可處理建立、更新和刪除 AWS 資源的複雜性。

**AWS Serverless Application Model (AWS SAM)**  
AWS SAM 是在 CloudFormation 上建置的開放原始碼架構。它提供可定義無伺服器應用程式的簡化語法。使用 [AWS SAM 範本](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html)，只需幾行 YAML 即可快速佈建 Lambda 函數、API、資料庫和事件來源。

**AWS Cloud Development Kit (AWS CDK)**  
CDK 是 IaC 的程式碼優先方法。可以使用 TypeScript、JavaScript、Python、Java、C\$1、.Net 或 Go 來定義基於 Lambda 的架構。選擇您偏好的語言，並使用程式設計元素，例如參數、條件、迴圈、合成和繼承，來定義基礎設施的所需結果。然後，CDK 會產生基礎 CloudFormation 範本以進行部署。如需搭配使用 Lambda 與 CDK 的範例，請參閱 [使用 部署 Lambda 函數 AWS CDK](lambda-cdk-tutorial.md)。

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/IaC_tools.png)


AWS 還提供了一種稱為 AWS Infrastructure Composer、使用簡單的圖形介面開發 IaC 範本的服務。使用 Infrastructure Composer，您可以透過在視覺化畫布中拖曳、分組和連線 AWS 服務來設計應用程式架構。然後，Infrastructure Composer 會從您的設計中建立 AWS SAM 範本或 CloudFormation 範本，供您用來部署應用程式。

在下面的 [在 AWS SAM 與 Infrastructure Composer 中使用 Lambda 函式](foundation-iac-getting-started.md) 章節中，您可以使用 Infrastructure Composer，根據現有的 Lambda 函數為無伺服器應用程式開發範本。

# 在 AWS SAM 與 Infrastructure Composer 中使用 Lambda 函式
<a name="foundation-iac-getting-started"></a>

在本教學課程中，您可以透過從現有的 Lambda 函數建立 AWS SAM 範本，然後新增其他 AWS 資源，在 Infrastructure Composer 中建置無伺服器應用程式，開始將 IaC 與 Lambda 搭配使用。

當您執行此教學課程時，您將學習到一些基本概念，例如如何在 AWS SAM 中指定 AWS 資源。您也將學習如何使用 Infrastructure Composer 來建置可使用 AWS SAM 或 CloudFormation 部署的無伺服器應用程式。

請執行下列步驟以完成本教學課程：
+ 建立範例 Lambda 函數
+ 使用 Lambda 主控台可檢視函數的 AWS SAM 範本
+ 將函數的配置匯出到 AWS Infrastructure Composer 並根據函數的組態設計一個簡單的無伺服器應用程式
+ 儲存可用來部署無伺服器應用程式的更新 AWS SAM 範本

## 必要條件
<a name="foundation-iac-prerequisites"></a>

在本教學課程中，您會使用 Infrastructure Composer 的[本機同步處理](https://docs.aws.amazon.com/application-composer/latest/dg/reference-features-local-sync.html)功能，將範本和程式碼檔案儲存到本機建置機器。要使用此功能，您需要一個支援檔案系統存取 API 的瀏覽器，該瀏覽器允許 Web 應用程式在本機檔案系統中讀取、寫入和儲存文件。我們建議使用 Google Chrome 或 Microsoft Edge。如需檔案系統存取 API 的詳細資訊，請參閱[什麼是檔案系統存取 API？](https://docs.aws.amazon.com/application-composer/latest/dg/reference-fsa.html#reference-fsa-api)

## 建立 Lambda 函數
<a name="foundation-iac-create-function"></a>

在此第一步驟中，將會建立 Lambda 函數，可用於完成本教學課程的其餘部分。為了簡化事情，您可以使用 Lambda 主控台，使用 Python 3.11 執行期來建立基本的「Hello world」函數。

**若要使用主控台建立「Hello world」Lambda 函數**

1. 開啟 [Lambda 主控台](https://console.aws.amazon.com/lambda)。

1. 選擇 **Create function (建立函數)**。

1. 保持選取**從頭開始撰寫**，然後在**基本資訊**之下的**函數名稱**中輸入 **LambdaIaCDemo**。

1. 針對**執行期**，選取 **Python 3.11**。

1. 選擇**建立函數**。

## 檢視函數的 AWS SAM 範本
<a name="foundation-iac-view-template"></a>

在您將函數組態匯出至 Infrastructure Composer 之前，請使用 Lambda 主控台以 AWS SAM 範本的方式檢視函數目前的組態。按照本章節中的步驟操作，您將瞭解 AWS SAM 範本的剖析，以及如何定義 Lambda 函數等資源以開始指定無伺服器應用程式。

**檢視函數的 AWS SAM 範本**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您剛建立的函數 (`LambdaIaCDemo`)。

1. 在**函數概觀**窗格中，選擇**範本**。

   代替表示函數配置的圖表，您將看到一個函數的 AWS SAM 模板。範本看起來應該如下所示。

   ```
   # This AWS SAM template has been generated from your function's 
   # configuration. If your function has one or more triggers, note 
   # that the AWS resources associated with these triggers aren't fully 
   # specified in this template and include placeholder values.Open this template 
   # in AWS Application Composer or your favorite IDE and modify 
   # it to specify a serverless application with other AWS resources. 
   AWSTemplateFormatVersion: '2010-09-09'
   Transform: AWS::Serverless-2016-10-31
   Description: An AWS Serverless Specification template describing your function.
   Resources:
     LambdaIaCDemo:
       Type: AWS::Serverless::Function
       Properties:
         CodeUri: .
         Description: ''
         MemorySize: 128
         Timeout: 3
         Handler: lambda_function.lambda_handler
         Runtime: python3.11
         Architectures:
           - x86_64
         EventInvokeConfig:
           MaximumEventAgeInSeconds: 21600
           MaximumRetryAttempts: 2
         EphemeralStorage:
           Size: 512
         RuntimeManagementConfig:
           UpdateRuntimeOn: Auto
         SnapStart:
           ApplyOn: None
         PackageType: Zip
         Policies:
           Statement:
             - Effect: Allow
               Action:
                 - logs:CreateLogGroup
               Resource: arn:aws:logs:us-east-1:123456789012:*
             - Effect: Allow
               Action:
                 - logs:CreateLogStream
                 - logs:PutLogEvents
               Resource:
                 - >-
                   arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/LambdaIaCDemo:*
   ```

讓我們花一點時間看看函數的 YAML 範本，並了解一些重要概念。

範本以宣告 `Transform: AWS::Serverless-2016-10-31` 開始。此聲明是必需的，因為在幕後，AWS SAM 模板是透過 CloudFormation 而部署。使用 `Transform` 陳述式將範本識別為 AWS SAM 範本檔案。

在 `Transform` 聲明之後伴隨的 `Resources` 部分。這是您要使用 AWS SAM 範本部署的 AWS 資源的定義位置。AWS SAM 範本可以包含 AWS SAM 資源和 CloudFormation 資源的組合。這是因為在部署期間，AWS SAM 範本會展開為 CloudFormation 範本，因此任何有效的 CloudFormation 語法都可以新增至 AWS SAM 範本。

目前，範本 `Resources` 區段中只定義了一個資源，即您的 Lambda 函數 `LambdaIaCDemo`。若要將 Lambda 函數新增至 AWS SAM 範本，請使用 `AWS::Serverless::Function` 資源類型。Lambda 函數資源的 `Properties` 定義函數的執行期、函數處理常式和其他組態選項。此處也定義了函數原始碼的路徑，AWS SAM 應該用於部署該函數。若要進一步了解 AWS SAM 中的 Lambda 函數資源，請參閱 *AWS SAM 開發人員指南* 中的 [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html)。

除了函數屬性和組態外，範本還會為您的函數指定 AWS Identity and Access Management (IAM) 政策。此政策授予您函數將日誌寫入 Amazon CloudWatch Logs 的許可。當您在 Lambda 主控台中建立函數時，Lambda 會自動將此政策附加至您的函數。若要進一步瞭解如何為 AWS SAM 範本中的函數指定 IAM 政策，請參閱《*AWS SAM 開發人員指南*》中 [AWS::Serverless::Function](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html) 頁面上的 `policies` 屬性。

若要進一步瞭解 AWS SAM 範本的結構，請參閱[AWS SAM 範本剖析](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy.html)。

## 使用 AWS Infrastructure Composer 來設計無伺服器應用程式
<a name="foundation-iac-design-app"></a>

若要開始使用函數的 AWS SAM 範本做為起點來建立簡單的無伺服器應用程式，請將函數組態匯出至 Infrastructure Composer，然後啟動 Infrastructure Composer 的本機同步處理模式。本機同步會自動將函數的程式碼和 AWS SAM 範本保存到本機構置機器，並在您在 Infrastructure Composer 中新增其他 AWS 資源時保持已儲存的範本保持同步。

**若要將您的函數匯出至 Infrastructure Composer**

1. 在**函數概觀**窗格中，選擇**匯出至應用程式編寫器**。

   若要將函數的組態和程式碼匯出至 Infrastructure Composer，Lambda 會在您的帳戶中建立 Amazon S3 儲存貯體來暫時存放此資料。

1. 在對話方塊中，選擇**確認並建立專案**以接受此儲存貯體的預設名稱，並將函數的設定和程式碼匯出至 Infrastructure Composer。

1. (選擇性) 若要為 Lambda 建立的 Amazon S3 儲存貯體選擇其他名稱，請輸入新名稱，然後選擇**確認並建立專案**。Amazon S3 儲存貯體的名稱必須是全域唯一的，並遵循[儲存貯體命名規則](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)。

   選取**確認並建立專案**會開啟 Infrastructure Composer 主控台。在*畫布*上，您將看到您 Lambda 函數。

1. 從**選單**下拉式清單中選擇**啟用本機同步**。

1. 在開啟的對話方塊中，選擇**選取資料夾**，然後選取本機建置機器上的資料夾。

1. 選擇**啟用**以啟用本機同步。

若要將您的函數匯出至 Infrastructure Composer，您需要有使用某些 API 動作的許可。如果您無法匯出函數，請見 [所需的許可](services-appcomposer.md#services-appcomposer-permissions) 並確認您有所需的許可。

**注意**  
標準 [Amazon S3 定價](https://aws.amazon.com/s3/pricing)適用於 Lambda 在您將函數匯出至 Infrastructure Composer 時所建立的儲存貯體。Lambda 放入儲存貯體的物件會在 10 天後自動刪除，但 Lambda 不會刪除儲存貯體本身。  
若要避免額外費用新增至您的 AWS 帳戶，請在將函數匯出至 Infrastructure Composer 之後，依照[刪除儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-bucket.html)中的指示執行。如需 Lambda 所建立 Amazon S3 儲存貯體的詳細資訊，請參閱 [AWS Lambda 搭配 使用 AWS Infrastructure Composer](services-appcomposer.md)。

**若要在 Infrastructure Composer 中設計無伺服器應用程式**

啟用本機同步之後，您在 Infrastructure Composer 中所做的變更會反映在儲存於本機建置機器上的 AWS SAM 範本中。您現在可以將其他 AWS 資源拖放到 Infrastructure Composer 畫布上，以建置您的應用程式。在此範例中，您將 Amazon SQS 簡單佇列新增為 Lambda 函數的觸發程序，以及新增 DynamoDB 資料表供函數寫入資料。

1. 執行下列動作，將 Amazon SQS 觸發條件新增至您的 Lambda 函數：

   1. 在**資源**面板的搜尋欄位中，輸入 **SQS**。

   1. 將 **SQS 佇列**資源拖曳到畫布上，並將其放置在 Lambda 函數的左側。

   1. 選擇**詳細資訊**，然後為**邏輯 ID** 輸入 **LambdaIaCQueue**。

   1. 選擇**儲存**。

   1. 按一下 SQS 佇列卡上的**訂閱**連接埠，然後將它拖曳至 Lambda 函數卡上的左側連接埠，即可連接您的 Amazon SQS 和 Lambda 資源。兩個資源之間出現一條線表示連線成功。Infrastructure Composer 也會在畫布底部顯示訊息，指示出兩個資源已成功連線。

1. 執行下列動作，為您的 Lambda 函數新增 Amazon DynamoDB 資料表，以便將資料寫入：

   1. 在**資源**面板的搜尋欄位中，輸入 **DynamoDB**。

   1. 將 **DynamoDB 資料表**資源拖曳到畫布上，並將其放置在 Lambda 函數的右側。

   1. 選擇**詳細資訊**，然後為**邏輯 ID** 輸入 **LambdaIaCTable**。

   1. 選擇**儲存**。

   1. 按一下 Lambda 函數卡的右側連接埠，然後將其拖曳至 DynamoDB 卡上的左側連接埠，藉此將 DynamoDB 資料表連接至 Lambda 函數。

現在您已新增這些額外資源，讓我們來看看 Infrastructure Composer 已建立的更新 AWS SAM 範本。

**若要檢視更新的 AWS SAM 範本**
+ 在 Infrastructure Composer 畫布上，選擇**範本**以從畫布檢視切換至範本檢視。

您的 AWS SAM 範本現在應該包含下列其他資源和屬性：
+ 識別碼為 `LambdaIaCQueue` 的 Amazon SQS 佇列

  ```
  LambdaIaCQueue:
      Type: AWS::SQS::Queue
      Properties:
        MessageRetentionPeriod: 345600
  ```

  當您使用 Infrastructure Composer 新增 Amazon SQS 佇列時，Infrastructure Composer 會設定 `MessageRetentionPeriod` 屬性。您也可以選取 SQS 佇列卡上的**詳細資訊**，然後核取或取消核取 **Fifo 佇列**來設定 `FifoQueue` 屬性。

  若要設定佇列的其他屬性，您可以手動編輯範本以新增它們。若要進一步瞭解 `AWS::SQS::Queue` 資源及其可用的屬性，請參閱《*CloudFormation 使用者指南*》中的[AWS::SQS::Queue](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sqs-queue.html)。
+ Lambda 函數定義中的 `Events` 屬性，可將 Amazon SQS 佇列指定為函數的觸發程序

  ```
  Events:
    LambdaIaCQueue:
      Type: SQS
      Properties:
        Queue: !GetAtt LambdaIaCQueue.Arn
        BatchSize: 1
  ```

  此 `Events` 屬性由事件類型和一組依賴於類型的屬性組成。若要瞭解不同 AWS 服務，您可以設定以觸發 Lambda 函數和您可以設定的屬性，請參閱《*AWS SAM 開發人員指南*》中的 [EventSource](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-eventsource.html)。
+ 具有識別碼 `LambdaIaCTable` 的 DynamoDB 資料表

  ```
  LambdaIaCTable:
      Type: AWS::DynamoDB::Table
      Properties:
        AttributeDefinitions:
          - AttributeName: id
            AttributeType: S
        BillingMode: PAY_PER_REQUEST
        KeySchema:
          - AttributeName: id
            KeyType: HASH
        StreamSpecification:
          StreamViewType: NEW_AND_OLD_IMAGES
  ```

  使用 Infrastructure Composer 新增 DynamoDB 資料表時，您可以選擇 DynamoDB 資料表卡片上的**詳細資料**並編輯索引鍵值來設定資料表的索引鍵。Infrastructure Composer 也會設定許多其他屬性的預設值，包括 `BillingMode` 和 `StreamViewType`。

  若要進一步瞭解這些屬性和您可以新增至 AWS SAM 範本的其他屬性，請參閱《*CloudFormation 使用者指南*》中的 [AWS::DynamoDB::Table](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html)。
+ 一項新的 IAM 政策，可讓您在新增的 DynamoDB 資料表上執行 CRUD 操作的函數許可。

  ```
  Policies:
  ...
    - DynamoDBCrudPolicy:
      TableName: !Ref LambdaIaCTable
  ```

完整的最終 AWS SAM 範本看起來應該如下所示。

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: An AWS Serverless Specification template describing your function.
Resources:
  LambdaIaCDemo:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: .
      Description: ''
      MemorySize: 128
      Timeout: 3
      Handler: lambda_function.lambda_handler
      Runtime: python3.11
      Architectures:
        - x86_64
      EventInvokeConfig:
        MaximumEventAgeInSeconds: 21600
        MaximumRetryAttempts: 2
      EphemeralStorage:
        Size: 512
      RuntimeManagementConfig:
        UpdateRuntimeOn: Auto
      SnapStart:
        ApplyOn: None
      PackageType: Zip
      Policies:
        - Statement:
            - Effect: Allow
              Action:
                - logs:CreateLogGroup
              Resource: arn:aws:logs:us-east-1:594035263019:*
            - Effect: Allow
              Action:
                - logs:CreateLogStream
                - logs:PutLogEvents
              Resource:
                - arn:aws:logs:us-east-1:594035263019:log-group:/aws/lambda/LambdaIaCDemo:*
        - DynamoDBCrudPolicy:
            TableName: !Ref LambdaIaCTable
      Events:
        LambdaIaCQueue:
          Type: SQS
          Properties:
            Queue: !GetAtt LambdaIaCQueue.Arn
            BatchSize: 1
      Environment:
        Variables:
          LAMBDAIACTABLE_TABLE_NAME: !Ref LambdaIaCTable
          LAMBDAIACTABLE_TABLE_ARN: !GetAtt LambdaIaCTable.Arn
  LambdaIaCQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 345600
  LambdaIaCTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      BillingMode: PAY_PER_REQUEST
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      StreamSpecification:
        StreamViewType: NEW_AND_OLD_IMAGES
```

## 使用 AWS SAM (選擇性) 部署您的無伺服器應用程式
<a name="foundation-iac-deploy"></a>

如果您使用剛剛在 Infrastructure Composer 中建立的範本，想要用 AWS SAM 來部署無伺服器應用程式，則必須先安裝 AWS SAM CLI。若要執行此操作，請遵循[安裝 AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html) 中的說明。

在部署應用程式之前，您也需要更新 Infrastructure Composer 與範本一起儲存的函數程式碼。目前，Infrastructure Composer 儲存的 `lambda_function.py` 檔案只包含 Lambda 在建立函數時提供的基本 'Hello world' 程式碼。

若要更新函數程式碼，請複製下列程式碼，並將其貼到 Infrastructure Composer 儲存至本機建置機器的 `lambda_function.py` 檔案中。當您啟動本機同步模式時，已指定 Infrastructure Composer 要儲存此檔案的目錄。

此程式碼接受來自您在 Infrastructure Composer 中建立之 Amazon SQS 佇列的訊息中的鍵值對。如果索引鍵和值都是字串，則程式碼會使用它們將項目寫入範本中定義的 DynamoDB 資料表。

### 更新 Python 函數程式碼
<a name="foundation-iac-updated-code"></a>

```
import boto3
import os
import json

# define the DynamoDB table that Lambda will connect to
tablename = os.environ['LAMBDAIACTABLE_TABLE_NAME']

# create the DynamoDB resource
dynamo = boto3.client('dynamodb')

def lambda_handler(event, context):
    # get the message out of the SQS event
    message = event['Records'][0]['body']
    data = json.loads(message)
    # write event data to DDB table
    if check_message_format(data):
        key = next(iter(data))
        value = data[key]
        dynamo.put_item(
            TableName=tablename,
            Item={
                'id': {'S': key},
                'Value': {'S': value}
            }
        )
    else:
        raise ValueError("Input data not in the correct format")

# check that the event object contains a single key value  
# pair that can be written to the database
def check_message_format(message):
    if len(message) != 1:
        return False
        
    key, value = next(iter(message.items()))
    
    if not (isinstance(key, str) and isinstance(value, str)):
        return False

    else:
        return True
```

**若要部署您的無伺服器應用程式**

若要使用 AWS SAM CLI 部署您的應用程式，請執行下列步驟。若要讓您的函數正確建置和部署，Python 第 3.11 版本必須安裝在您的建置機器和 `PATH`。

1. 從 Infrastructure Composer 儲存 `template.yaml` 和 `lambda_function.py` 檔案的目錄中執行下列命令。

   ```
   sam build
   ```

   此命令會收集應用程式的建置成品，並將它們放置在適當的格式和位置以進行部署。

1. 若要部署應用程式並建立 AWS SAM 範本中指定的 Lambda、Amazon SQS 和 DynamoDB 資源，請執行下列命令。

   ```
   sam deploy --guided
   ```

   使用此 `--guided` 標記意味著 AWS SAM 將顯現提示，以引導您完成部署過程。對於此部署，請按 Enter 接受預設選項。

在部署程序期間，AWS SAM 會在您的 AWS 帳戶 中建立下列資源：
+ 一個名為 `sam-app` 的 CloudFormation [堆疊](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-concepts.html#cfn-concepts-stacks)
+ 名稱格式為 `sam-app-LambdaIaCDemo-99VXPpYQVv1M` 的 Lambda 函數
+ 名稱格式為 `sam-app-LambdaIaCQueue-xL87VeKsGiIo` 的 Amazon SQS 佇列
+ 名稱格式為 `sam-app-LambdaIaCTable-CN0S66C0VLNV` 的 DynamoDB 資料表

AWS SAM 還會建立必要的 IAM 角色和政策，讓 Lambda 函數可以讀取來自 Amazon SQS 佇列的訊息，並在 DynamoDB 資料表上執行 CRUD 操作。

## 測試已部署的應用程式 (選擇性)
<a name="foundation-iac-test"></a>

若要確認您的無伺服器應用程式是否正確部署，請將訊息傳送至包含索引鍵值組的 Amazon SQS 佇列，並檢查 Lambda 是否使用這些值將項目寫入 DynamoDB 資料表。

**測試您的無伺服器應用程式**

1. 開啟 Amazon SQS 主控台的[佇列](https://console.aws.amazon.com/sqs/v2/home#/queues)頁面，然後選取從範本所建立 AWS SAM 的佇列。名稱具有格式 `sam-app-LambdaIaCQueue-xL87VeKsGiIo`。

1. 選擇**傳送和接收訊息**，然後將以下 JSON 貼到**傳送訊息**區段裡的**訊息內文**中。

   ```
   {
       "myKey": "myValue"
   }
   ```

1. 選擇**傳送訊息**。

   將訊息傳送至佇列會導致 Lambda 透過範本 AWS SAM 中定義的事件來源映射調用您的函數。若要確認 Lambda 已如預期調用您的函數，請確認項目已新增至 DynamoDB 資料表中。

1. 開啟 DynamoDB 主控台的 [資料表](https://console.aws.amazon.com/dynamodbv2#tables) 頁面，然後選擇資料表。名稱具有格式 `sam-app-LambdaIaCTable-CN0S66C0VLNV`。

1. 選擇**探索資料表項目**。在 **Items returned** 窗格中，應該會看到一個包含 **id** `myKey` 和 **數值** `myValue` 的項目。

# 使用 部署 Lambda 函數 AWS CDK
<a name="lambda-cdk-tutorial"></a>

 AWS Cloud Development Kit (AWS CDK) 是基礎設施即程式碼 (IaC) 架構，您可以使用您選擇的程式設計語言來定義 AWS 雲端基礎設施。若要定義您自己的雲端基礎設施，要先編寫包含一個或更多堆疊的應用程式 (使用 CDK 支援的其中一種語言)。然後，您將它合成到 CloudFormation 範本，並將您的 資源部署到 AWS 帳戶。按照本主題中的步驟部署一個 Lambda 函數，從 Amazon API Gateway 端點傳回事件。

隨附於 CDK 的 AWS 建構程式庫提供模組，可讓您用來建立 AWS 服務 所提供資源的模型。針對熱門服務，程式庫會提供具有智能預設和最佳實務的彙整建構。您可以使用 [aws\$1lambda](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html) 模組來定義函數和相關資源，幾行程式碼即可完成。

## 先決條件
<a name="lambda-cdk-prerequisites"></a>

開始本教學課程之前，請執行下列命令 AWS CDK 來安裝 。

```
npm install -g aws-cdk
```

## 步驟 1：設定您的 AWS CDK 專案
<a name="lambda-cdk-step-1"></a>

為您的新 AWS CDK 應用程式建立目錄並初始化專案。

------
#### [ JavaScript ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language javascript
```

------
#### [ TypeScript ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language typescript
```

------
#### [ Python ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language python
```

專案開始後，啟用專案的虛擬環境，並安裝 AWS CDK的基準相依項。

```
source .venv/bin/activate
python -m pip install -r requirements.txt
```

------
#### [ Java ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language java
```

將此 Maven 專案匯入 Java 整合式開發環境 (IDE)。例如，在 Eclipse 中，依次選擇**檔案** > **匯入** > **Maven** > **現有的 Maven 專案**。

------
#### [ C\$1 ]

```
mkdir hello-lambda
cd hello-lambda
cdk init --language csharp
```

------

**注意**  
 AWS CDK 應用程式範本使用專案目錄的名稱來產生來源檔案和類別的名稱。在此範例中，目錄名為 `hello-lambda`。若使用不同的專案目錄名稱，您的應用程式將與這些說明不相符。

AWS CDK v2 包含名為 的單一套件 AWS 服務 中所有 的穩定建構`aws-cdk-lib`。在初始化專案時，此套件會安裝為相依性套件。使用某些程式設計語言時，套件會在您第一次建置專案時安裝。

## 步驟 2：定義 AWS CDK 堆疊
<a name="lambda-cdk-step-2"></a>

CDK *堆疊*是一或多個建構的集合，可定義 AWS 資源。每個 CDK 堆疊代表您 CDK 應用程式中的 CloudFormation 堆疊。

若要定義 CDK 堆疊，請遵循您偏好之程式設計語言的指示。此堆疊定義下列項目：
+ 函數的邏輯名稱：`MyFunction`
+ 函數程式碼的位置 (在 `code` 屬性中指定)。如需詳細資訊，請參閱 *AWS Cloud Development Kit (AWS CDK) API Reference* 中的 [Handler code](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html#handler-code) 一節。
+ REST API 的邏輯名稱：`HelloApi`
+ API Gateway 端點的邏輯名稱：`ApiGwEndpoint`

請注意，本教學課程中的所有 CDK 堆疊都會使用 Lambda 函數的 Node.js [執行時期](lambda-runtimes.md)。您可以針對此 CDK 堆疊和 Lambda 函數使用不同的程式設計語言，以利用每種語言的優勢。例如，您可以針對 CDK 堆疊使用 TypeScript，以利用基礎設施程式碼靜態輸入的優勢。您可以針對 Lambda 函數使用 JavaScript，以利用動態類型語言的彈性和快速開發優勢。

------
#### [ JavaScript ]

開啟 `lib/hello-lambda-stack.js` 檔案並將內容替換如下：

```
const { Stack } = require('aws-cdk-lib');
const lambda = require('aws-cdk-lib/aws-lambda');
const apigw = require('aws-cdk-lib/aws-apigateway');

class HelloLambdaStack extends Stack {
  /**
   *
   * @param {Construct} scope
   * @param {string} id
   * @param {StackProps=} props
   */
  constructor(scope, id, props) {
    super(scope, id, props);
    const fn = new lambda.Function(this, 'MyFunction', {
      code: lambda.Code.fromAsset('lib/lambda-handler'),
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler'
    });

    const endpoint = new apigw.LambdaRestApi(this, 'MyEndpoint', {
      handler: fn,
      restApiName: "HelloApi"
    });

  }
}

module.exports = { HelloLambdaStack }
```

------
#### [ TypeScript ]

開啟 `lib/hello-lambda-stack.ts` 檔案並將內容替換如下：

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as apigw from "aws-cdk-lib/aws-apigateway";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as path from 'node:path';

export class HelloLambdaStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps){
    super(scope, id, props)
    const fn = new lambda.Function(this, 'MyFunction', {
      runtime: lambda.Runtime.NODEJS_LATEST,
      handler: 'index.handler',
      code: lambda.Code.fromAsset(path.join(__dirname, 'lambda-handler')),
    });

    const endpoint = new apigw.LambdaRestApi(this, `ApiGwEndpoint`, {
      handler: fn,
      restApiName: `HelloApi`,
    });

  }
}
```

------
#### [ Python ]

開啟 `/hello-lambda/hello_lambda/hello_lambda_stack.py` 檔案並將內容替換如下：

```
from aws_cdk import (
    Stack,
    aws_apigateway as apigw,
    aws_lambda as _lambda
)
from constructs import Construct

class HelloLambdaStack(Stack):

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        fn = _lambda.Function(
            self,
            "MyFunction",
            runtime=_lambda.Runtime.NODEJS_LATEST,
            handler="index.handler",
            code=_lambda.Code.from_asset("lib/lambda-handler")
        )

        endpoint = apigw.LambdaRestApi(
            self,
            "ApiGwEndpoint",
            handler=fn,
            rest_api_name="HelloApi"
        )
```

------
#### [ Java ]

開啟 `/hello-lambda/src/main/java/com/myorg/HelloLambdaStack.java` 檔案並將內容替換如下：

```
package com.myorg;

import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;
import software.amazon.awscdk.services.apigateway.LambdaRestApi;
import software.amazon.awscdk.services.lambda.Function;

public class HelloLambdaStack extends Stack {
    public HelloLambdaStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public HelloLambdaStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Function hello = Function.Builder.create(this, "MyFunction")
                            .runtime(software.amazon.awscdk.services.lambda.Runtime.NODEJS_LATEST)
                            .code(software.amazon.awscdk.services.lambda.Code.fromAsset("lib/lambda-handler"))
                            .handler("index.handler")
                            .build();

        LambdaRestApi api = LambdaRestApi.Builder.create(this, "ApiGwEndpoint")
                                .restApiName("HelloApi")
                                .handler(hello)
                                .build();

    }
}
```

------
#### [ C\$1 ]

開啟 `src/HelloLambda/HelloLambdaStack.cs` 檔案並將內容替換如下：

```
using Amazon.CDK;
using Amazon.CDK.AWS.APIGateway;
using Amazon.CDK.AWS.Lambda;
using Constructs;

namespace HelloLambda
{
    public class HelloLambdaStack : Stack
    {
        internal HelloLambdaStack(Construct scope, string id, IStackProps props = null) : base(scope, id, props)
        {
            var fn = new Function(this, "MyFunction", new FunctionProps
            {
                Runtime = Runtime.NODEJS_LATEST,
                Code = Code.FromAsset("lib/lambda-handler"),
                Handler = "index.handler"
            });

            var api = new LambdaRestApi(this, "ApiGwEndpoint", new LambdaRestApiProps
            {
                Handler = fn
            });
        }
    }
}
```

------

## 步驟 3：建立 Lambda 函數程式碼
<a name="lambda-cdk-step-3"></a>

1. 從專案 (`hello-lambda`) 的根目錄建立 Lambda 函數程式碼的 `/lib/lambda-handler` 目錄。此目錄是在 AWS CDK 堆疊的 `code` 屬性中指定。

1. 在 `/lib/lambda-handler` 目錄中，建立名為 `index.js` 的新檔案。將以下程式碼貼到檔案。該函數會從 API 請求擷取特定屬性，並將其傳回為 JSON 回應。

   ```
   exports.handler = async (event) => {
     // Extract specific properties from the event object
     const { resource, path, httpMethod, headers, queryStringParameters, body } = event;
     const response = {
       resource,
       path,
       httpMethod,
       headers,
       queryStringParameters,
       body,
     };
     return {
       body: JSON.stringify(response, null, 2),
       statusCode: 200,
     };
   };
   ```

## 步驟 4：部署 AWS CDK 堆疊
<a name="lambda-cdk-step-4"></a>

1. 從專案根目錄執行 [cdk synth](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-synth.html) 命令：

   ```
   cdk synth
   ```

   此命令會從 CDK 堆疊合成 AWS CloudFormation 範本。該範本是大約為 400 行的 YAML 檔案，與下面的內容相似：
**注意**  
如果您遇到以下錯誤，請確定您位於專案目錄的根目錄。  

   ```
   --app is required either in command-line, in cdk.json or in ~/.cdk.json
   ```  
**Example CloudFormation 範本**  

   ```
   Resources:
     MyFunctionServiceRole3C357FF2:
       Type: AWS::IAM::Role
       Properties:
         AssumeRolePolicyDocument:
           Statement:
             - Action: sts:AssumeRole
               Effect: Allow
               Principal:
                 Service: lambda.amazonaws.com
           Version: "2012-10-17"		 	 	 
         ManagedPolicyArns:
           - Fn::Join:
               - ""
               - - "arn:"
                 - Ref: AWS::Partition
                 - :iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
       Metadata:
         aws:cdk:path: HelloLambdaStack/MyFunction/ServiceRole/Resource
     MyFunction1BAA52E7:
       Type: AWS::Lambda::Function
       Properties:
         Code:
           S3Bucket:
             Fn::Sub: cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}
           S3Key: ab1111111cd32708dc4b83e81a21c296d607ff2cdef00f1d7f48338782f92l3901.zip
         Handler: index.handler
         Role:
           Fn::GetAtt:
             - MyFunctionServiceRole3C357FF2
             - Arn
         Runtime: nodejs24.x
         ...
   ```

1. 執行 [cdk deploy](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-deploy.html) 命令：

   ```
   cdk deploy
   ```

   等待資源建立完畢。最終輸出包含 API Gateway 端點的 URL。範例：

   ```
   Outputs:
   HelloLambdaStack.ApiGwEndpoint77F417B1 = https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/
   ```

## 步驟 5：測試函數
<a name="lambda-cdk-step-5"></a>

若要調用該 Lambda 函數，請複製 API Gateway 端點並將其貼到 Web 瀏覽器或執行 `curl` 命令：

```
curl -s https://abcd1234.execute-api.us-east-1.amazonaws.com/prod/
```

回應是從原始事件物件所選取屬性的 JSON 表示，其中包含對 API Gateway 端點提出之請求的相關資訊。範例：

```
{
  "resource": "/",
  "path": "/",
  "httpMethod": "GET",
  "headers": {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Accept-Language": "en-US,en;q=0.9",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Desktop-Viewer": "true",
    "CloudFront-Is-Mobile-Viewer": "false",
    "CloudFront-Is-SmartTV-Viewer": "false",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Viewer-ASN": "16509",
    "CloudFront-Viewer-Country": "US",
    "Host": "abcd1234.execute-api.us-east-1.amazonaws.com",
     ...
```

## 步驟 6：清除您的資源
<a name="lambda-cdk-step-6"></a>

API Gateway 端點可公開存取。為了避免意外產生費用，請執行 [cdk destroy](https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-destroy.html) 命令來刪除堆疊和所有相關聯的資源。

```
cdk destroy
```

## 後續步驟
<a name="lambda-cdk-next-steps"></a>

如需以您選擇的語言撰寫 AWS CDK 應用程式的資訊，請參閱下列內容：

------
#### [ TypeScript ]

[以 TypeScript 使用 AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-typescript.html)

------
#### [ JavaScript ]

[以 JavaScript 使用 AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-javascript.html)

------
#### [ Python ]

[在 Python AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html)

------
#### [ Java ]

[在 Java AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-java.html)

------
#### [ C\$1 ]

[在 C\$1 AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-csharp.html)

------
#### [ Go ]

[在 Go AWS CDK 中使用](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-go.html)

------