terraformとGitHub ActionsによるAWS Lambda ソースコードの自動デプロイ
はじめに
株式会社 MamaWell でエンジニアのお手伝いをしている、kkb0318 です。
いまのプロジェクトでは以下のような事情もあり、インフラの設定を terraform で IaC 化しています。
- リソースを立ち上げっぱなしにしたくない(作ってすぐ消せるようにしておきたい)
- (今後)ステージング環境も作成したい
terraform は IaC を実現するためのツールであることもふまえ、Lambda のソースコードのデプロイは別で行うこともあるかと思いますが、本プロジェクトでは terraform で一括管理できるようにしています。
本記事では、Lambda のソースコードのデプロイを terraform のみで行う方法について解説します。
フォルダ構成
以下のようなフォルダ構成にしています。
.
├── .github/ # GitHub Actions
├── api/ # バックエンド
├── infra/ # インフラ(terraform)
└── ui/ # フロントエンド
まだ立ち上げ時期ということもあり、とりあえずフロント・バック・インフラ全て1つのリポジトリで管理するようにしています。
このあとでてくる GitHub Actions や terraform ファイルの設定で、各フォルダを参照しています。
Lambda の構築
ソースコードを含めたデプロイ設定
はじめに、terraform のarchive providerの機能を使って zip ファイルを作成します。
variable "lambda_func1" {
default = "func1"
}
data "archive_file" "func1" {
type = "zip"
output_path = "../api/${var.lambda_func1}/src.zip"
source_dir = "../api/${var.lambda_func1}"
excludes = ["../api/${var.lambda_func1}/tests"]
}
今回は、フォルダ構成に記載したとおり、tf ファイルを infra フォルダ直下に入れているため、Lambda のソースコードが保存されている api フォルダまでのパスを指定しています。
source_dir
にソースコードが含まれているディレクトリのパスを指定しています。
また、ディレクトリテストコードは不要なので excludes
オプションで除外しています。
S3 への zip ファイル保存
次に、作成した zip ファイルを S3 に保存するよう設定します。
resource "aws_s3_object" "func1" {
bucket = aws_s3_bucket.api.id
key = "${var.lambda_func1}.zip"
source = data.archive_file.func1.output_path
}
resource "aws_lambda_function" "func1" {
function_name = var.lambda_func1
handler = "src.app.lambda_handler"
source_code_hash = base64sha256(data.archive_file.func1.output_path)
runtime = "python3.9"
s3_bucket = aws_s3_bucket.api.id
s3_key = aws_s3_object.func1.key
}
Lambda 関数が使用するソースコードを設定します。
先ほど設定した S3 の情報をs3_bucket
s3_key
に設定することで、S3 に保存した zip ファイルを Lambda で使用することができます。
base64sha256
により zip ファイルのハッシュを計算することで差分を発生させています。
これを設定することで、terraform がソースコードの変更を検知し Lambda 関数を最新のコードでデプロイしてくれるようになります。
その他:権限・ログ設定
cloudwatch の設定です。この設定がなくてもログ出力はされますが、terraform 管理下にして構築/削除できるようにしたかったため設定しています。
resource "aws_cloudwatch_log_group" "func1" {
name = "/aws/lambda/${var.lambda_func1}"
retention_in_days = 3
}
権限の設定については、API Gateway-Lambda 連携を想定した記述になっています。
resource "aws_lambda_permission" "func1" {
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.func1.function_name
principal = "apigateway.amazonaws.com"
source_arn = "${aws_apigatewayv2_api.main.execution_arn}/*/*"
}
API Gateway は HTTP API を使用していますので、source_arn
がaws_apigatewayv2_api
になっています。
HTTP API については以下の記事で解説しています。
GitHub Actions による Lambda の自動デプロイ
GitHub Actions により、main ブランチへのマージをトリガーにインフラが更新されるようにしています。
on:
push:
branches:
- main
jobs:
deploy-infra:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configre aws credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-1
- name: Setup Terraform
uses: hashicorp/setup-terraform@v2
with:
terraform_version: 1.3.6
- run: terraform init
working-directory: ./infra/
- run: terraform plan
working-directory: ./infra/
- run: terraform apply -auto-approve
working-directory: ./infra/
この設定では、terraform, aws cli の設定をした後、./infra フォルダを working directory として terraform apply
を実行しています。
これにより、main ブランチへマージするだけで、インフラおよび Lambda のソースコードをアップデートできるようになります。
さいごに
Lambda のソースコードだけ別でデプロイするような運用にしてしまうと、そもそもソースコードの反映が面倒ですし、ソースコードの反映を忘れて動作検証してしまうといったミスも発生する可能性があります。
本記事のような設定を行っておくことにより、Lambda ソースコードやインフラ設定の変更が自動的に反映されるようになるため、ソースコードの修正だけに注力することができるようになります。
加えて、 Lambda のテストができる環境を用意しておくことで、開発体験が良く効率的に開発ができるようになるため、ぜひ試してみてください。
Lambda のテストの話については以下に記載しています。
エンジニア募集
株式会社 MamaWell ではエンジニアを募集しています。
勤務形態はリモートで、働く曜日や日時は自由です。副業・アルバイトも募集中です。
モダンな開発に興味がある方、新規プロダクト立ち上げに興味のある方はぜひ、以下までご連絡ください!
Discussion