1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS CDKでLambda関数のソースコード二重管理を解消した話

Posted at

はじめに

AWS CDKを使ってLambda関数をデプロイする際、ソースコードの管理方法に悩んだことはありませんか?

本記事では、Lambda関数のデプロイ用に別フォルダへコードをコピーして管理していた運用を見直し、元のソースコードを直接参照する方法に改善した事例を紹介します。この改善により、コードの二重管理が不要になり、メンテナンス性が大幅に向上しました。

AWS CDKとは

AWS CDK(Cloud Development Kit)は、プログラミング言語を使ってAWSのインフラをコードで定義できるフレームワークです。Python、TypeScript、Javaなどの言語でインフラを記述でき、CloudFormationテンプレートを自動生成してくれます。

Lambda関数をデプロイする際は、Code.from_asset()メソッドを使ってローカルのディレクトリを指定することで、そのディレクトリ配下のファイルがLambda関数としてデプロイされます。

今回の課題

従来の構成

プロジェクトでは以下のようなディレクトリ構成でLambda関数を管理していました。

project/
├── functions/                    # 実際の開発用ソースコード
│   ├── commonUtils.py           # 共通ユーティリティ
│   ├── functionProcessData.py   # Lambda関数A
│   ├── functionGetData.py       # Lambda関数B
│   └── functionPostData.py      # Lambda関数C
│
└── cdk_deploy/
    └── assets/                  # デプロイ用コピー先
        ├── lambdaProcessData/
        │   ├── commonUtils.py
        │   └── functionProcessData.py
        ├── lambdaGetData/
        │   ├── commonUtils.py
        │   └── functionGetData.py
        └── lambdaPostData/
            ├── commonUtils.py
            └── functionPostData.py

問題点

この構成には以下の問題がありました。

  1. 二重管理の手間: functions/フォルダで開発したコードを、デプロイ前に毎回assets/フォルダにコピーする必要がある
  2. コピー忘れのリスク: コピーを忘れると古いコードがデプロイされてしまう(つまり、更新されない)
  3. ストレージの無駄: 同じコードが複数箇所に存在する
  4. メンテナンス性の低下: Lambda関数が増えるたびにコピースクリプトの修正が必要

解決策

改善後の構成

functions/フォルダのコードを直接参照するように変更しました。

project/
├── functions/                    # 実際の開発用ソースコード
│   ├── commonUtils.py           # 共通ユーティリティ
│   ├── functionProcessData.py   # Lambda関数A
│   ├── functionGetData.py       # Lambda関数B
│   └── functionPostData.py      # Lambda関数C
│
└── cdk_deploy/
    └── cdk/
        └── lambda_stack.py      # CDKスタック定義

assets/フォルダとdeploy_copy.pyは不要になりました。

実装方法

CDKのLambda Stackに、デプロイ時に必要なファイルを動的に集める処理を追加しました。

# lambda_stack.py
import os
import shutil
from aws_cdk import Duration, RemovalPolicy, Stack
from aws_cdk import aws_iam as _iam
from aws_cdk import aws_lambda as _lambda
from constructs import Construct


