げっとシステムログ

WEB開発メモ

AWS CloudFormation で Lambda をデプロイする

Slack Bot のイベントハンドラを Lambda で作成したい。

そのために、ローカルでテストしつつ、CloudFormation でデプロイを自動化したい。

CONTENTS
  1. この記事の内容
  2. できあがったもの
  3. aws cloudformation package でパッケージング
  4. aws cloudformation deploy でデプロイ
  5. デプロイスクリプト
  6. まとめ
  7. 参考資料

この記事の内容

ほぼ下記の記事と同じ内容。 これをトレースしてみたもの。

TOP

できあがったもの

以下のテンプレートを aws cloudformation コマンドで処理する。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: STACK_DESCRIPTION
Parameters:
  Role:
    Type: String
    Description: "lambda role arn"
  KMS:
    Type: String
    Description: "KMS key arn"
  SecretRegion:
    Type: String
    Description: "region of secret"
  SecretId:
    Type: String
    Description: "id of secret"
Resources:
  lambdaResource:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: LAMBDA_FUNCTION_NAME
      Runtime: nodejs10.x
      Handler: index.handler
      MemorySize: 128
      Timeout: 3
      CodeUri: ..
      AutoPublishAlias: active
      KmsKeyArn:
        Ref: KMS
      Role:
        Ref: Role
      Environment:
        Variables:
          SECRET_REGION:
            Ref: SecretRegion
          SECRET_ID:
            Ref: SecretId

TOP

aws cloudformation package でパッケージング

以下の記事を参考にテンプレートを作成する。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: STACK_DESCRIPTION
Parameters:
  Role:
    Type: String
    Description: "lambda role arn"
  KMS:
    Type: String
    Description: "KMS key arn"
  SecretRegion:
    Type: String
    Description: "region of secret"
  SecretId:
    Type: String
    Description: "id of secret"
Resources:
  lambdaResource:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: LAMBDA_FUNCTION_NAME
      Runtime: nodejs10.x
      Handler: index.handler
      MemorySize: 128
      Timeout: 3
      CodeUri: ..
      AutoPublishAlias: active
      KmsKeyArn:
        Ref: KMS
      Role:
        Ref: Role
      Environment:
        Variables:
          SECRET_REGION:
            Ref: SecretRegion
          SECRET_ID:
            Ref: SecretId
  • Parameters : コマンドラインから指定するパラメータ。テンプレートからは Ref: KEY で参照
  • AutoPublishAlias : デプロイ時にエイリアスを付け替える

エイリアスについては AWS Lambda で Slack Bot イベントハンドラを作る にまとめた。

STACK_DESCRIPTIONLAMBDA_FUNCTION_NAME は適宜指定する。

ディレクトリ構成は以下のような形にした。

- package.json
- node_modules/
- index.js
- lib/
- config/
  - template.yaml

このテンプレートを aws cloudformation package コマンドで処理するとデプロイ可能な形式に変換できる。

aws cloudformation package \
  --template-file config/template.yaml \
  --output-template-file config/packaged-template.yaml \
  --s3-bucket $S3_BUCKET_NAME

$S3_BUCKET_NAME は適宜指定する。 ここには CodeUri で指定したソースがアップロードされる。

このコマンドを実行するユーザーは $S3_BUCKET_NAME で指定するバケットにアップロードする権限を持っている必要がある。

TOP

aws cloudformation deploy でデプロイ

先に package コマンドで生成した packaged-template.yaml を deploy すると、テンプレートで定義した Lambda がデプロイされる。 --parameter-overridesParameters の内容を指定する。

aws cloudformation deploy \
  --template-file config/packaged-template.yaml \
  --region $STACK_REGION \
  --stack-name $STACK_NAME \
  --parameter-overrides \
    Role=$ROLE_ARN \
    KMS=$KMS_ARN \
    SecretRegion=$SECRET_REGION \
    SecretId=$SECRET_ID

変数はそれぞれ、以下のものを設定する。

deploy する際に必要なポリシーは以下の通り。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "cloudformation",
      "Effect": "Allow",
      "Action": [
        "cloudformation:GetTemplateSummary",
        "cloudformation:DescribeStacks",
        "cloudformation:DescribeChangeSet",
        "cloudformation:CreateChangeSet",
        "cloudformation:ExecuteChangeSet"
      ],
      "Resource": [
        "arn:aws:cloudformation:REGION:ACCOUNT:stack/STACK_NAME/*"
      ]
    },
    {
      "Sid": "transform",
      "Effect": "Allow",
      "Action": "cloudformation:CreateChangeSet",
      "Resource": "arn:aws:cloudformation:REGION:aws:transform/*"
    },
    {
      "Sid": "lambda",
      "Effect": "Allow",
      "Action": [
        "lambda:ListVersionsByFunction",
        "lambda:TagResource",
        "lambda:UntagResource",
        "lambda:ListTags",
        "lambda:GetFunction",
        "lambda:CreateFunction",
        "lambda:DeleteFunction",
        "lambda:UpdateFunctionConfiguration",
        "lambda:UpdateFunctionCode",
        "lambda:PublishVersion",
        "lambda:CreateAlias",
        "lambda:UpdateAlias"
      ],
      "Resource": [
        "arn:aws:lambda:REGION:ACCOUNT:function:FUNCTION_NAME"
      ]
    },
    {
      "Sid": "iam",
      "Effect": "Allow",
      "Action": [
        "iam:PassRole"
      ],
      "Resource": [
        "arn:aws:iam::ACCOUNT:role/ROLE_NAME"
      ]
    }
  ]
}

REGIONACCOUNTSTACK_NAMEFUNCTION_NAMEROLE_NAME は適宜指定する。

複数のユーザーでデプロイするのが面倒だったので、stack, function に関してはデプロイする分だけ複数指定するようにした。

TOP

デプロイスクリプト

パラメータは1度指定すれば良いので、--parameter-overrides はデプロイスクリプトでは指定する必要はない。

aws cloudformation package \
  --template-file config/template.yaml \
  --output-template-file config/packaged-template.yaml \
  --s3-bucket $S3_BUCKET_NAME \
&& \
aws cloudformation deploy \
  --template-file config/packaged-template.yaml \
  --region $STACK_REGION \
  --stack-name $STACK_NAME

TOP

まとめ

CloufFormation で Lambda をデプロイしてみた。 これでデプロイを自動化できるので、ローカルでテストしつつ、マージされたらデプロイというフローで開発できる。

TOP

参考資料

TOP