

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

# 在 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` 的項目。