🍎

terraformとGitHub ActionsによるAWS Lambda ソースコードの自動デプロイ

2023/02/15に公開

はじめに

株式会社 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 管理下にして構築/削除できるようにしたかったため設定しています。

lambda_func1.tf

resource "aws_cloudwatch_log_group" "func1" {
  name              = "/aws/lambda/${var.lambda_func1}"
  retention_in_days = 3
}

権限の設定については、API Gateway-Lambda 連携を想定した記述になっています。

lambda_func1.tf
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_arnaws_apigatewayv2_apiになっています。
HTTP API については以下の記事で解説しています。

https://zenn.dev/kkb0318/articles/article3-infra-apigwv2

GitHub Actions による Lambda の自動デプロイ

GitHub Actions により、main ブランチへのマージをトリガーにインフラが更新されるようにしています。

deploy.yml
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 のテストの話については以下に記載しています。

https://zenn.dev/kkb0318/articles/article2-api-env

エンジニア募集

株式会社 MamaWell ではエンジニアを募集しています。

勤務形態はリモートで、働く曜日や日時は自由です。副業・アルバイトも募集中です。

モダンな開発に興味がある方、新規プロダクト立ち上げに興味のある方はぜひ、以下までご連絡ください!

https://mamawell.jp/engineer_recruit/

Discussion