class LambdaFunctionStack(Stack):
    """Lambda関数をデプロイするCDKスタック"""

    def __init__(self, scope: Construct, construct_id: str,
                 lambda_role: _iam.Role,
                 layer_version: object,
                 **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)
        
        self.lambda_role = lambda_role
        
        # Lambda関数のデプロイ
        lambda_process_data = self.deploy_lambda_function(
            "ProcessData", 
            layers=[], 
            role=self.lambda_role
        )

    def deploy_lambda_function(self, name, layers, role):
        """Lambda関数デプロイメソッド
        
        :param name: 関数名(例: ProcessData)
        :param layers: Lambdaレイヤー
        :param role: IAMロール
        :return: Lambda関数オブジェクト
        """
        lambda_name = 'lambda' + name
        function_name = 'function' + name
        
        # functionsフォルダから直接参照するための一時ディレクトリを作成
        asset_path = self._create_lambda_asset(function_name)

        lambda_function = _lambda.Function(
            self,
            lambda_name,
            handler=function_name + '.lambda_handler',
            function_name=lambda_name,
            architecture=_lambda.Architecture.ARM_64,
            runtime=_lambda.Runtime.PYTHON_3_10,
            code=_lambda.Code.from_asset(asset_path),
            role=role,
            timeout=Duration.seconds(30),
            memory_size=1024,
            layers=layers,
        )
        lambda_function.apply_removal_policy(RemovalPolicy.DESTROY)

        return lambda_function

    def _create_lambda_asset(self, function_name):
        """functionsフォルダから必要なファイルを集めた一時assetディレクトリを作成
        
        :param function_name: 関数名(例: functionProcessData)
        :return: assetディレクトリのパス
        """
        # プロジェクトルートのfunctionsフォルダへのパス
        current_dir = os.path.dirname(os.path.abspath(__file__))
        project_root = os.path.abspath(os.path.join(current_dir, '..', '..'))
        functions_dir = os.path.join(project_root, 'functions')
        
        # cdk.outディレクトリ内に一時ディレクトリを作成
        asset_dir = os.path.join(
            project_root, 
            'cdk_deploy', 
            'cdk.out', 
            'assets', 
            function_name
        )
        os.makedirs(asset_dir, exist_ok=True)
        
        # 必要なファイルをコピー
        # 1. メインの関数ファイル
        main_function = os.path.join(functions_dir, f'{function_name}.py')
        if os.path.exists(main_function):
            shutil.copy2(main_function, asset_dir)
        
        # 2. 共通ユーティリティファイル
        common_utils = os.path.join(functions_dir, 'commonUtils.py')
        if os.path.exists(common_utils):
            shutil.copy2(common_utils, asset_dir)
        
        return asset_dir

ポイント解説

1. 一時ディレクトリの作成

cdk.out/assets/配下に関数ごとの一時ディレクトリを作成します。このディレクトリはCDKのビルド成果物として扱われ、デプロイ後も残るため、差分デプロイが効率的に行えます。

asset_dir = os.path.join(
    project_root, 
    'cdk_deploy', 
    'cdk.out', 
    'assets', 
    function_name
)
os.makedirs(asset_dir, exist_ok=True)

2. 必要なファイルのみをコピー

各Lambda関数に必要なファイル(メイン関数ファイルと共通ユーティリティ)だけを一時ディレクトリにコピーします。

# メインの関数ファイル
main_function = os.path.join(functions_dir, f'{function_name}.py')
if os.path.exists(main_function):
    shutil.copy2(main_function, asset_dir)

# 共通ユーティリティファイル
common_utils = os.path.join(functions_dir, 'commonUtils.py')
if os.path.exists(common_utils):
    shutil.copy2(common_utils, asset_dir)

3. CDKのassetとして指定

作成した一時ディレクトリのパスをCode.from_asset()に渡すことで、CDKが自動的にLambda関数としてデプロイします。

code=_lambda.Code.from_asset(asset_path)

改善効果

この変更により、以下の効果が得られました。

  1. 二重管理の解消: functions/フォルダのコードを直接参照するため、コピー作業が不要に
  2. デプロイの簡素化: cdk deployコマンドだけでデプロイが完了
  3. コピー忘れのリスク排除: 常に最新のコードがデプロイされる
  4. メンテナンス性の向上: 新しいLambda関数を追加する際も、deploy_lambda_function()を呼び出すだけ

まとめ

AWS CDKでLambda関数をデプロイする際、ソースコードの二重管理を解消する方法を紹介しました。

従来はデプロイ用に別フォルダへコードをコピーしていましたが、CDKスタック内で一時ディレクトリを動的に作成することで、元のソースコードを直接参照できるようになりました。

この改善により、開発効率が向上し、コピー忘れなどのヒューマンエラーも防げるようになりました。同様の課題を抱えている方の参考になれば幸いです。

参考リンク

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?