LoginSignup
0
0

More than 3 years have passed since last update.

AWS LambdaのCustom Runtimeを使い、Node.js v8などEoLとなったランタイムを動かす

Last updated at Posted at 2020-04-05

はじめに

Node.js、バージョンアップの足がかなり早いですよね。
AWS Lambdaにおけるランタイムサポート期間も、これにあわせてハイテンポになっています。

ちゃんとバージョンアップをしろというご意見は重々承知の上ではありますが、
Node.js v8.10でLambda Functionを使い続けざるを得ない場合に、カスタムランタイムを使ってEoLとなったランタイムを動かし延命処置を図ります。

動作確認環境

  • Arch Linux (2020.04.04)
  • Docker 19.03.8-ce
  • aws-cli 1.18.36

カスタムランタイムの使い方

カスタムランタイムの仕様については、公式ドキュメントが詳しいので割愛します。

カスタムランタイムを使用するには、デプロイパッケージあるいはLayerに、node実行ファイルと、ハンドラー関数を起動するためのbootstrap実行ファイルを含める必要があります。
今回は既存のLambda Functionを使用することを想定していますので、関数のデプロイパッケージには手を加えずLambda Layerでランタイムを読み込ませます。

Lambda Layerの作成には、以下のリポジトリを活用させていただきます。
https://github.com/lambci/node-custom-lambda

こちらのリポジトリにはNode v10、v12のファイルが含まれています。(2020/04/04現在)
今回はこのリポジトリをフォークし、v8.10用のファイルを追加することでLayerを作成します。

bootstrapについては、CとJavascriptで書かれたものがそれぞれv12.x/bootstrap.cv12.x/bootstrap.jsにあります。(v10.xも同様)

bootstrap.c(をコンパイルしたbootstrap)がまずAWS Lambdaによって起動され、これがbootstrap.jsスクリプトをカスタムランタイムのNodeで実行します。
bootstrap.jsは、AWS Lambda ランタイムインターフェイスから関数の呼び出しイベントの受け取り、デプロイパッケージのスクリプト実行、実行結果のPOSTを行います。

上記リポジトリのbootstrap.jsはNode v8.10でも問題なく動くので、
必要な変更点はLambda Layerに含めるnode実行ファイルをv8.10のものに変更するだけとなります。

カスタムランタイムの作成

前節で紹介したリポジトリをクローンするところからはじめます。
Dockerが必要となります。

$ git clone https://github.com/lambci/node-custom-lambda.git
$ cd node-custom-lambda

v12.xのディレクトリを元に、v8.10のディレクトリを作成します。

$ cp -r v12.x v8.10
$ cd v8.10

v12.xのLayerファイルを削除しておきます。

$ rm layer.zip

このプロジェクトでは、Docker上でbootstrap.cのビルドとNodeのダウンロードを行います。

config.shを編集し、Nodeのバージョンを指定します。

config.sh
< export NODE_VERSION=12.16.1
---
> export NODE_VERSION=8.10.0

ビルドします。

$ ./build.sh

v8.10/layer.zipファイルが出来上がります。
これを解凍すると以下のようなファイルが入っています。

layer
├── bin
│   └── node
├── bootstrap
└── bootstrap.js

Nodeのバージョンを確認しておきます。

$ ./layer/bin/node -v
v8.10.0

テストが用意されていますので、実行してみます。

$ ./test.sh

以上でカスタムランタイムのLayerが完成しました。

カスタムランタイムのデプロイ

リポジトリにはpublish.shが用意されていますが、このスクリプトは全てのリージョンにデプロイされてしまいます。
今回はap-northeast-1にのみデプロイできればよいので、AWS CLIを使って手動でLayerを作成します。

まず、作成したレイヤーのファイル(layer.zip)を任意のS3にアップロードします。

aws s3api put-object --bucket ${BUCKET_NAME} --key nodejs/8.10.0/layer.zip --body layer.zip --output json

次に、Lambda Layerを作成します。
ここではCloudFormationで作成します。

template.yml
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  S3BucketName:
    Description: A S3 bucket name contains layer.zip
    Type: String

Resources:
  Nodejs8Runtime:
    Type: AWS::Lambda::LayerVersion
    Properties:
      Content:
        S3Bucket: !Ref S3BucketName
        S3Key: nodejs/8.10.0/layer.zip
      Description: Layer for Node.js 8.10.0 Custom Runtime
      LayerName: custom-runtime-nodejs-8

Outputs:
  Nodejs8RuntimeLayerARN:
    Description: A lambda layer ARN of Node.js 8.10.0 Custom Runtime
    Value: !Ref Nodejs8Runtime
    Export:
      Name: !Sub ${AWS::StackName}-runtime-nodejs8

Stackを作成。

aws cloudformation create-stack --stack-name dev-lambdalayers-nodejs \
--template-body file://template.yml \
--parameter ParameterKey=S3BucketName,ParameterValue=${S3_BUCKET_NAME}

Layerができていることを確認します。

$ aws lambda list-layer-versions --layer-name custom-runtime-nodejs-8
{
  "LayerVersions": [
    {
      "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:123456789012:layer:custom-runtime-nodejs-8:1",
      "Version": 1,
      "Description": "Layer for Node.js 8.10.0 Custom Runtime",
      "CreatedDate": "2020-04-04T16:59:31.629+0000"
    }
  ]
}

Lambda Functionの作成とテスト

上記で作成したカスタムランタイムをテストします。

Lambda FunctionはServerless Frameworkを使用して作ることにします。
provider.runtimeprovidedを指定することでカスタムランタイムを使用できます。
Lambda Layerは、先程のCloudformation StackのOutputをインポートしてARNを指定します。

serverless.yml
service: test-lambda-function

provider:
  name: aws
  runtime: provided
  stage: dev
  region: ap-northeast-1

functions:
  hello:
    handler: handler.hello
    layers:
      - 'Fn::ImportValue': dev-lambdalayers-nodejs-runtime-nodejs8

関数のコードはシンプルに、実行しているNode.jsのバージョンを返すだけです。

handler.js
module.exports.hello = async event => {
  return process.version;
};

これを実行して、v8.10.0という文字列が帰ってきたら成功です。

$ sls invoke -f hello
"v8.10.0"

注意点

  • AWS公式のNode.jsランタイムにはaws-sdkが含まれていますが、この方法で作成したカスタムランタイムにはいずれのnpmパッケージも含まれていません。

おわりに

以上でNode v8を使用するLambda Functionの延命措置ができました。
同様の方法で、Node v6、v4も動かすことが可能です。

しっかりバージョンアップしていくのがベストであることは言うまでもありませんが、
node-gypなどネイティブモジュールはバージョンアップで動かなくなることも多々ありますので、とりあえずの措置には使えるかと思います。

また今回使用したコードはすべて以下リポジトリにアップしています。
https://github.com/uhey22e/node-custom-lambda

0
0
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
0
0