AWS LambdaのデッドレターキューとSNSでリトライ構成を構築する(Serverless Framework準備編)

AWS Lambdaを利用する場合、失敗した場合に大元の関数の引数等を引き継いで何らかのリトライ処理を実行したい場合があると思います。

本記事では、AWS LambdaのデッドレターキューとAWS SNSを利用した関数のリトライ構成について、Serverless Frameworkを使って試してみたいと思います。

なお、AWS Lambdaのデッドレターキューを利用したリトライについては公式のドキュメントに記載があります。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-async.html#dlq



もくじ



開発環境

ローカルの開発マシンはMacで、Dockerを使用します。

  • macOS Catalina
  • docker desktop 2.2.0.5
  • docker-compose 1.25.4



準備

Amazon Linuxが再現されたDockerイメージで開発

AWS Lambdaの関数が実行される環境はAmazon Linuxらしいです。Macのローカルで動いてたのにAWS Lambdaにしたら動かない、というような環境差分を避けるため、下記のAmazon Linuxの環境が再現されたDockerイメージを利用して開発します。

github.com

今回はnode.jsをで試すため、tagがbuild-nodejs12.xのイメージを利用します。



Serverless Frameworkを利用

AWS Lambda用の関数の作成からデプロイまで、オールインワンで簡単にできるServerless Frameworkを利用します。

serverless.com



AWS IAMでデプロイ用のユーザー/ポリシーを作成する

Serverless Framworkを利用してAWSにデプロイする際、デプロイ用のIAMユーザー(アクセスキーIDとシークレットアクセスキー)を作成し、そのIAMユーザーに各種AWSリソースへアクセスできるポリシーをアタッチする必要があります。

これについては、公式のドキュメントに丁寧に書いてあります。

  • ユーザー名:serverless-admin
  • アタッチするAWS管理ポリシー:AdministratorAccess

serverless.com


作成したIAMユーザーのアクセスキーIDとシークレットアクセスキーをホストマシン側に~/.aws/private/credentialsを作成し記載しておきます。 アクセスキーIDとシークレットアクセスキーは漏れたら危険なので取り扱いには注意しましょう。

[default]
aws_secret_access_key = AWS上で表示された値
aws_access_key_id = AWS上で表示された値


また、~/.aws/private/configにリージョン情報等を記載しておきます。

[profile default]
region = ap-northeast-1
output = json

※今回は~/.aws/privateというディレクトリを切っていますが、必須ではありません。筆者の都合でprivateディレクトリにお試し用のIAMユーザーの認証情報ファイルを配置しています。


なお、今回アタッチしたAdministratorAccessポリシーは少し権限が大きく、本来は最小の権限に絞ったポリシーを自作してアタッチする方がセキュリティ的には望ましいです。

これについては公式ドキュメントがあり、以下のgistに記載されているJSONを使用することを推奨しています。

gist.github.com



Dockerfileを用意

以下のようなDockerfileを用意します。Serverless Frameworkをグローバルにインストールしておきます。

FROM lambci/lambda:build-nodejs12.x

# Serverless Framework
RUN npm install -g serverless

WORKDIR /var/task
CMD ["/bin/bash"]


都度docker runを実行してコンテナを起動するのは面倒なので、docker-compose.ymlでコンテナを起動できるようにします。また、ソースコードをホスト側と共有するために、予め./srcディレクトリを作成しておきます。

container_nameimageの名称は任意です。今回はlambda_node12xとします。

version: '3.7'

services:
  lambda_node12x:
    build:
      context: .
    container_name: lambda_node12x
    image: lambda_node12x
    volumes:
      - ./src:/var/task
      - ${HOME}/.aws/private:/root/.aws/
    working_dir: /var/task
    tty: true
    stdin_open: true



AWS credentialsをホストとDockerコンテナで共有する

上記のdocker-compose.ymlvolumes${HOME}/.aws/private:/root/.aws/と書いていますが、これは先ほど作成したAWSの認証情報を記載したcredentialsconfigファイルをDockerコンテナ内でも参照できるようにするためです。

これをしないとAWSにデプロイできません。

なお、この方法とは別に、Serverless Framworkの`config credentialsコマンドでAWSの認証情報を設定することが可能です。

また、今回はprofile名をdefaultのままにしていますが、変更している場合は以下のコマンドで変更する必要があります。

sls deploy --aws-profile hogeProfile


個人的には、コンテナを削除しても設定し直す必要がないため、 profileはdefaultcredentialsをホスト側に用意して共有するのが楽だと思います。


以上で準備は完了です。



関数を作成してデプロイする

Dockerコンテナ上で関数作成

Dockerコンテナにログインし、Serverless Frameworkのコマンドを叩いてテスト用の関数を作成します。

# ログイン
docker exec lambda_node12x bash

# コンテナ内で実行
sls create -t aws-nodejs --path=failFunc

# 以下のように作成される
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/var/task/failFunc"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.67.1
 -------'

Serverless: Successfully generated boilerplate for template: "aws-nodejs"



関数をローカルで試す

下記のコマンドでローカルで関数の実行を試すことができます。まだ何も修正していないのでテンプレートにより作成された関数が実行されます。

sls invoke local -f hello

# 下記の結果が返ってくる
{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Go Serverless v1.0! Your function executed successfully!\",\n  \"input\": \"\"\n}"
}



デプロイする

sls createで作成されたserverless.ymlAWSのリージョン情報を追記します。設定しないとデフォルトのus-east-1にデプロイされます。

provider:
  name: aws
  runtime: nodejs12.x
  region: ap-northeast-1 # これを追記


デプロイはコマンドで一発です。-vをつけているとデプロイの実行過程をみることができます。

sls deploy -v

成功したらAWSのコンソールのAWS Lambdaでデプロイした関数を確認できます。

f:id:urawa72h:20200408224634p:plain



デプロイした関数を削除する

下記のコマンドで削除できます。

sls remove -v


上記以外のコマンドは公式のCLIリファレンスを参照しましょう。

serverless.com



Serverless Framworkは便利

AWS LambdaのデッドレターキューとAWS SNSを利用した関数のリトライ構成について書こうと思っていましたが、Serverless Framworkの紹介だけで長くなってしまったので、今回はここまでとします。

次回の記事で本題について書こうと思います。