こうこく
作 ▸

AWS Lambda Layerのデプロイ (アップロード→関数への適用) をスクリプト化する

たくさんのLambda関数とそれら全部で共通利用するLayerを同時に開発してて、手動でアップロード→ちまちま設定するのが面倒くさくなって考えました。

ここではNode.jsで作りましたが、アップロードもLayerの設定もAWS-CLIでやってるので、何でスクリプト化しても同じだと思います。

Windows 10AWS-CLI 1.16.81Node.js 8.10.0
もくじ

前提

  • AWS-CLIがインストールされてて、aws コマンドにパスが通ってること前提です。
  • あらかじめ aws configure コマンド等でPCにAWSの認証情報が設定してあり、レスポンスはjsonで受け取れるものとします。
  • アップロード対象のLayerのソースコードはあらかじめzip圧縮しておき、コマンドライン引数でスクリプトにzipファイルパスを渡すものとします。(実際に私がやった時はスクリプト内でzipにしましたが、長くなるので省きました。)

やりかた

Layerのアップロードは、AWS-CLIの lambda publish-layer-version コマンドで行います。

関数にLayerを設定するのは、AWS-CLIの lambda update-function-configuration コマンドで行います。

update-function-configuration コマンドで関数にLayerを設定するには、バージョン番号を含むLayer ARNが必要です。これは、publish-layer-version のレスポンスに含まれている LayerVersionArn から取得できます。

publish-layer-versionのレスポンスサンプル
{
  "LayerVersionArn": "arn:aws:lambda:ap-northeast-1:999999999999:layer:myLayer1:1",
  "Description": "",
  "CreatedDate": "2019-07-12T02:23:55.363+0000",
  "LayerArn": "arn:aws:lambda:ap-northeast-1:999999999999:layer:myLayer1",
  "Content": {
    "CodeSize": 258,
    "CodeSha256": "YyoE1c1/OsdvvEW6wRWXv3e/H6gPgTgwdnX42qWAunY=",
    "Location": "https://awslambda-ap-ne-1-layers.s3.ap-northeast-1.amazonaws.com/snapshots/999999999999/myLayer1-d405cb93-7bbf-4370-b980-0dff58d3aacf?versionId=QufXWRK.8lOaLcqIRTKsFIjQSv6EOJzQ&X-Amz-Security-Token=AgoJb3JpZ2luX2VjEFkaDmFwLW5vcnRoZWFzdC0xIkgwRgIhAIXSrYMF%2BABSucT5cwrm0ZxjfJsibSmzFq3QSlutk%2Fb5AiEAgx4LXGUyVFWRX%2BsLY3LtEovFuRcyvxL51hnhBTLHtg8q7QMIsv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FARAAGgw5MTk5ODA5MjUxMzkiDEhhK2xuKbXHmdt6MSrBA0QFzvP7YDNurejWiAX4XmZdZVSeNEzdXZL%2FTo%2FVIL%2F%2FpmbzmVuNKcLtCWT7nRG9t%2BpIOtt1h2u69ejnhIZnoYPhBPlYinJ5dURw7htKl32Sb6wSm2re%2B65nVz%2BxyB8ggv6g%2FnuFVxtgWtdFeCHlwk4Lu1ioHNxXrUbqM5lT6goadI8lbPZmj6gOOl%2FBjJBcccX4XfnNOAu02N9%2FobAGi8qV4nDK%2BupOxmZtyIk7%2F2cCobR0e3ijT7oz6jOFkusPL121HcOyzYg13SrCuMU5x4RZfyKLN4y48SBgm5xDbE2JJwhJGABfVlsc9RhAL3kNbYct%2Fiq1i1kKqTviZ30NyaOnN9pKbsJhacd%2BZgTlKfa8%2F%2FkyNN0WAi%2FYPKtQv2ARQBikhXUhztetUM9qozOtj7NbjEJ7fKoitSJWedw7eS%2Bk5bE31pg5wNH85WYBr7p8rpkCY0ufNClsGc1pmDpC3qDmOldXvnQgbV05jgoQqqbMiLJQGR%2B1fychaFCs1A9ZBu4iAEkayHrDl7IkR8EFoQYt9y88uNYTq6KKBEHNUvICDprBIAyrTvxTYe8UVWtCd0D1y%2FJZd5CwepyMSfN6Jxy%2BMJW9n%2BkFOrMBLHum3dsnRzKxbZ%2BTZxfUm6hlRZ2QsZ8tUJ0njz7LRzSuGCA%2B02Qtu%2FRgaXyJLId5Ylq2ghBEUiUcHhA8SVS7O3dwaT2b%2BYSsSqrduzMLhs3mhDREvCDVT0NXShknfRO6ptfpxKEhniaF3NP5BeiKf9xj%2FC9qGkC4YpiyzH0RcxIhc68THZUMuOHYBoXYoxIZwRsjVkAjBJNZgPNx%2FucSnp%2BcCFsL220l%2FThDPNspjkydXHA%3D&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20190712T022353Z&X-Amz-SignedHeaders=host&X-Amz-Expires=599&X-Amz-Credential=ASIA5MMZC4DJZL5D6CW5%2F20190712%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Signature=c936a2c65cc5a35f4575de47ba675815861f0ece547315b9638de462681bfbc8"
  },
  "Version": 1,
  "CompatibleRuntimes": [
    "nodejs8.10",
    "nodejs10.x"
  ]
}

