🐕‍🦺

[AWS]Lambdaでシェルスクリプトを定期実行する環境を作成

に公開

背景

EC2上でcronにより定期実行しているシェルスクリプトを、コスト削減の観点からAWS Lambdaへ移行を検討する

方針

  • 定期実行はEventBridgeをトリガーとしてLambda
  • Lambdaカスタムランタイムを使用
  • OSはAmazonLinux2023を使用

ファイル群

  • bootstrap
  • シェルスクリプト
  • Dockerfile

これらのファイルを用意する

bootstrap

bootstrapはAWS公式チュートリアルのものを使用

bootstrap
#!/bin/sh

set -euo pipefail

# Initialization - load function handler
source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh"

# Processing
while true
do
  HEADERS="$(mktemp)"
  # Get an event. The HTTP request will block until one is received
  EVENT_DATA=$(curl -sS -LD "$HEADERS" "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")

  # Extract request ID by scraping response headers received above
  REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)

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

  # Send the response
  curl "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response"  -d "$RESPONSE"
done

シェルスクリプト

実行するシェルスクリプトはAWS公式チュートリアルのものを使用
適宜シェルスクリプトは環境に合わせ修正してください。

function.sh
function handler () {
  EVENT_DATA=$1
  echo "$EVENT_DATA" 1>&2;
  RESPONSE="Echoing request: '$EVENT_DATA'"

  echo $RESPONSE
}

Dockerfile

シェルスクリプトが最低限動くコンテナを用意

Dockerfile
FROM public.ecr.aws/lambda/provided:al2023

COPY bootstrap ${LAMBDA_RUNTIME_DIR}
COPY function.sh ${LAMBDA_TASK_ROOT}

RUN chmod +x ${LAMBDA_RUNTIME_DIR}/bootstrap \
&& chmod +x ${LAMBDA_TASK_ROOT}/*.sh

CMD [ "function.handler" ]

AWS構築

前提としてAWS CLIが叩けること
コマンド内の[AccountID]は適宜修正

LambdaデプロイのためECRを準備する

$ aws ecr create-repository --repository-name demo --encryption-configuration encryptionType=AES256 --image-scanning-configuration scanOnPush=false 

Dockerクライアントの認証

$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [AccountID].dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded

イメージ作成

$ docker buildx build --platform linux/amd64 --provenance=false  -t demo .

イメージにタグ付け

$ docker tag demo:latest [AccountID].dkr.ecr.ap-northeast-1.amazonaws.com/demo:latest

イメージをECRにプッシュ

$ docker push [AccountID].dkr.ecr.ap-northeast-1.amazonaws.com/demo:latest

Lambdaの作成

$ aws lambda create-function --function-name demo --package-type Image --code ImageUri="[AccountID].dkr.ecr.ap-northeast-1.amazonaws.com/demo:latest" --role [RoleARN] --timeout 30 --memory-size 512

コンソールで作る場合はコンテナイメージを選択する

テスト実行することでイベントデータが出力される。

参考

AWSチュートリアルLambda カスタムランタイムの構築
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtimes-walkthrough.html

Discussion