AWS SAMとApplication Composerで効率的なIaC環境を構築

# この記事は
新サービスの構築において調べたことや解決した課題などについて備忘も兼ねて書いたものです。
（そのため、後日「こっちの方がよかった！」とか「もっとこうしておけばよかった！」といったことがあるかもしれません）

# 課題
AWSを利用してインフラ構築を行う際、管理が煩雑になることはよくある問題です。
各種サービスの設定や連携状況を手作業で行っていると、管理が大変になり、ミスを引き起こす可能性もあります。
そこで、自動化を実現することで、作業の効率化とミスの削減を目指したいと考えました。

# 考えた方法
この問題を解決するためには、Infrastructure as Code（IaC）を導入すれば、設定をコードで管理し、一元的に管理することができると考えました。
AWSでは、このIaCを実現するためのツールとして、CloudFormationやSAM（Serverless Application Model）が提供されています。
さらに、各種サービスの連携状況を視覚的に確認できるツールとしてAWS Application Composerも利用できます。

# 今日の目標

初日として、まずはSAMとCloudFormationを使って簡単なサーバーレスアプリケーションを作成し、その構成をAWS Application Composerで視覚的に表示することを目指します。

# 手順・実装内容

## AWS CLIのインストール
以下のコマンドを利用してAWS CLIをインストールします。
```
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
```

## AWSの認証情報登録
AWSのIAMでユーザーを作成し、アクセスキーとシークレットキーを取得した上で、以下のコマンドを実行します。
```
aws configure
```

なお、IAMユーザーにいくつかCloudFormation関連の権限が必要でした。
一部今回の作業に直接は関係しないもの（=AWSコンソール上で必要だったもの）もありますが下記を設定しています。
```JSON
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "cloudformation:GetStackPolicy",
                "cloudformation:DeleteStack",
                "cloudformation:CreateChangeSet",
                "cloudformation:DescribeChangeSet",
                "cloudformation:ExecuteChangeSet"
            ],
            "Resource": "XXXXXXX"
        }
    ]
}
```

## SAM CLIのインストール
以下のコマンドを利用してSAM CLIをインストールします。（インストーラーは事前に[入手](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/install-sam-cli.html)しておいてください）
```
sudo installer -pkg aws-sam-cli-macos-arm64.pkg -target /
```

## SAMの初期化
以下のコマンドでSAMを初期化します。
```
sam init
```
今回は後々DynamoDBに書き込みをする予定だったので14のテンプレートを選択しました。
```
Which template source would you like to use?
  1 - AWS Quick Start Templates
  2 - Custom Template Location
Choice: 1

Choose an AWS Quick Start application template
  1 - Hello World Example
  2 - Data processing
  ・
  ・
  ・
  14 - DynamoDB Example
  15 - Machine Learning
Template: 14 
```

## SAMテンプレートの編集
DynamoDBを使用するサンプルテンプレートを基に独自の設定を加えます。
```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: |
  pj-xxxxx
  Sample SAM Template for pj-xxxxx
Globals:
  Function:
    Timeout: 3
Resources:
  Event:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: id
        Type: String
  postEvent:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: ./postEvent
      Handler: handler.handler
      Runtime: python3.9
      Environment:
        Variables:
          EVENT_TABLE_NAME: !Ref Event
          EVENT_TABLE_ARN: !GetAtt Event.Arn
      Policies:
        - DynamoDBWritePolicy:
            TableName: !Ref Event
        - DynamoDBCrudPolicy:
            TableName: !Ref Event
      MemorySize: 3008
      Timeout: 30
      Events:
        EventApi:
          Type: Api
          Properties:
            Path: /event
            Method: POST
Outputs:
  EventApi:
    Description: API Gateway endpoint URL for Prod stage for Post function
    Value: !Sub https://${ServerlessRestApi}.execute-api.${AWS::Region}.${AWS::URLSuffix}/Prod/
  postEvent:
    Description: Post Lambda Function ARN
    Value: !GetAtt postEvent.Arn
  Event:
    Description: DynamoDB table name
    Value: !GetAtt Event.Arn
```

/eventにpostしたらpostEventというlambda関数を通じてeventテーブルに書き込みが発生する、という想定で修正をしました。

## Lambda関数の更新
今回は実際に動くものを作るのが目標ではないので、以下のようにLambda関数を編集して、単にメッセージを表示するようにします。
```python
import json


def handler(event, context):
    print('Hello from postEvent!')

    return {}
```

## SAMテンプレートのビルドとデプロイ
以下のコマンドを実行してSAMテンプレートをビルドし、AWSへデプロイします。
```
sam build
sam deploy --guided
```
今回は下記のようにしました
```
Stack Name [sam-app]: 適切な名前を入力
AWS Region [ap-northeast-1]: 何も入力せずにEnter（東京リージョンの場合はap-northeast-1）
Confirm changes before deploy [y/N]: y
Allow SAM CLI IAM role creation [Y/n]: Y
Disable rollback [y/N]: N
postEvent has no authentication. Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: Y
SAM configuration file [samconfig.toml]: 
SAM configuration environment [default]: 
```



## ローカルでの実行
以下のコマンドでLambda関数をローカルで実行します。
```
sam local invoke 
```
ここまでで正常にデプロイができ、APIも動いていることが確認できました。


## AWS Application Composerでの確認
最後にAWS Application ComposerでSAMテンプレートを開き、視覚的に構成を確認します。

![スクリーンショット 2023-07-18 22.02.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3476743/35d688d9-d202-454a-89ad-ca8233b24693.png)


以上の手順により、AWS SAMとApplication Composerを使用した効率的なIaC環境を構築することができました。今後はこの基盤を活用して、さらに効率的なインフラ管理を進めていきます。