注意点ですが、update-function-configuration コマンドでLayerを設定するときは、設定したい全てのLayerをオプション --layers で指定する必要があるようです。既存のレイヤーに追加する、みたいなのはできません。

なので以下に紹介しているスクリプトを実行すると、スクリプト内でアップロードしたLayer以外は対象の関数から剥がれてしまいます。複数のLayerを使う場合は工夫が必要だと思います。

スクリプト

ここではNode.jsで実装したので、コマンド実行は execSync で行いました。

publish-layer.js
'use strict';

const fs = require('fs');
const path = require('path');
const execSync = require('child_process').execSync;

// Layer名
const layerName = 'myLayer1';

// Layerの互換性のあるランタイム
const compatibleRuntimes = ['nodejs8.10', 'nodejs10.x'];

// Layer適用対象の関数たち
const functions = ['myFunction1', 'myFunction2', 'myFunction3'];


// コマンドライン引数でLayerのzipファイルパスを受け取る (相対パス可)
if (process.argv.length < 3) {
	console.log('zipファイルのパスが指定されていません。');
	process.exit(1);
}
const zipPath = path.resolve(__dirname, process.argv[2]);  // ※process.argv[0]はnodeのパス, [1]はスクリプトのパス, [2]から引数
if (!fs.existsSync(zipPath)) {
	console.log('zipファイルが見つかりませんでした。');
	process.exit(1);
}

// Layerをアップロード
let latestVersionArn;
try {
	const res = execSync(`aws lambda publish-layer-version --layer-name ${layerName} --zip-file fileb://${zipPath} --compatible-runtimes `+ compatibleRuntimes.join(' '));
	
	// レスポンスからバージョンつきLayer ARNを取得
	latestVersionArn = JSON.parse(res.toString('utf8')).LayerVersionArn;
	console.log('Layerアップロード完了 ->', latestVersionArn);
} catch (e) {
	console.log('Layerアップロード中にエラー', e);
	process.exit(1);
}

// 関数にレイヤーを設定
for (let funcName of functions) {
	try {
		execSync(`aws lambda update-function-configuration --function-name ${funcName} --layers ${latestVersionArn}`);
		console.log(`関数 ${funcName} にLayer設定完了`);
	} catch (e) {
		console.log(`関数 ${funcName} にLayer設定中にエラー`, e);
	}
}

上記スクリプト publish-layer.js は、以下のように node コマンドで実行します。引数としてzipファイルパスを指定します。

node publish-layer.js .\path\to\layer.zip

うまくいった場合、コンソールに以下のように表示されます。

実行結果
Layerアップロード完了 -> arn:aws:lambda:ap-northeast-1:999999999999:layer:myLayer1:1
関数 myFunction1 にLayer設定完了
関数 myFunction2 にLayer設定完了
関数 myFunction3 にLayer設定完了
この記事に何かあればこちらまで (非公開)