この記事はBASEアドベントカレンダーの5日目の記事です。 こんにちは!BASEのCRM3チームでバックエンド開発を担当している オリバ(@toshi_oliver)です。2022年11月に入社したので、今回が初のブログとなります。
はじめに
さて、今回はAWSのサーバレスサービスを代表すると言っても過言ではない、AWS Lambda(以下、Lambda)に関する記事を投稿します。
BASEのバックエンドの大部分はPHPで開発されており、システムの一部にLambdaを使用しているのですが、Lambdaのランタイムでサポートされている言語は以下となっております。
- Node.js
- Python
- Ruby
- Java
- Go
- .NET Core
ご覧の通り、PHPはサポートされておりません。 では、PHPの使用は断念しなければならないのかというとそうではなく、カスタムランタイムを使用することでPHPの使用が可能となります。
しかし、公式ドキュメントを見ると、ランタイム用のbootstrapファイルやシェルファイルを用意し、それをzip化しさらにLambdaレイヤー化する必要があります。
Lambdaはプログラム開発に集中するためのサービスであるにも関わらず、PHPを選択することで手間が増えてしまうのは本末転倒であります。
また、公式ブログによりコンテナイメージを使用する手段もありますが、DockerfileとBootstrapファイルの管理が必要となるため、やや手間が増えます。
そこで、本記事ではLambdaにてPHPのカスタムランタイム環境を簡単に構築できる、bref
を紹介します。
前提
- anyenv(1.1.5)
- phpenv(v0.9.0-rc.1)
- PHP(8.1.0)
- AWS CLI(2.9.1)
- SAM CLI(1.65.0)
- bref(v1.7)
環境構築
空のディレクトリ上でComposerを使ってbrefをインストールします。
$ composer require bref/bref
プロジェクトの初期化を行います。
$ vendor/bin/bref init
以下のメッセージが出力されます。brefでは、Webアプリケーション用またはイベントドリブン関数用のLambdaのどちらかを構築するか選択できるので、今回は1
を選択します。
What kind of lambda do you want to create? (you will be able to add more functions later by editing `serverless.yml`) [Web application]: [0] Web application [1] Event-driven function
ディレクトリ配下に以下のファイルが生成されました。
├── sserverless.yml ├── vendor │ └── async-aws │ └── ... ├── composer.json ├── composer.lock └── index.php
デフォルトで
serverless.yml
が生成されます。これはサーバレスのIacツールであるServerless Framework(以下、sls)で必要となるテンプレートファイルです。今回はIacツールにAWS SAM(以下、SAM)を使用するので、serverless.ymlを削除しSAM用のtemplete.yamlを作成しますtemplate.yamlのLayersパラメータに、bref公式ドキュメントに紹介されているLambda Layerの最新ARNを指定します。今回は
arn:aws:lambda:ap-northeast-1:209497400698:layer:php-81:34
を指定します。注意してほしいのが、Webアプリケーション用とイベントドリブン用で対象のARNが異なっており、Webアプリケーション用を選択した場合はphp-81-fpm:34
用のARNを選択する必要がありますRuntimeに
provided.al2
を指定しておりますが、これはAWS が提供するパブリックの ECR に配備されている provided:al2 のイメージをベースイメージとして指定していますtemplate.yaml
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: Sample SAM Template for handson-bref Globals: Function: Timeout: 3 Resources: HelloWorldFunction: Type: AWS::Serverless::Function Properties: FunctionName: hello-world-function CodeUri: . Runtime: provided.al2 Handler: index.php MemorySize: 1024 Timeout: 30 Layers: - arn:aws:lambda:ap-northeast-1:209497400698:layer:php-81:34
- index.php
<?php declare(strict_types=1); require __DIR__ . '/vendor/autoload.php'; return function ($event) { return 'Hello ' . ($event['name'] ?? 'world'); };
デプロイ
BASEではサーバレスのIac管理をSAMで行うことが多いので、SAMを使用したデプロイを実施します。
- 本来なら
sam build
を使用してビルドを行いたいのですが、カスタムランタイムを設定している場合はmakefileを自身で用意する必要があり手間がかかってしまうので、Lambdaパッケージ用のS3バケットを用意します
$ aws s3 mb s3://furukawa-bref-test --profile {任意}
SAM CLIを使用してパッケージングを行います。
$ sam package \ --template-file template.yaml \ --output-template-file bref-output.yaml \ --s3-bucket furukawa-bref-test \ --profile {任意}
SAM CLIを使用してデプロイを行います。
$ sam deploy --template-file bref-output.yaml \ --stack-name furukawa-bref-test --profile {任意} --capabilities CAPABILITY_IAM
デプロイが完了したので、Lambdaコンソール上で試しにテストを行います。
問題なくLambda関数を実行できました。
おわりに
brefを使用することで、DockerfileとBootstrapを使用せずに、LambdaランタイムをPHPに設定することができました。ただし、brefを使用する際に以下の点に注意が必要です。
- brefで用意されているLambda Layerを使用すると、sam buildを使用したデプロイができない
- bref(v1.7)ではarm64に対応していない
- GitHub Issueによると、β版のbref(v2.0)ではarm64に対応するようなので、もうしばらく時間が必要
- Lambda LayerのARNに、${bref:layer.php-81}を指定することでPHP8.1の最新のマイナーバージョンを取得してくれるが、 slsのみの対応
次回は、brefを使用してSlackbotを作ってみたいと思います。
明日は、kondo.hirotakaさん、yusakuさんの記事です。お楽しみに!!