

# Lambda と Infrastructure as code (IaC) の使用
<a name="foundation-iac"></a>

Lambda 関数が単独で実行されることはまれです。代わりに、多くの場合、データベース、キュー、ストレージなどの他のリソースと共に、サーバーレスアプリケーションの一部を形成します。[Infrastructure as Code (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)を使用して、Lambda 関数を含む AWS インフラストラクチャ全体をモデル化およびプロビジョニングできます。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 に対するコードファーストアプローチです。Lambda ベースのアーキテクチャは、TypeScript、JavaScript、Python、Java、C\$1/.Net、または Go を使用して定義できます。希望する言語を選択し、パラメータ、条件、ループ、構成、継承などのプログラミング要素を使用して、インフラストラクチャの望ましい結果を定義します。次に、CDK はデプロイ用の基盤となる CloudFormation テンプレートを生成します。CDK で Lambda を使用する方法の例については、「[AWS CDK を使用した Lambda 関数のデプロイ](lambda-cdk-tutorial.md)」を参照してください。

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


また、AWS ではシンプルなグラフィカルインターフェイスを使用して IaC テンプレートを開発する、AWS Infrastructure Composer というサービスも提供しています。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 リソースの AWS SAM での指定方法など、いくつかの基本的な概念を習得できます。また、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)機能を使用して、テンプレートとコードファイルをローカルビルドマシンに保存します。この機能を使用するには、File System Access API に対応するブラウザが必要です。これにより、Web アプリケーションでローカルファイルシステム内のファイルの読み取り、書き込み、保存を行うことができます。Google Chrome または Microsoft Edge の使用が推奨されます。File System Access API の詳細については、「[What is the File System Access 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. [**Create function**] (関数の作成) をクリックします。

## 関数の 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. **[関数の概要]** ペインで、**[Application Composer にエクスポート]** を選択します。

   関数の設定とコードを 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) を参照して、必要な権限があることを確認してください。

**注記**  
関数を Infrastructure Composer にエクスポートする場合、Lambda が作成するバケットに標準の [Amazon S3 の料金](https://aws.amazon.com/s3/pricing)が適用されます。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 のキャンバスにドラッグアンドドロップして、アプリケーションを構築できるようになりました。この例では、Lambda 関数のトリガーとして Amazon SQS のシンプルなキューを追加し、データを書き込む関数に DynamoDB テーブルを追加します。

1. Amazon SQS トリガーを Lambda 関数に追加するには、次の手順を実行します。

   1. **[リソース]** パレットの検索フィールドに、「**SQS**」と入力します。

   1. **[SQS キュー]** リソースをキャンバスにドラッグし、Lambda 関数の左側に配置します。

   1. **[詳細]** を選択し、**[論理 ID]** に「**LambdaIaCQueue**」と入力します。

   1. **[保存]** を選択します。

   1. SQS キューカードの **[サブスクリプション]** ポートをクリックし、Lambda 関数カードの左側のポートにドラッグして、Amazon SQS リソースと Lambda リソースを接続します。2 つのリソースの間に線が表示されれば、接続に成功しています。また、Infrastructure Composer では、2 つのリソースが正常に接続されたことを示すメッセージもキャンバスの下部に表示されます。

1. 以下を実行して、Lambda 関数に Amazon DynamoDB テーブルを追加し、データを書き込みます。

   1. **[リソース]** パレットの検索フィールドに、「**DynamoDB**」と入力します。

   1. **[DynamoDB テーブル]** リソースをキャンバスにドラッグし、Lambda 関数の右側に配置します。

   1. **[詳細]** を選択し、**[論理 ID]** に「**LambdaIaCTable**」と入力します。

   1. **[保存]** を選択します。

   1. DynamoDB テーブルを Lambda 関数に接続するには、Lambda 関数カードの右側のポートをクリックして、DynamoDB カードの左側のポートにドラッグします。

これらのリソースを追加したところで、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)」を参照してください。
+ Amazon SQS キューを関数のトリガーとして指定する Lambda 関数定義の `Events` プロパティ

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

  `Events` プロパティは、1 つのイベントタイプと、そのタイプに依存する一連のプロパティで構成されます。Lambda 関数をトリガーするために設定できるさまざまな AWS のサービス と設定できるプロパティについては、「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)」を参照してください。
+ 追加した DynamoDB テーブルで CRUD オペレーションを実行する権限を関数に付与する新しい IAM ポリシー。

  ```
  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>

AWS SAM を使用し、Infrastructure Composer で作成したばかりのテンプレートを使用してサーバーレスアプリケーションをデプロイする場合は、まず 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 テーブル

また、Lambda 関数が Amazon SQS キューからメッセージを読み取り、DynamoDB テーブルで CRUD オペレーションを実行できるように、AWS SAM で必要な IAM ロールとポリシーを作成します。

## デプロイしたアプリケーションのテスト (オプション)
<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. **[テーブルアイテムの探索]** を選択します。**[返された項目]** ペインに、**[id]** `myKey` と **[値]** `myValue` がある項目が表示されるはずです。

# AWS CDK を使用した Lambda 関数のデプロイ
<a name="lambda-cdk-tutorial"></a>

AWS Cloud Development Kit (AWS CDK) は、選択したプログラミング言語を使用して、AWS クラウドインフラストラクチャの定義に使用できる、Infrastructure as Code (IaC) フレームワークです。独自のクラウドインフラストラクチャを定義するには、最初に、(CDK でサポートされている言語のいずれかで) 1 つ以上のスタックが含まれるアプリケーションを記述します。次に、それを CloudFormation テンプレートに合成して、AWS アカウント にリソースをデプロイします。このトピックの手順に従って、Amazon API Gateway エンドポイントからイベントを返す Lambda 関数をデプロイします。

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-cdk-lib` と呼ばれる単一パッケージですべての AWS のサービス の安定した構成を含んでいます。このパッケージは、プロジェクト開始時に依存関係としてインストールされます。特定のプログラミング言語で作業する場合、パッケージはプロジェクトを初めて構築するときにインストールされます。

## ステップ 2: AWS CDK スタックを定義する
<a name="lambda-cdk-step-2"></a>

CDK *スタック*は、AWS リソースを定義する 1 つ以上のコンストラクトのコレクションです。各 CDK スタックは、CDK アプリ内の CloudFormation スタックを表します。

CDK スタックを定義するには、希望するプログラミング言語の手順に従います。このスタックでは、以下を定義します。
+ 関数の論理名: `MyFunction`
+ `code` プロパティで指定された関数コードの場所。詳細については、「*AWS Cloud Development Kit (AWS CDK) API リファレンス*」の「[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 デプロイ](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 エンドポイントをコピーしてウェブブラウザに貼り付けるか、`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)

------