はじめに
AWS Lambdaは、サーバーレスでイベント駆動型のコンピューティングサービスです。従来のLambda関数ではzipファイルでコードをアップロードしていましたが、コンテナイメージを使用することで、より柔軟で強力な開発・デプロイが可能になります。
本記事では、Infrastructure as CodeツールであるTerraformを用いて、Lambda関数として実行するコンテナイメージを構築し、AWS環境へデプロイする手順を解説します。
制作したレポジトリはこちらです。
参考にしたサイト
目的
Lambda関数をコンテナイメージで実行することにより、柔軟性とパフォーマンスを向上させることを目指します。
インフラ構成
以下のAWSサービスを用いてインフラを構築します。
- ECR: Dockerイメージを保存するプライベートなレジストリ
- Lambda: サーバーレスでコードを実行するサービス
- IAM: AWSリソースへのアクセスを制御するサービス
PythonファイルをLambdaにアップロードする場合との比較: メリットとデメリット
従来のzipファイルアップロードと比較した、コンテナイメージを使用するメリットとデメリットは以下の点が挙げられます。
メリット
- 一貫性と依存関係の管理: コンテナイメージは依存関係や環境設定を含む一貫した実行環境を提供
- パフォーマンス: コンテナイメージは迅速にデプロイおよびスケール可能
- 柔軟性: カスタムランタイムや特定のOSライブラリが必要な場合にも対応可能
デメリット
- 複雑さ: コンテナのビルドと管理が複雑
- ビルド時間: コンテナイメージのビルドに時間がかかることがある
- コスト: コンテナレジストリの使用には追加コストが発生
- ファイルの確認: Lambda管理画面で個別のファイルを確認できない
実装方法
IAM
IAMロールはLambda関数がAWSリソースにアクセスするための許可を管理します。
resource "aws_iam_role" "lambda_role" {
name = "lambda_role"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = "sts:AssumeRole",
Effect = "Allow",
Principal = {
Service = "lambda.amazonaws.com",
},
},
],
})
tags = {
Name = "${var.app_name}-lambda-iam-role"
}
}
IAMポリシーはLambda関数が必要とする権限を指定します。
resource "aws_iam_policy" "lambda_policy" {
name = "lambda_policy"
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"ecr:*"
],
Resource = "*",
Effect = "Allow"
}
]
})
}
IAMポリシーをIAMロールにアタッチして、ポリシーの権限をロールに委任します。
resource "aws_iam_policy_attachment" "lambda_role_attachment" {
name = "${var.app_name}-lambda-attach"
roles = ["${aws_iam_role.lambda_role.name}"]
policy_arn = aws_iam_policy.lambda_policy.arn
}
Lambda
Lambda関数をTerraformで定義する際には、以下のような設定を行います。
resource "aws_lambda_function" "main" {
function_name = var.lambda_function_name
package_type = "Image"
image_uri = "${var.lambda_repository_url}:latest"
description = "lambda_function"
role = var.lambda_iam_role
publish = true
memory_size = 128
timeout = 30
depends_on = [aws_cloudwatch_log_group.lambda]
tags = {
Name = "${var.app_name}-lamdba"
}
}
Lambda関数のログを保存するために、CloudWatchロググループを設定します。
resource "aws_cloudwatch_log_group" "lambda" {
name = "/aws/lambda/${var.lambda_function_name}"
}
Docker for Lambda
Lambda関数を実行するためのDockerfileを以下のように作成します。
FROM public.ecr.aws/lambda/python:3.12
# Copy requirements.txt
COPY requirements.txt ${LAMBDA_TASK_ROOT}
# Install the specified packages
RUN pip install --no-cache-dir -r requirements.txt
# Copy function code
COPY lambda_function.py ${LAMBDA_TASK_ROOT}
# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)
CMD [ "lambda_function.handler" ]
pythonのライブラリーをインストールします。
boto3
不要なファイルやディレクトリを除外する.dockerignoreファイルを設定します。
# 一般的な除外ルール
.DS_Store
.AppleDouble
.LSOverride
Icon
._*
# ファイルシステム関連
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# iCloud関連
*.icloud
# Xcode関連
*.xcodeproj
xcuserdata/
build/
DerivedData/
# その他
*.symlink
*.localized
*.vmx
*.vmdk
# Dockerとgitの除外ルール
.git
*Dockerfile*
*docker-compose*
実際のLambda関数のコードは以下のようになります。
import sys
def handler(event, context):
return 'Hello from AWS Lambda using Python' + sys.version + '!'
この設定により、Dockerを使用してLambda関数のコンテナイメージをビルドし、AWS Lambdaで実行できる準備が整います。Lambda関数の依存関係や実装を容易に管理し、柔軟性とパフォーマンスを向上させることができます。
結果
以下のテスト結果になりました。
まとめ
Terraformを使用してLambda関数のコンテナイメージを構築することで、AWS上でのアプリケーションの柔軟性と効率を大幅に向上させることができます。本記事で紹介した手順に従うことで、よりスケーラブルで高性能なサーバーレスアーキテクチャを実現できるでしょう。