はじめに
この記事では、ローカルで作成した Lambda 関数を CodeCatalyst ワークフローでデプロイする方法について説明します。Lambda 関数をデプロイするために必要な設定やファイル構成、CDK プロジェクトの設定方法などについて詳しく説明します。実務でこのような方法で Lambda 関数をデプロイする機会があり、調べてみたところ情報が少なかったため、今回の記事を作成しました。
前提条件
- 実行環境:Codecatalyst
- CodeCatalyst にログインしていること
- CodeCatalyst でプロジェクトを作成していること
- ロールやセキュリティグループ、VPC などの設定が完了していること
Lambda デプロイプロジェクトのディレクトリ構成
このセクションでは、Lambda 関数のデプロイに関連するプロジェクトのディレクトリ構成について説明します。プロジェクト内の各ディレクトリやファイルが持つ役割を理解することで、プロジェクト全体の流れやデプロイプロセスの構造を把握しやすくなります。
ディレクトリ構造
以下は、このプロジェクトのディレクトリ構造を示したものです。
.
├── codecatalyst
│ ├── workflows
│ │ ├── deploy_lambda_workflow.yaml # ワークフローの定義
├── backend
│ ├── src
│ │ ├── deploy_lambda_test1
│ │ │ ├── lambda_function.py # Lambda 関数のソースコード
│ │ ├── deploy_lambda_test2
│ │ │ ├── lambda_function.py # Lambda 関数のソースコード
| ├── cdk.json # CDK 設定ファイル
| ├── dev_lambda.yml # Lambda 関数の設定
| ├── app.py # CDK アプリケーションのエントリーポイント
| ├── python_stack.py # Lambda スタックの構築
| ├── requirements.txt # ワークフローの実行に必要なライブラリ
各ディレクトリとファイルの説明
-
codecatalyst/workflows/deploy_lambda_workflow.yaml: Codecatalyst のワークフローを定義するファイルです。Lambda 関数をデプロイするためのワークフローを設定します。
-
backend/src/deploy_lambda_test1 および backend/src/deploy_lambda_test2: それぞれ異なる Lambda 関数のソースコードが格納されています。各ディレクトリ内には
lambda_function.py
ファイルがあり、これが Lambda 関数のエントリーポイントとなります。 -
backend/cdk.json: CDK プロジェクトの設定ファイルです。CDK が Lambda 関数をデプロイする際に必要な設定が記載されています。
-
backend/dev_lambda.yml: 各 Lambda 関数の追加設定が記載されたファイルです。VPC、セキュリティグループ、IAM ロールなどの設定が含まれます。
-
backend/app.py: CDK アプリケーションのエントリーポイントです。このファイルを実行することで、CDK スタックが構築されます。
-
backend/python_stack.py: CDK スタックの定義ファイルです。Lambda 関数や関連するリソースの設定がここで行われます。
-
backend/requirements.txt: ワークフローの実行に必要なライブラリが記載されています。ワークフローの実行時にこれらのライブラリがインストールされます。
Lambda デプロイ用のワークフローの設定
このセクションでは、Codecatalyst を使用して Lambda 関数をデプロイするためのワークフロー設定について詳しく説明します。Codecatalyst のワークフローを構築することで、特定の条件で Lambda 関数を自動的にビルドおよびデプロイできるようにします。
ワークフローの目的
このワークフローは、指定されたブランチにコードがプッシュされた際に自動的にトリガーされ、Lambda 関数をビルドして、AWS 環境にデプロイします。これにより、コードをプッシュするだけで、Lambda 関数が AWS 上で更新されるため、開発プロセスを効率化できます。
ワークフローの定義
ワークフローの定義ファイルは codecatalyst/workflows/deploy_lambda_workflow.yaml
です。ここでは、ワークフローのスキーマ、トリガー、アクションなどが定義されています。
-
SchemaVersion: ワークフローのスキーマバージョンを指定します。ここでは
"1.0"
を使用します。 -
Triggers: ワークフローをトリガーする条件を定義します。この例では、
dev_deploy_test
ブランチにコードがプッシュされるとワークフローがトリガーされます。 -
Actions: ワークフローが実行するアクションを定義します。以下の 3 つの主要なアクションがあります。
- BackendBuildAndPackage: Lambda 関数のソースコードをビルドし、パッケージします。ビルド後、アーティファクトとして結果を出力します。
- BackendCDKBootstrapAction: CDK をブートストラップし、AWS 環境への接続を確立します。このアクションは、ビルドが完了した後に実行されます。
- BackendCDKDeploy: ビルドしたアーティファクトを使って、CDK スタックをデプロイします。このアクションは、CDK のブートストラップが完了した後に実行されます。
ワークフローの設定
ワークフロー内の設定では、AWS アカウント ID、IAM ロール、環境名、リージョンなど、Lambda 関数をデプロイするために必要な情報を指定します。設定内容は以下の通りです。
- AWS_ACCOUNT_ID: Lambda 関数をデプロイする AWS アカウント ID を指定します。
- ROLE_NAME: ワークフローが使用する IAM ロール名を指定します。必要な権限があることを確認してください。
- ENVIRONMENT_NAME: Lambda 関数をデプロイする CodeCatalyst の環境名を指定します。
-
Region: Lambda 関数をデプロイするリージョンを指定します。ここでは
ap-northeast-1
を使用しています。
このようなワークフロー設定により、特定のブランチへのプッシュをきっかけに、Lambda 関数のビルドとデプロイが自動的に行われます。これにより、デプロイプロセスが効率化され、開発者の負担が軽減されます。
ワークフローの設定ファイル
-
codecatalyst/workflows/deploy_lambda_workflow.yaml
ファイルの構成は以下の通りです。AWS_ACCOUNT_ID: AWS アカウント ID を指定します。
ROLE_NAME: ロール名を指定します。
ENVIRONMENT_NAME: 環境名を指定します(CodeCatalyst 上で作成)。# デプロイメントワークフローの設定 Name: deploy_lambda_workflow SchemaVersion: "1.0" # スキーマのバージョンを指定 # トリガーの設定 Triggers: - Type: PUSH # PUSHイベントでトリガー Branches: - dev_deploy_test # トリガーされるブランチ # アクションの定義 Actions: # バックエンドのビルドとパッケージ BackendBuildAndPackage: Identifier: aws/build@v1 # AWS CodeCatalystのビルドアクション Inputs: Sources: - WorkflowSource # ワークフローのソース Outputs: Artifacts: - Name: backend # アーティファクト名 Files: - "**/*" # すべてのファイルを含む Configuration: Steps: - Run: echo "Building Backend Artifacts..." # ビルドステップでのメッセージ # CDKのブートストラップ BackendCDKBootstrapAction: Identifier: aws/cdk-bootstrap@v1 # AWS CDKのブートストラップアクション Inputs: Artifacts: - backend # バックエンドからのアーティファクト DependsOn: - BackendBuildAndPackage # ビルドアクションが完了後 Configuration: Region: ap-northeast-1 # デプロイ先のリージョン Environment: Name: { ENVIRONMENT_NAME } # 環境名 Connections: - Name: { AWS_ACCOUNT_ID } # AWSアカウントID Role: { ROLE_NAME } # IAMロール # CDKによるデプロイ BackendCDKDeploy: Identifier: aws/cdk-deploy@v1 # AWS CDKのデプロイアクション Inputs: Artifacts: - backend # バックエンドからのアーティファクト DependsOn: - BackendCDKBootstrapAction # ブートストラップアクションが完了後 Configuration: StackName: DeployLambdaStack # デプロイするCDKスタック名 CdkRootPath: backend/ # CDKプロジェクトのルートパス Region: ap-northeast-1 # デプロイ先のリージョン Context: '{"stack_name": "DeployLambdaStack"}' # CDKコンテキスト設定 Environment: Name: { ENVIRONMENT_NAME } # 環境名 Connections: - Name: { AWS_ACCOUNT_ID } # AWSアカウントID Role: { ROLE_NAME } # IAMロール
CDK プロジェクトの設定
このセクションでは、AWS Cloud Development Kit(CDK)を使用して Lambda 関数をデプロイするためのプロジェクト設定について説明します。CDK は、インフラストラクチャをコードとして定義し、AWS 環境にリソースをデプロイできる強力なツールです。
CDK プロジェクトの役割
CDK プロジェクトは、Lambda 関数を含む AWS リソースのデプロイを自動化するために使用されます。プロジェクト内で必要なリソースを定義し、CodeCatalyst ワークフローと連携してデプロイプロセスを効率化します。
cdk.json ファイル
cdk.json
ファイルは、CDK プロジェクトの設定を定義するファイルです。主に、CDK アプリケーションのエントリーポイントや追加の設定、CDK コンテキスト、およびデプロイ環境に関する情報が含まれます。
-
app: CDK アプリケーションのエントリーポイントを指定します。ここでは
python3 app.py
を指定しており、app.py
ファイルが CDK のメインスクリプトとして実行されます。 -
watch: ファイル変更の監視設定です。デプロイに関係のないファイルを除外したり、監視するファイルを指定することができます。
-
context: CDK コンテキスト設定です。プロジェクト内の異なるコンポーネント間で共有される情報を定義します。例えば、デフォルトの TLS バージョンや Lambda バージョンプロパティの認識など、プロジェクト全体で有効な設定が含まれます。
-
dev: デプロイ環境に関する情報です。AWS アカウント ID、リージョン、サブネット ID など、デプロイ先に関する設定が記載されています。
-
resources: プロジェクト内のリソースを定義するための設定です。Lambda 関数のソースコードやレイヤーの位置、または必要なライブラリファイルを指定します。
CDK プロジェクトの重要性
CDK プロジェクトの設定は、Lambda 関数を含む AWS リソースを効率的にデプロイするために重要です。適切に構成された cdk.json
ファイルは、デプロイプロセスをスムーズにし、将来の変更やスケーリングに対応しやすくなります。
このように、CDK プロジェクトの設定を理解することで、インフラストラクチャの定義とデプロイプロセスの管理を容易にし、開発プロセスの効率化を実現できます。
CDK プロジェクトの設定ファイル
-
backend/cdk.json
ファイルを編集します。cdk.json
ファイルには、CDK アプリケーションの設定を記述します。
今回のプロジェクトでは環境変数として AWS アカウント ID 等の情報を持たせています。{ "app": "python3 app.py", "watch": { "include": ["**"], "exclude": [ "README.md", "cdk*.json", "requirements*.txt", "source.bat", "**/__init__.py", "python/__pycache__", "tests" ] }, "context": { "@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true, "@aws-cdk/core:stackRelativeExports": true, "@aws-cdk/aws-rds:lowercaseDbIdentifier": true, "@aws-cdk/aws-lambda:recognizeVersionProps": true, "@aws-cdk/aws-lambda:recognizeLayerVersion": true, "@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true, "@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true, "@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true, "@aws-cdk/core:checkSecretUsage": true, "@aws-cdk/aws-iam:minimizePolicies": true, "@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true, "@aws-cdk/core:validateSnapshotRemovalPolicy": true, "@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true, "@aws-cdk/aws-s3:createDefaultLoggingPolicy": true, "@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true, "@aws-cdk/aws-apigateway:disableCloudWatchRole": true, "@aws-cdk/core:enablePartitionLiterals": true, "@aws-cdk/core:target-partitions": ["aws", "aws-cn"] }, "dev": { "account": "AWS_ACCOUNT_ID", "region": "ap-northeast-1", "subnetIds": ["subnetId1", "subnetId2"], "envPrefix": "dev_" }, "resources": { "layer": "layer", "lambdaFile": "lambda_function.py", "src": "src" } }
デプロイ用のライブラリのインストール
-
backend/requirements.txt
ファイルを編集します。ワークフローの実行に必要なライブラリを記述します。
attrs==22.1.0 aws-cdk-lib==2.50.0 boto3==1.24.95 botocore==1.27.95 cattrs==22.1.0 certifi==2023.7.22 cffi==1.15.1 charset-normalizer==2.1.1 constructs==10.1.132 coverage==6.5.0 cryptography==41.0.3 exceptiongroup==1.0.0rc9 idna==3.4 iniconfig==1.1.1 Jinja2==3.1.2 jmespath==1.0.1 jsii==1.69.0 MarkupSafe==2.1.1 moto==4.0.8 packaging==21.3 pluggy==1.0.0 publication==0.0.3 py==1.11.0 pycparser==2.21 pyparsing==3.0.9 pytest==7.1.3 pytest-cov==4.0.0 python-dateutil==2.8.2 pytz==2022.5 requests==2.31.0 responses==0.22.0 s3transfer==0.6.0 six==1.16.0 toml==0.10.2 tomli==2.0.1 typeguard==2.13.3 types-toml==0.10.8 typing_extensions==4.4.0 urllib3==1.26.12 Werkzeug==2.2.3 xmltodict==0.13.0
Lambda 関数の設定
このセクションでは、Lambda 関数の構成を記述するための設定ファイルについて説明します。AWS Lambda 関数は、AWS 上でサーバーレスアプリケーションを実行するために使用されます。Lambda 関数を正常にデプロイし、適切に動作させるためには、必要なリソースや設定を正確に記述することが重要です。
dev_lambda.yml ファイル
dev_lambda.yml
ファイルは、Lambda 関数の設定を定義する YAML ファイルです。Lambda 関数に関連する VPC、セキュリティグループ、IAM ロール、その他のリソース情報が含まれます。
-
Lambda 関数の識別子:
dev_lambda.yml
ファイル内では、異なる Lambda 関数を識別するためのキーが使用されます。たとえば、deploy_lambda_test1
やdeploy_lambda_test2
のように、Lambda 関数の名前が記載されています。 -
role: Lambda 関数が使用する IAM ロールを指定します。IAM ロールには、Lambda 関数が必要とする権限が付与されています。ARN(Amazon Resource Name)形式で指定します。
-
vpc: Lambda 関数が実行される VPC(Virtual Private Cloud)を指定します。Lambda 関数が VPC 内で実行される場合、VPC の ID を記載します。
-
securityGroupIds: Lambda 関数が所属するセキュリティグループの ID を指定します。セキュリティグループは、Lambda 関数のネットワークアクセスを制御するために使用されます。
以下は、dev_lambda.yml
の例です。
deploy_lambda_test1:
role: "arn:aws:iam::871499774512:role/lambda-role"
vpc: "vpc-0b3b3b3b3b3b3b3b3"
securityGroupIds:
- "sg-0b3b3b3b3b3b3b3b3"
- "sg-1a2b3c4d5e6f7g8h9"
deploy_lambda_test2:
role: "arn:aws:iam::871499774512:role/lambda-role"
vpc: "vpc-0b3b3b3b3b3b3b3b3"
securityGroupIds:
- "sg-0b3b3b3b3b3b3b3b3"
- "sg-1a2b3c4d5e6f7g8h9"
Lambda 関数の設定の重要性
Lambda 関数の設定は、デプロイ時に正確に指定される必要があります。IAM ロール、VPC、およびセキュリティグループの設定は、Lambda 関数が適切な権限とネットワークアクセスを持つことを保証します。
特に、Lambda 関数が VPC 内で実行される場合、適切なセキュリティグループとサブネットを指定することは、セキュリティとネットワーク通信の確保に不可欠です。
このように、Lambda 関数の設定ファイルは、デプロイプロセスにおいて非常に重要な役割を果たします。正確に設定することで、Lambda 関数が期待どおりに動作し、セキュリティやネットワーク要件を満たすことができます。
CDK アプリケーションのエントリーポイントの設定
このセクションでは、AWS Cloud Development Kit(CDK)を使用して AWS リソースを定義およびデプロイするためのエントリーポイント、すなわち app.py
ファイルの設定について説明します。CDK アプリケーションのエントリーポイントは、CDK によるインフラストラクチャのコード化の開始点となる重要なコンポーネントです。
app.py の役割
app.py
は、CDK アプリケーションの中核を成すスクリプトであり、CDK のすべてのリソーススタックがここから起動されます。このファイルでは、CDK で定義されるリソーススタック(この場合は Lambda 関数を含むスタック)のインスタンスを作成し、CDK アプリケーションを初期化して実行します。
app.py の設定とコードの概要
以下は app.py
の典型的な設定とその説明です。
stack_name は deploy_lambda_workflow.yaml のスタック名と合わせる必要があります。
ここがずれているとスタックが正常にデプロイされません。自分もハマりました。
#!/usr/bin/env python3
import os
import aws_cdk as cdk
from python_stack import PythonStack
# 環境変数からスタック名を取得し、デフォルト値を設定
stack_name = "DeployLambdaStack" if "LOCAL_TESTING" not in os.environ else "PythonStack"
app = cdk.App()
PythonStack(
app,
stack_name,
)
app.synth()
-
スクリプトのシェバン:
#!/usr/bin/env python3
これは Unix ベースのシステムでスクリプトが Python 3 環境で実行されることを保証するためのものです。 -
モジュールのインポート: 必要なライブラリとローカルに定義された
PythonStack
クラスをインポートします。 -
環境変数の確認:
os.environ
を使用して環境変数LOCAL_TESTING
の有無をチェックし、スタック名を動的に設定します。これにより、ローカルテストと本番デプロイで異なる設定を適用することが可能になります。 -
CDK アプリケーションの初期化:
cdk.App()
を呼び出して CDK アプリケーションを初期化し、PythonStack
インスタンスをアプリケーションに追加します。 -
アプリケーションの合成:
app.synth()
メソッドを呼び出して CDK アプリケーションの合成を行い、CloudFormation テンプレートを生成します。これにより、AWS 環境にデプロイする準備が整います。
エントリーポイントの重要性
app.py
ファイルは、CDK によるデプロイプロセスにおいて中心的な役割を果たします。正確な初期化とリソースの定義を行うことで、AWS 上に正しくインフラストラクチャをデプロイすることができます。また、このスクリプトはプロジェクトの構造を理解する上での入口点ともなるため、他の開発者がプロジェクトに貢献しやすくなる重要な要素です。
このように、app.py
の適切な設定は、CDK を使用したインフラストラクチャの自動化と効率化に不可欠です。正確なリソースの定義と初期化を行うことで、AWS 環境にリソースを迅速かつ正確にデプロイすることができます。
Lambda スタックの構築
このセクションでは、AWS Cloud Development Kit(CDK)を使用して Lambda 関数と関連するリソースを構築するための設定とプロセスを説明します。Lambda スタックは、Lambda 関数、セキュリティ、ネットワーク設定など、アプリケーションのサーバーレスコンポーネントをまとめたものです。
python_stack.py の役割
python_stack.py
は、CDK スタックを定義する Python ファイルです。このファイルでは、Lambda 関数、VPC、セキュリティグループ、IAM ロールなど、必要な AWS リソースを定義します。また、他の設定ファイルから情報を読み込み、環境ごとの設定を適用する役割も担います。
CDK スタックの定義
以下は python_stack.py
の基本的な構成と、その説明です。
import os
import json
import yaml
from os import path
from pathlib import Path
from aws_cdk import (
Stack,
CfnOutput,
aws_lambda as lambda_,
aws_ec2 as ec2,
aws_iam as iam,
Duration,
)
from constructs import Construct
# ファイルパスの取得
cdk_json_path = os.path.join(os.path.dirname(__file__), "cdk.json")
lambda_yml_path = os.path.join(os.path.dirname(__file__), "dev_lambda.yml")
# 環境変数を取得する関数
def get_env_json(path):
with open(path, "r") as f:
return json.load(f)
# YAMLファイルを取得する関数
def get_env_yml(path):
with open(path, "r") as f:
return yaml.safe_load(f)
# スタッククラス
class PythonStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs):
# 環境変数とLambda設定を取得
env = get_env_json(cdk_json_path)
config = env["dev"]
lambda_env = get_env_yml(lambda_yml_path)
super().__init__(scope, construct_id, env={"region": config["region"], "account": config["account"]}, **kwargs)
# サブネットの取得
subnets = [ec2.Subnet.from_subnet_id(self, f"ExistingSubnet{i+1}", subnet_id) for i, subnet_id in enumerate(config["subnetIds"])]
# Lambda関数の作成
self.create_lambdas(env, config, lambda_env, subnets)
def create_lambdas(self, env, config, lambda_env, subnets):
src_dir_path = Path(__file__).parent / env["resources"]["src"]
for lambda_subdir in [d for d in src_dir_path.iterdir() if d.is_dir()]:
lambda_name = f"{lambda_subdir.name}"
# Lambda設定が存在する場合のみ作成
lambda_vals = lambda_env.get(lambda_name, None)
if lambda_vals:
# セキュリティグループの取得
security_groups = [
ec2.SecurityGroup.from_security_group_id(self, f"ExistingSecurityGroup_{lambda_name}{idx+1}", security_group_id=sg_id)
for idx, sg_id in enumerate(lambda_vals["securityGroupIds"])
]
existing_vpc = ec2.Vpc.from_lookup(self, f"ExistingVPC{lambda_name}", vpc_id=lambda_vals["vpc"]) if lambda_vals["vpc"] else None
lambda_function = lambda_.Function(
self,
f"LambdaFunction{lambda_name}",
runtime=lambda_.Runtime.PYTHON_3_9,
handler=env["resources"]["lambdaFile"].replace(".py", ".lambda_handler"),
code=lambda_.Code.from_asset(path.join(path.dirname(__file__), lambda_subdir)),
function_name=f"{config['envPrefix']}{lambda_name}",
timeout=Duration.seconds(600),
role=iam.Role.from_role_arn(self, f"ExistingRole_{lambda_name}", role_arn=lambda_vals["role"], mutable=False),
vpc=existing_vpc,
security_groups=security_groups,
vpc_subnets=ec2.SubnetSelection(subnets=subnets),
)
CfnOutput(self, f"LambdaFunction{lambda_name}Arn", value=lambda_function.function_arn)
このコードでは、CDK スタックの定義と、Lambda 関数、VPC、セキュリティグループ、IAM ロールなどのリソースの構築方法が示されています。
Lambda スタックの構築のポイント
-
外部設定ファイルの読み込み:
cdk.json
やdev_lambda.yml
などのファイルから必要な設定を読み込むことで、スタックの構築に必要な情報を取得します。 -
VPC とセキュリティグループの設定: Lambda 関数が実行される VPC と、関連するセキュリティグループを定義します。これにより、Lambda 関数のネットワークセキュリティが確保されます。
-
Lambda 関数の定義: Lambda 関数自体の設定を行います。ランタイム、ハンドラー、ソースコード、IAM ロールなど、Lambda 関数の重要な構成要素を定義します。
-
構築の流れ: 最初に VPC やセキュリティグループなどの基礎リソースを取得し、その後 Lambda 関数を定義します。これにより、デプロイプロセスが効率的かつ安全に進行します。
このように、python_stack.py
を使用して CDK スタックを構築することで、AWS リソースを効率的に定義し、Lambda 関数を確実にデプロイすることができます。スタックの構築プロセスを理解することで、将来のプロジェクトで柔軟に変更や拡張を行うための基盤が構築されます。
ワークフローの実行
-
ローカルで作成した Lambda 関数を CodeCatalyst ワークフローでデプロイします。
今回のワークフローは、
dev_deploy_test
ブランチに push された際に実行されます。$ git add . $ git commit -m "Add Lambda function deployment workflow" $ git push origin dev_deploy_test
-
CodeCatalyst でワークフローが実行されると、Lambda 関数がデプロイされます。
ワークフローの実行結果を確認し、Lambda 関数が正常にデプロイされたことを確認します。
まとめ
この記事では、ローカルで作成した Lambda 関数を CodeCatalyst ワークフローでデプロイする方法について説明しました。ここからさらにレイヤー情報の追加やレイヤーバージョンのデプロイ、APIGateway などの連携も行ったので追加の記事で上げていこうと思います。同じように Lambda 関数をデプロイする際に詰まっている方の参考になれば幸いです。