トレタ開発者ブログ

飲食店向け予約/顧客台帳サービス「トレタ」、超直前予約アプリ「トレタnow」を開発・提供するスタートアップ企業です。

lambrollでシンプルなLambdaデプロイの仕組みを作った話

トレタ Advent Calendar 2020 5日目の記事です。


はじめに

はじめまして。2020年4月からSREチームにJOINしたbutadoraと申します。

入社日から即フルリモートでなれない部分もありましたが、気づけばもう年末であっという間の1年だったなと感じるこの頃です。

さて、今回はAPI Gateway+LambdaでREST APIを構築するにあたり、 lambrollというデプロイツールを利用したデプロイフローを採用したため、紹介させていただきます。

lambrollとは

lambrollはfujiwaraさんによって作成されたLambdaのデプロイツールです。

github.com

一方lambrollはLambdaリソースに特化しており、 1コマンドでコードのアップロード準備〜デプロイをやってくれます。 大まかなデプロイの流れは以下のとおりです。

  1. デプロイ対象ディレクトリのzipアーカイブ
  2. zipファイルのアップロード(to S3)
  3. Lambda functionの(作成&)更新
  4. currentタグの(作成&)エイリアス更新

lambroll開発の経緯やクイックスタートはfujiwaraさんのブログにまとまっているためそちらをご参照ください。

sfujiwara.hatenablog.com

ディレクトリ構成

最終的な構成としては以下のようになりました。

.
├── bin/  # go biuldのバイナリデータ出力先ディレクトリ
├── .gitignore
├── .lambdaignore  # lambdaアーカイブ時に除外するディレクトリ
├── function.production.json  # production環境のLambda(lambroll)設定ファイル
├── function.staging.json  # staging環境のLambda(lambroll)設定ファイル
├── go.mod  # goプログラムの依存モジュール管理ファイル
├── go.sum  # goプログラムの依存モジュールのチェックサム管理ファイル
└── main.go  # goプログラム本体のファイル
  • 今回はgoで書かれているため、ビルド後のファイル置き場(空ディレクトリ)を用意
  • function.jsonはfunction.環境名.jsonそれぞれに書き分けて--functionオプションで切り替え

CI/CD

デプロイフローを実現するために追加した設定を書いていきます。

必要な権限(IAM Policy)

lambrollはAWS Lambda APIを利用している。 lambroll deployを実行するためには以下のようなIAM Policyが必要となります。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:PassRole"
            ],
            "Resource": "arn:aws:iam::123456789012:role/lambda-role"
        },
        {
            "Effect": "Allow",
            "Action": [
                "lambda:CreateAlias",
                "lambda:CreateFunction",
                "lambda:GetFunction",
                "lambda:GetFunctionConfiguration",
                "lambda:ListTags",
                "lambda:UpdateAlias",
                "lambda:UpdateFunctionCode",
                "lambda:UpdateFunctionConfiguration"
            ],
            "Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:*"
        }
    ]
}
  • IAMのResourceはLambdaFunctionに割り当てるIAM Role

.circleci/confg.yml

今回はCircleCIで実現しました。configの一部を抜粋して紹介します。

version: 2.1
orbs:
  lambroll: fujiwara/lambroll@0.0.7

executors:
  golang:
    docker:
      - image: cimg/go:1.14
        auth:
          username: $DOCKERHUB_USER
          password: $DOCKERHUB_PASSWORD

commands:
  function_build:
    parameters:
      function_dir:
        type: string
    steps:
      - run:
          name: create persistent dir
          command: mkdir -p /tmp/lambroll-api/<<parameters.function_dir>>/bin
      - run:
          name: go build
          command: "GOOS=linux GOARCH=amd64 go build -ldflags='-s -w' -o /tmp/lambroll-api/<<parameters.function_dir>>/bin/main ./main.go"
          working_directory: "functions/<<parameters.function_dir>>"

  lambroll_init:
    steps:
      - lambroll/install:
          version: v0.9.1

jobs:
  build:
    executor: golang
    steps:
      - checkout
      - function_build:
          function_dir: hoge-function
      - function_build:
          function_dir: fuga-function
      - persist_to_workspace:
          root: /tmp/lambroll-api
          paths:
            - hoge-function/bin/*
            - fuga-function/bin/*

  lambroll_deploy:
    executor: golang
    steps:
      - checkout
      - attach_workspace:
          at: functions/
      - lambroll_init
      - run:
          command: lambroll deploy --src="./bin" --function="function.$ENV.json"
          working_directory: "functions/hoge-function"
      - run:
          command: lambroll deploy --src="./bin" --function="function.$ENV.json"
          working_directory: "functions/fuga-function"

# workflowsは省略
  • lambrollはgithubのreleaseから取ってくるだけですぐ利用できるが、Orbが用意されているためそちらを利用してインストール
    • 今回はbuildに使っているcimg/goをそのまま利用しているが、他のコンビニエンスイメージでもインストールできるはず
  • 環境変数はCircleCIのcontextsから呼び出すようにしている。定義している環境変数は以下。
    • ENV: 環境名
    • AWS_ACCESS_KEY_ID: lambrollデプロイ用ユーザのAWSアクセスキー
    • AWS_SECRET_ACCESS_KEY: lambrollデプロイ用ユーザのAWSシークレットアクセスキー
    • AWS_REGION: Lambdaをデプロイするリージョン

前日譚

トレタでは基本的にAWSリソースの管理にはTerraformを採用しています。 しかしながら、Lambdaに関してはzipアーカイブの用意などの事前作業が別途必要など、Terraformだけでデプロイを完結させることは難しいです。

そこで、真っ先に浮かんだのはServerless Frameworkでしたが、 Lambdaとその他リソースではデプロイフローが異なるのではないかという考えから、 シンプルにLambdaリソースだけを管理して、その他リソースはTerraformに任せる構成を模索しました。

その結果、lambrollが候補に上がり、lambrollの思想がマッチしていることやメンテナンスが継続されていることからPoCも兼ねて採用しました。

最後に

今回はサーバレスAPIの新規構築にlambrollを利用しましたが、 既存のLambda関数をlambroll管理下に置くことも容易にできるため、Serverless Frameworkからの置き換えも検討していきたいと考えています。

先日発表されたLambdaのcontainer imageにも即日対応されていたため、近々試して見ようと思います。

エンジニア募集中

トレタに興味を持っていただけましたら、是非一度お話しましょう!

https://corp.toreta.in/recruit/midcareer/

© Toreta, Inc.

Powered by Hatena Blog