7
9

More than 3 years have passed since last update.

lambda custom runtimeでbash動かす+標準にないnkfコマンドを使えるようにする

Last updated at Posted at 2019-12-26

はじめに

オンプレで動いている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というファイルが、一番はじめに呼び出される。

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.sh
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コマンド自体が見つからないよって言われて、怒られる
+++ 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を変更します。

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

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9