AWS Lambdaレイヤー化＆自動バージョン管理 ― 作業全体のまとめ

# AWS Lambda Layer + SAM まとめ

　現在進めているプロジェクトにおいて、これまではlambdaのコードを直接いじっていたが、同じ関数を何度も繰り返し利用する場面とコードの更新の際に全ての関数を開き、モジュール化しているコードを修正しなければならなかった。今回、AWS SAMを利用することで、モジュールのレイヤー化及びその環境変数やバージョン管理を一括に行う。
　この記事は、MySQL 接続ユーティリティを共通コードとして **Lambda Layer** 化し、AWS SAM を使って **自動バージョン管理**＆全関数反映を行う手順の備忘録である。
 SAMを用いることによってレイヤーの一元管理が可能となり、レイヤー機能の更新の際にすべての任意のレイヤーを使用しているすべての関数に対してバージョンアップが可能になる。また、samで管理することによりgitでのバージョン管理が可能となる。

---

## 目的

- 必要な Python ライブラリを Layer にまとめる  
- `sam build && sam deploy` のみで **Layer の新バージョン発行 → すべての関数に即時反映**

---

## 開発環境

- **Python**: 3.11.x  
- **AWS CLI**: v2
- **SAM CLI**: 1.x  
- （任意）**Docker**: ビルドにコンテナを使う場合

---

## 環境構築

### 1. AWS CLI v2 インストール & 設定

AWS CLI インストール : https://awscli.amazonaws.com/AWSCLIV2.msi

以下で接続のための設定を行う。
各種キーは**iam**のロールから発行できる

```bash

# 資格情報プロファイル作成
aws configure --profile sam-dev
# → Access Key, Secret Key, Default region を入力

aws --version　# インストールされているかどうか確認する

```

### 2. AWS SAM CLI のインストール


AWS SAM CLI のインストール : https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html

``` powershell
sam --version #インストールされているかどうか確認
```

### 3.プロジェクトの作成
 これで初期化する、これ実行後に現在いるフォルダのルートディレクトリにsam用のでディレクトリが作成される
```
sam init
```
この後プロジェクトを作成する

### 4.デプロイ
```
sam deploy --guided --profile sam-dev

＃すでにsamtemplate.tomlが生成されている場合は以下でおｋ！
sam deploy
```
1 回目のみスタック名・リージョン・S3 バケット名などを対話入力。
`samconfig.toml` が生成され，次回からは sam deploy だけでOK。


---

## 新しい Lambda 関数を追加して SAM でデプロイする流れ

AWS SAM (Serverless Application Model) を用いて **新しい Lambda 関数** を追加・デプロイする一連の手順を示します。

---

### 1. `template.yaml` に関数リソースを追加

```yaml
Resources:
  MyNewFunction:                # ★好きな論理名
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: my-new-function   # AWS 上の名前（省略可）
      Handler: app.handler            # ファイル名.関数名
      Runtime: python3.11             # 例: python3.11 / nodejs18.x
      CodeUri: my_new_function/       # コードを置くフォルダ
      MemorySize: 128
      Timeout: 10
      Policies:
        - AWSLambdaBasicExecutionRole
```

下記の情報は各lambda関数ごとに設定が必要。

| プロパティ | 説明 |
|---------|---------|
| FunctionName | コンソールに表示される関数名（省略時はスタック名 + 論理名）
| Handler | <ファイル名>.<関数名> 形式でエントリポイントを指定
| Runtime | 使用ランタイム（Python, Node.js など）
| CodeUri | 関数コードを配置するディレクトリ
| Policies | 付与する IAM 権限（例: AWSLambdaBasicExecutionRole） 


### 2. プロジェクト構成(例)

　関数を作成したいときはルートディレクトリに作りたい関数のフォルダを作成し、template.yamlに関数ごとにプロパティを書き込む。また、requestモジュールなどのパッケージはAWSのlambdaに元々組み込まれていないため、外付けでインストールする必要がある。インストールする際は、commom_layer/pythonの下にインストールする。

CONNECTRAYER/ 
├── common_layer/ ← Layer 用ディレクトリ 
│ └── python/ 
│ 　　├── connect_db.py ← 共通モジュール (今回はconnect_db.py)
│ 　　├── mysql/ … ← pip install -t で展開されたライブラリ 
│ 　　└── mysql_connector_python-*.dist-info/ 
├── db_client/ ← Lambda 関数用フォルダ ここにメイン処理を書き加える
│ 　├── lambda_function.py ← Handler 本体 
│ 　└── init.py 
├── template.yaml ← SAM テンプレート 
└── samconfig.toml ← ガイド付きデプロイ設定

---

## 共通モジュール：`connect_db.py`

　ここに各ファイルで使いたい共通のレイヤーを書き込む。また、別のパッケージを作成したいとき、同じディレクトリに別のファイルを作成する

```python
# common_layer/python/connect_db.py
import os
import mysql.connector
import logging

logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

def connect_db(path):
    print("test") #ここにレイヤー処理を書き加えていく
    return 
```

---
## SAM テンプレート：template.yaml

template.yamlの例は以下のようになる。

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: ConnectLayer + DbClientFunction

Globals:
  Function:
    Timeout: 10
    Tracing: Active
    LoggingConfig:
      LogFormat: JSON

Resources:
  ConnectLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: common-layer
      Description: MySQL 接続ユーティリティ
      ContentUri: common_layer/
      CompatibleRuntimes: [ python3.11 ]
      RetentionPolicy: Delete

  DbClientFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: db_client/
      Handler: lambda_function.lambda_handler
      Runtime: python3.11
      Layers:
        - !Ref ConnectLayer
      Environment:
        Variables:
          DB_HOST:     your-db-host
          DB_USER:     your-user
          DB_PASSWORD: your-password
          DB_NAME:     sampledb
          DB_PORT:     '114514'
      Events:
        ApiInvoke:
          Type: Api
          Properties:
            Path: /hello
            Method: get

Outputs:
  ApiUrl:
    Description: API Gateway URL
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello"
  DbClientFunctionArn:
    Description: Lambda ARN
    Value: !GetAtt DbClientFunction.Arn

```

---

## ビルド & デプロイ

初回時以降は、以下のように実行し、

```bash
# 一括ビルド & デプロイ
sam build
sam deploy
```

---

## ローカルテスト

ローカルテストを行う場合は以下のように実行する

```bash
## 単体呼び出し
echo '{}' > events/event.json
sam local invoke DbClientFunction -e events/event.json

# HTTP API をローカル起動
sam local start-api
curl http://127.0.0.1:3000/hello
```
---
## 運用ポイント
- RetentionPolicy: Delete で古い LayerVersion は自動削除

- 環境変数は SAM テンプレートで一元管理（Secrets Manager 推奨）

- CI/CD（GitHub Actions 等）に sam build && sam deploy を組み込む

---
## 効果
- 共通 DB 接続コードを 1 か所 で管理

- 修正 → sam deploy だけで 全関数に即反映

- 関数 ZIP が軽量化 → Cold Start 短縮

- チームでのオンボーディングがスムーズ

- gitでバージョン管理が可能 


メモ
- 初期セットアップ方法
- samとは