背景
- Lambdaはサーバーレス構成に必須なサービス
- LambdaLayerは複数のLambdaで共通するモジュールを使いまわしできるサービス
- LambdaLayer用のzipを作る際には、その作業用のAmazonLinuxのEC2立てたり、Dockerコンテナ作ったりするのが理想
- 公開されているライブラリだけでなく、自身の共通モジュールも含めたりすると構築環境への転送も必要
一言でいうと、使いたいが面倒くさい。
CodeBuildがあるじゃないか
AWS CodeBuild は、CodeCommitやGiuhubなどのソース管理システムからソースをcloneして、各種ビルド処理後に成果物(アーティファクト)をS3にアップロード出来るサービス。
ビルド用のマシンの環境はまっさらな状態(awscliとかの基本的なのは既に入っている)。本ビルド処理前にライブラリのインストール処理とかも可能だったり、独自のAMIを使ったりする事も出来る。
- 他のライブラリなどが入っていない綺麗な環境
- 自分で作ったライブラリなどの参照が可能
- 使った処理時間だけの課金(一日中ビルドとかしてなければ微々たる料金)
という要件に完全マッチしているサービス。
zip作ってみる
準備するもの
LambdaLayerを作ろうとする人は既にあると思います。すいませんがそちらに関しての詳細説明は省かせてもらいます。
また、各種操作で、AWSコンソールをある程度扱った事がある前提の説明になっています。ご了承ください。
CodeCommitやGithubのリポジトリ
実ビルド処理はbuildspec.ymlというファイル(名前変更可能)をリポジトリから読み込むために必要。
今回はGithubで行っています。CodeCommitの場合、後述のCloudFormationのSourceブロックが以下のようになると思います。
CodeCommitの場合の置換
Source:
Location:
!Join
- ''
- - 'https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/'
- !Ref CodeCommitProject
Type: CODECOMMIT
S3バケット
結果ファイルを配置する為に必要
ビルド用のロール
codebuildに適用可能(信頼関係に「codebuild.amazonaws.com」がある)で、S3やcodebuildを実行できるロール。そのArnが必要です。
CodeBuildプロジェクトをCloudFormationで作成
CloudFormationTemplate
Description:
codebuild project by cloudformation.
Parameters:
CodeBuildLambdaLayerProjectName:
Description: Please enter name of the codebuild project for lambda layer.
Type: String
Default: "codebuild-lambdalayer"
GithubProject:
Description: Please enter the github project name.
Type: String
Default: "my-group/lambda-layer"
SourceBranch:
Type: String
Default: "develop"
S3BucketNameForAtrifacts:
Type: String
Default: "my-lambda-layer-artifacts"
ArtifactPath:
Type: String
Default: "lambdalayer-packaging"
ArtifactName:
Type: String
Default: "lambdalayer-thirdparty.zip"
BuildServiceRoleArn:
Type: String
BuildSpecFilePath:
Type: String
Default: "buildspec.yml"
Resources:
LambdaLayerCodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref CodeBuildLambdaLayerProjectName
Description: codebuild project of build zip file for LambdaLayer.
ServiceRole: !Ref BuildServiceRoleArn
Artifacts:
ArtifactIdentifier: LambdaLayerArtifact
Type: S3
Location: !Ref S3BucketNameForAtrifacts
NamespaceType: NONE
Path: !Ref ArtifactPath
Name: !Ref ArtifactName
Packaging: ZIP
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
Image: aws/codebuild/standard:4.0-20.09.14
Source:
Location:
!Join
- ''
- - 'https://github.com/'
- !Ref GithubProject
Type: GITHUB
BuildSpec: !Ref BuildSpecFilePath
SourceVersion: !Ref SourceBranch
TimeoutInMinutes: 10
これをローカルに保存しておく。
AWSコンソールから、CloudFormationへ飛んで、スタックの作成=>新しいリソースを使用(標準)=>テンプレートの準備完了=>テンプレートファイルのアップロード=>ファイルの選択で、以下の内容をコピペして保存したファイルを読込。=>パラメーター入力(
BuildServiceRoleArn、GithubProject、S3BucketNameForAtrifactsあたりは環境に応じて変更してください)=>次へ=>次=>スタックの作成
実処理ファイル(buildspec.yml)を作成
buildspec.ymlの中で色々な処理が出来るのですが、今回はinstallするだけです。
pythonフォルダを作成し、ライブラリのインストール時に -t オプションで、インストール先フォルダを指定しています。
こちらを前述CodeBuildプロジェクトで指定したリポジトリ、ブランチのルートに配置してpushしておきます。
フォルダの位置やファイル名も上記 BuildSpecFilePathパラメーターで指定可能ですが今回はデフォルトのままです。
今回はnumpyライブラリをインストールしています。
buildspec.yml
version: 0.2
phases:
install:
commands:
- mkdir -p workdir/python
- pip3 install -t workdir/python numpy
artifacts:
base-directory: 'workdir'
files:
- '**/*'
CodeBuild実行
AWSコンソールでCodeBuildのページに行き、左ペインで ビルド=>ビルドプロジェクト で出てきた一覧で作成されているCodeBuildプロジェクトを選択=>ビルドを開始=>パラメーター入力(基本CodeBuildプロジェクトでの指定値ですが、ブランチ名など変更可能)=>ビルド開始
S3ファイルのオブジェクトURL確認もしくはダウンロード
AWSコンソール上で、S3を参照すると指定したバケットの指定位置に対象ファイルが出力されています。詳細情報の「オブジェクト URL」を保存しておきます。(もしくは指定していしたS3バケットにファイルが出力されています。AWSコンソールからダウンロードしておきます)
LambdaLayerを作成
AWS Lambda Layersでライブラリを共通化 が解りやすいです。
AWSコンソールから、Lambdaページに行き、左ペインで Additional resource 配下にある 「レイヤー」 => レイヤーの作成
- 名前:mytestlayer など
- Amazon S3 からファイルをアップロードするを選択し、S3のアドレスに前述「オブジェクトURL」を指定(ダウンロードした場合には、ローカルに保存していたファイルをアップロード)
- 互換性のあるランタイムにPython3.8を指定
LambdaLayerを使ったLambda関数を作ってみる
まずは関数雛形作成
AWSコンソールから、Lambdaページに行き、左ペインで関数を選択。関数の作成
- 1から作成
- 名前は適当
- 実行ランタイムにPython3.8を使用
を指定して、関数の作成。
使用するLambdaLayerを追加
デザイナーの画面に移動するので、デザイン画面の「Layers(0)」をクリック。レイヤー設定エリアが表示されるので、レイヤーの追加を選択
- カスタムレイヤーを選択
- 先ほど作成したlayerが出てくるのでそれを選択
- バージョンは1
レイヤーの追加を実行。
※今回カスタムで追加したnumpyは、AWSレイヤーを選択すると、その中に用意されています。
コードの中で使ってみる
以下コードをコードエディタで入力。デプロイボタンを押す
import json
import logging
import numpy as np
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def lambda_handler(event, context):
a = np.arange(15).reshape(3, 5)
logger.debug(a)
# TODO implement
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
テスト
Lambda詳細画面で「テスト」を押す。新しいテストイベントの作成が出てくるので適当な名前を付けて保存。
元の画面に戻って、作成したテストを選んで「テスト」実行。
[DEBUG] 2020-12-03T02:46:46.368Z 2a7c94ee-052c-4f49-bc26-17929de6b66d [[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
import成功していますね。
感想
CodeBuildプロジェクトまでCloudFormation管理する必要はないかもしれませんが、しておくと便利かと思います。
その割にLambda側をCloudFormation管理してませんが、こちらはテスト用なので・・・・
今回はやってませんが、gitリポジトリを参照できるので、独自ソースのLayer化も楽です。
CodeBuild、今回の件や本来のビルド以外にも色々使えそうです。