はじめに
オンプレで動いているBashのスクリプトをlambdaで動かしたいなと思い、
AWSのチュートリアルを実践プラスアルファで、nkfコマンド使えるようにする。
参考にしたチュートリアル
チュートリアル – カスタムランタイムの公開 - AWS Lambda
$ tree
.
├── bootstrap
├── function.sh
└── response.txt
こんな感じで始めていきます。
ロールの作成
やること
- Rolesのページを開く。
- ロールの作成
- 信頼されたエンティティ - Lambda
- アクセス許可 - AWSLambdaBasicExecutionRole
- ロール名 -
lambda-role
チュートリアルでは、これをさっくり作ってくれとなっていますが、せっかくなのでawscliで作ってみます。
AWSCLIでの手順
変数の定義
$ ROLE_NAME=lambda-role
$ echo $ROLE_NAME
lambda-role
信頼ポリシーの作成
$ cat << EOF > policy
> {
> "Version": "2012-10-17",
> "Statement": [
> {
> "Effect": "Allow",
> "Principal": {
> "Service": "lambda.amazonaws.com"
> },
> "Action": "sts:AssumeRole"
> }
> ]
> }
> EOF
確認。
失敗していたらparse error
と出る
$ cat policy | jq
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Role作成
$ aws iam create-role --role-name ${ROLE_NAME} --assume-role-policy-document file://policy
結果確認
$ aws iam list-roles --query "Roles[?RoleName == '${ROLE_NAME}']"
{
"Role": {
"Path": "/",
"RoleName": "lambda-role",
"RoleId": "AAAAAAAAAAAAAAAAAAAAAA",
"Arn": "arn:aws:iam:: 123456789012:role/lambda-role",
"CreateDate": "2019-12-01-01",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
}
}
管理ポリシーAWSLambdaBasicExecutionRole
をアタッチする
$ aws iam attach-role-policy --role-name ${ROLE_NAME} --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
結果確認
$ aws iam list-attached-role-policies --role-name lambda-role
{
"AttachedPolicies": [
{
"PolicyName": "AWSLambdaBasicExecutionRole",
"PolicyArn": "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
]
}
bootstarpを作成する
カスタムランタイムの場合、bootstrap
というファイルが、一番はじめに呼び出される。
#!/bin/sh -xv
set -euo pipefail
# ここだけ、チュートリアルから編集。tmpフォルダ内にawscliを配置するためHOMEを設定
export HOME="/tmp"
# ハンドラ関数の読み込み
source $LAMBDA_TASK_ROOT/"$(echo $_HANDLER | cut -d. -f1).sh"
while true
do
HEADERS="$(mktemp)"
# イベントの取得
EVENT_DATA=$(curl -sS -LD "$HEADERS" -X GET "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/next")
REQUEST_ID=$(grep -Fi Lambda-Runtime-Aws-Request-Id "$HEADERS" | tr -d '[:space:]' | cut -d: -f2)
# ハンドラ関数の実行
RESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")
# 結果を返却
curl -X POST "http://${AWS_LAMBDA_RUNTIME_API}/2018-06-01/runtime/invocation/$REQUEST_ID/response" -d "$RESPONSE"
done
function.sh
bootstrapを起点として、実際に呼び出される関数です。
bootstrapのRESPONSE=$($(echo "$_HANDLER" | cut -d. -f2) "$EVENT_DATA")
ところから呼び出されます。
function handler () {
EVENT_DATA=$1
echo "$EVENT_DATA" 1>&2;
RESPONSE=$(nkf --help)
echo $RESPONSE
}
アップロード
# Lambdaレイヤーに、bootstrapを含めてzip化
$ zip runtime.zip bootstrap
$ aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
# Lambda作成
$ zip function_only.zip function.sh
$ aws lambda create-function --function-name bash-runtime --zip-file fileb://function-only.zip --handler function.handler --runtime provided --role arn:aws:iam::123456789012:role/lambda-role --layers arn:aws:lambda:ap-northeast-1:123456789012:layer:bash-runtime:1
怒られます
これをアプロードし、Lambda上のテストで実行すると怒られます。
+++ nkf --help
/var/task/function.sh: line 5: nkf: command not found
++ RESPONSE=
+ RESPONSE=
というわけで、nkfコマンドをインストールして、一緒にアップロードします
Lambdaの中身はAmazon Linuxとのことなので、LinuxOSから、yum install。
最初はAL2でやろうと思ったのですが、nkfのリポジトリが無さそうだったので、とりあえずcentOSにしました(やることに対してイメージが大きい気がするけど。。)
FROM centos:7
WORKDIR /usr/local/src/
# yum-config-manager のインストール
RUN yum -y install yum-utils
# yum repository の追加
RUN yum -y update
RUN yum -y install epel-release
RUN yum -y install http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
RUN yum -y install http://dev.mysql.com/get/mysql57-community-release-el7-9.noarch.rpm
# NKF インストール
RUN yum -y install nkf
version: '3'
services:
lambda-with-c-compiler:
build: .
volumes:
- ./lib:/var/tmp
command: bash -c "cp /usr/bin/nkf /var/tmp/"
やっていることは、./lib
フォルダとマウントした/var/tmp
に、yum installしたnkfをコピーしているだけです。
$ docker-compose build
$ docker-compose up -d
$ ls -l ./lib/
-rwxr-xr-x 1 nakajimaatsushi staff 273248 Dec 24 01:37 nkf
また、Lambdaレイヤーとしてアップロードしたものは、/opt
の下に配置されるそうなので、
そこにPATH通すように、bootstrapを変更します。
export PATH="$HOME/.local/bin:/opt/lib:$PATH"
そこからアップし直すと、使えました。
# Lambdaレイヤーに、bootstrapとlibを含めてzip化
$ zip runtime.zip bootstrap lib/*
$ aws lambda publish-layer-version --layer-name bash-runtime --zip-file fileb://runtime.zip
# Lambda-Layerを更新
$ aws lambda update-function-configuration --function-name bash-runtime --layers arn:aws:lambda:ap-northeast-1:123456789012:layer:bash-runtime:2
# Lambdaコード更新(libだけ追加なら正直やらなくていいはず)
$ zip function_only.zip function.sh
$ aws lambda update-function-code --function-name bash-runtime --zip-file fileb://function-only.zip
正直使い所はなさそう
参考にしたもの
チュートリアル – カスタムランタイムの公開 - AWS Lambda
カスタム AWS Lambda ランタイム - AWS Lambda
AWS CLI Command Reference — AWS CLI 1.16.309 Command Reference