【AWS】Lambdaがコンテナイメージに対応!お手軽にAWS CLIなどの実行スケジュールも組める!

先日のアップデート情報のひとつにLambdaがコンテナイメージからの関数実行に対応した話がありましたね!

コンテナイメージに対応することでLambda関数の作成や管理が容易になります!

何より「Zipで固めてアップロード」という古典的な方法から脱却できるのが良いですね。

今回は実際にカスタムランタイムイメージから簡単なシェルスクリプトを実行するところまでやってみました。

Lambdaのベースイメージ


Lambda実行のためのベースとなるコンテナイメージは下記のURLから参照することができます。
https://gallery.ecr.aws/?searchTerm=lambda

今回はシェルスクリプトを実行したいのでprovidedを選択しましたが、pythonやnode.jsなど利用用途がはっきりしている場合にはそれぞれに用意されているイメージを選択すると良いでしょう。

Dockerfileの作成

FROM public.ecr.aws/lambda/provided:latest
RUN yum install -y awscli
COPY bootstrap /var/runtime/bootstrap
COPY hello.sh /var/runtime/hello.sh
RUN chmod 755 /var/runtime/bootstrap /var/runtime/hello.sh
CMD ["hello.handler"]

このDockerfileではAWS CLIのインストールと、bootstrapと「Hello form Lambda」を返すだけのhello.shというスクリプトをコピーしています。
CMDで実行指定するものは通常のLambdaと同様にhandler形式で呼び出します。

今回はカスタムランタイムを利用するため、実行するシェルスクリプトと別にbootstrapというものを用意する必要があります。

bootstrapはカスタムランタイムを利用する際に最初に呼び出されるスクリプトで、初期化処理と対象となる関数スクリプトの呼び出しを行います。

これはコンテナイメージに限らず、通常のLambdaでカスタムランタイムを利用する場合にも定義する必要があるものなので、イメージが付き難い人は通常のLambdaで一度作成してみることをお勧めします。

Dockerfileで使用しているスクリプトは次の節に添付します。

実行スクリプト

#!/bin/sh
set -euo pipefail

# Handler format: .
#
# The script file .sh  must be located at the root of your
# function's deployment package, alongside this bootstrap executable.
source $(dirname "$0")/"$(echo $_HANDLER | cut -d. -f1).sh"

while true
do
    # Request the next event from the Lambda runtime
    HEADERS="$(mktemp)"
    EVENT_DATA=$(curl -v -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
    INVOCATION_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)

    # Execute the handler function from the script
    RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")

    # Send the response to Lambda runtime
    curl -v -sS -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$INVOCATION_ID/response" -d "$RESPONSE"
done

bootstrapはデフォルトから変更していません。
こちらは公式チュートリアルのドキュメントにも記載がある他、AWSコンソールから通常のLambdaをカスタムランタイムで作成する際に自動的に生成されるものと同様です。

function handler () {
    EVENT_DATA=$1

    RESPONSE="{\"statusCode\": 200, \"body\": \"Hello from Lambda!\"}"
    echo $RESPONSE
}

こちらが実行するシェルスクリプトです。
hello.shは「Hello form Lambda」を返すだけの簡単なスクリプトになっています。
こちらもAWS公式のサンプルコードをそのまま利用しています。

ビルドとプッシュ


Dockerfile / hello.sh / bootstrapをそれぞれ同一階層のディレクトリに格納しています。
この状態でECRへログインして、docker buildコマンドとdocker pushコマンドを叩きます。

docker build後にはローカル環境で動作確認をしたいところですが、ローカル環境でLambdaイメージを正しく実行するためには専用の環境を作成する必要があります
今回はLambdaのコンテナイメージを利用することの確認のため、ローカルでは動作確認をせずにECRへプッシュしました。

# ECRへログイン
$(aws ecr get-login --no-include-email --region {リージョン} --profile {貴方のアカウント})

# ビルドを実行
docker build . -t {プッシュ先のECRのURI}:latest

# ECRへプッシュ
docker push {プッシュ先のECRのURI}:latest


無事に自分のECRリポジトリへイメージがプッシュできていることを確認してください。

Lambdaの作成とコンテナイメージの指定


Lambda関数を作成する際に「コンテナイメージ」という選択項目が増えているので、こちらを選びます。
利用するコンテナイメージのURIを選択する項目が表示されるため、立ち上げたいイメージを指定してLambda関数の作成を行ってください。


試しにテストを実行したところ、正常に「Hello form Lambda」が表示されていることがわかります。
今回は単純なスクリプトを実行しましたが、DockerfileではAWS CLIをインストールしているため、決まった時間にAWS CLIを実行して特定のコマンドを流すような処理も実行可能ですね。

イメージの更新後はデプロイをしよう


注意点というほどでもないのですが、コンテナイメージに修正を加えてECRへlatestタグをつけてアップロードしたあと、そのままLambda関数を実行したところ古いイメージのまま処理が実行されてしまいました。

Lambdaの仕様上、最後にLambdaを実行してから十分な時間が立っていない場合には、前回の環境が再利用されるのかもしれませんね。
そのため、イメージを修正した後はたとえ同じタグをつけていたとしても「新しいイメージをデプロイ」からきちんと反映をさせる必要があります。

おわりに

実際にコンテナイメージからLambdaを作成して実行してみました。
コンテナイメージから実行できる方がZipファイルをアップロードするよりもスマートな感じがしますね!

AWS CLIをはじめとする必要なソフトウェア各種を事前にイメージに入れ込めるため、カスタムランタイムでの利用が非常に便利になったと思います。
一方で何も考えずに利用するとコンテナイメージのサイズが肥大化してしまい、実行時間に遅れが出てしまうなどの問題も発生しそうです。

いずれにせよ、総合的に見ると今回のアップデートは非常に満足です!
まだまだ出たばかりの新機能なので不明点も多いですが、今後も問題点やメリットなどが見つかれば改めて記事にしていきます。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)