LoginSignup
2
1

More than 1 year has passed since last update.

terraformで構成管理しつつaws lambdaをデプロイする

Last updated at Posted at 2021-10-07

DMMデータインフラ部に所属しているyuuaです
terraformで作成しlambdaをデプロイする際にterraformにlambda関数を含めるとchangeがでたり、扱いづらく
悩むときがあるのでその際の手順的な備忘録です

今回のlambdaはlambda containerではありません

初回の手順

1.terraformで基本的なlambdaの事前の情報を作成する(配置先など)
2.lambda関数をzip化しs3バケットに配置する

継続的なデプロイの手順

基本的にgithub actionsなどのCI/CDを使います

1.github actionsでlambda function / lambda layerをバケットに配置
2.github actionsでupdate functionの実行

下準備

lambdaを配置するようのs3 keyなどをterraformで作成します

s3.tf
// bucket作成
resource "aws_s3_bucket" "lambda_bucket" {
  bucket = "lambda-bucket"
}

// lambda関数配置するようのkeyを作成
resource "aws_s3_bucket_object" "lambda_function" {
  key    = "functions/nodejs/"
  bucket = aws_s3_bucket.lambda_bucket.id
}

// layerを使う場合はlayer用も
resource "aws_s3_bucket_object" "lambda_layer" {
  key    = "layers/nodejs/hoge/"
  bucket = aws_s3_bucket.lambda_bucket.id
}

これで一旦 terraform apply を実施する

lambda functionを配置

default のnode.js lambda

aiu.js
exports.handler = async (event) => {
    // TODO implement
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

上記を zip 化し先ほど作成したs3のkeyに配置します。
配置自体はcliでもconsoleでもciでも配置できれば何でも良いです

lambdaのリソース定義

関数をs3に配置したらterraformでlambda関数を定義します

lambda.tf
data "aws_iam_policy_document" "role" {
  statement {
    actions = ["sts:AssumeRole"]
    effect  = "Allow"
    principals {
      identifiers = ["lambda.amazonaws.com"]
      type        = "Service"
    }
  }
}

resource "aws_iam_role" "role" {
  name               = "${var.function_name}-lambda"
  assume_role_policy = data.aws_iam_policy_document.role.json
}

// logginなど必要であれば、適宜roleにattachなどしてください

// 関数定義
resource "aws_lambda_function" "function" {
  function_name                  = var.function_name
  handler                        = var.handler
  role                           = aws_iam_role.role.arn
  runtime                        = var.runtime
  s3_bucket                      = bucketを指定
  s3_key                         = 配置したkeyを指定
  layers                         = [layerを使うのであれば指定]
}

terraform applyを実施する

上記でlambda関数の作成自体は完了です
publishなどのoptionは適宜

継続的なデプロイをするために

基本的に一度作ったら終わりということはあまりないと思うので継続的なdeployをするために定義を作成します

ここではgithub actionsを定義して、Pull Requestから各branchにPR close/mergeされたタイミングでdeployできるようにします
外部からdeployする際は iam で 必要な権限を付与したuserを作成し、そのユーザのsecretを使います。

ざっと必要になりそうな権限

s3:PutObject
s3:GetObject
s3:DeleteObject
s3:ListBucket
lambda:GetFunction
lambda:UpdateFunctionCode
lambda:UpdateFunctionConfiguration
// layerがいるなら
lambda:GetLayerVersion
lambda:PublishLayerVersion
lambda:ListLayerVersions
lambda:AddLayerVersionPermission

github actions定義

lambda function

下記はセルフホストランナーでの定義ですが通常通りgihtub hosting/セルフホスティングどちらでも問題ないです

function.deploy.yml
name: deploy-function

on:
  pull_request:
    branches:
      - ブランチ名
    types: [closed]

jobs:
  update-functions:
    name: lambda deploy
    runs-on: [self-hosted, linux]
    if: github.event.pull_request.merged == true // mergeされたら処理継続
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: code build
        uses: actions/setup-node@v2
        with:
          node-version: "14"
          cache: "npm"
      - run: npm install // 必要であれば
      - run: npx webpack // buildなどあれば

      // aws credentialを設定
      - name: Configure 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: リージョン

      // zipファイルを作成
      - name: compression
        working-directory: ./dist
        run: zip function.zip main.js

      - name: lambda update function codes
        working-directory: ./dist
        run: |
          aws lambda update-function-code --function-name function名 --zip-file fileb://function.zip
      // 必要であればpublish

コードをzip化し aws cliupdate-function-codeを実行しています
これでPR Close/merge時にdeployが実行されます

lambda layer

layerはnodeの場合 nodejs/node_modules をzip化する必要があります
ここではlambda functionとは別にlayer用のディレクトリを定義しそこにpackage.jsonをおいています

layer.deploy.yml
name: lambda-layer-deploy

on:
  pull_request:
    branches:
      - develop
    types: [closed]
    paths:
      - "layerのpath/**"

jobs:
  update-functions:
    name: lambda layer deploy
    runs-on: [self-hosted, linux]
    if: github.event.pull_request.merged == true
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: code build
        uses: actions/setup-node@v2
        with:
          node-version: "14"
          cache: "npm"

      - name: lambda layer
        working-directory: ./layer
        run: |
          mkdir nodejs
          cp package*.json nodejs/
          npm install --prefix ./nodejs --production
          zip -r package.zip nodejs/node_modules

      - name: Configure 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: リージョン

      - name: lambda layer deploy
        working-directory: ./layer
        run: aws lambda publish-layer-version --layer-name layer名 --zip-file fileb://package.zip --compatible-runtimes nodejs14.x

      // 現在のlatestを取得
      - name: lambda layer latest version
        id: step1
        run: |
          layer=$(aws lambda list-layer-versions --layer-name layer名 --query 'LayerVersions[0].LayerVersionArn')
          echo "::set-output name=layer_ver::$layer"

      - name: lambda update configure
        run: |
          aws lambda update-function-configuration --function-name function名 --layers ${{ steps.step1.outputs.layer_ver }} //複数layerがある場合は ${{ hogehoge }} ${{ foobar }} このような形で続けてかけます 

まとめ

terraformでlambdaのリソースを作成しつつ継続的なdeployはCI/CDで行う環境を備忘録的な形でまとめました。
IaCとlambda関数のcodeが分離され、意識することもすくないのでlambda containerを使わない場合は
今のところ一番使いやすいかなと思っています。

データインフラ部では、AWSでのビッグデータ基盤関連の運用を行っており、
様々リソースを活用したプロダクト開発を行っています。
中途採用などもおこなっておりますので、興味のある方は、一度弊社HPなどから
カジュアル面談など、是非ご応募ください。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1