Lambda で PHP を実行しようとしたらハマった
Lambda で PHP を実行しようと思い、AWS 公式ブログや複数の記事を見たのですが、現時点では手順通りに動かなかったのでハマりました。
解決策として、2 つの方法を見つけたので紹介します。
結論
- Serverless Framework を使用する
- AWS Serverless Application Model (AWS SAM) を使用する
経緯
Lambda で PHP を実行する方法について検索すると、AWS 公式ブログの内容をもとにした記事がいくつかヒットします。
AWS 公式の内容だから手順通りに実行すればできると思っていたのですが、GitHub の手順通りに実行したところ、デプロイ後に以下のエラーが発生しました。
{
"errorMessage": "RequestId: 0d280a9a-152b-4876-998f-193e24f2d143 Error: Runtime exited with error: exit status 126",
"errorType": "Runtime.ExitError"
}
START RequestId: 0d280a9a-152b-4876-998f-193e24f2d143 Version: $LATEST
/lambda-entrypoint.sh: /var/runtime/bootstrap: /var/lang/bin/php^M: bad interpreter: No such file or directory
/lambda-entrypoint.sh: line 14: /var/runtime/bootstrap: Success
END RequestId: 0d280a9a-152b-4876-998f-193e24f2d143
REPORT RequestId: 0d280a9a-152b-4876-998f-193e24f2d143 Duration: 25.73 ms Billed Duration: 26 ms Memory Size: 128 MB Max Memory Used: 3 MB
RequestId: 0d280a9a-152b-4876-998f-193e24f2d143 Error: Runtime exited with error: exit status 126
Runtime.ExitError
上記のエラーの解決策が分からなかったので、AWS 公式ブログや GitHub の手順では実行がうまくいきませんでした。
参考になった記事
以下の 2 つの記事が参考になりました。
Serverless Framework を使用する方法と、SAM を使用する方法に分かれていたので、それぞれを検証し、自分なりに少し変更してみました。
1. Serverless Framework を使用する方法
こちらの方法では以下のツールを使用します。
・AWS CLI
・npm
・Serverless framework
・Composer
・PHP
-
Administrator
ポリシーを付与した IAM ユーザーを作成 -
Serverless framework のインストール
npm install -g serverless
- Serverless framework の認証情報を設定
serverless config credentials --provider aws --key <Access key ID> --secret <Secret access key> --profile php-user
- bref のインストール
composer require bref/bref
- 関数の作成
vendor/bin/bref init
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
[1] Event-driven function
を選択します。
- デプロイ
serverless deploy --aws-profile php-user
デプロイ後、バージニア北部リージョン (us-east-1) に app-dev-hello
という Lambda 関数が作成されます。
Lambda コンソールからテスト実行すると、以下の結果が返ってきます。
"Hello world"
以上が Serverless Framework を使用する方法です。
基本的には参考サイトと同様の手順ですが、profile
は適宜変更してください。
Serverless Framework で気になった点
Serverless Framework では .aws/config
に記載されている認証情報を利用することができないようです。
This is a known issue with Serverless, Serverless only checks ~/.aws/credentials for the profile and not ~/.aws/config.
これはサーバーレスの既知の問題です。サーバーレスは~/.aws/credentialsはプロファイルのみをチェックし、~/.aws/configはチェックしません。
Serverless Framework のフォーラムでも議論されていたようで、一応解決策はあるようですが、正直よくわかりませんでした。
とりあえずデプロイのためだけに IAM ユーザーを作成したくなかったので、この点を SAM で解決しました。
AWS Serverless Application Model (AWS SAM) を使用する方法
こちらの方法では以下のツールを使用します。
・AWS CLI
・Composer
・PHP
・AWS SAM CLI
なお、SAM CLI で使用する profile 情報は、./aws/config
に記載済みの情報を使用するので、新たに IAM ユーザーを作成する必要はありません。
[profile Study]
role_arn = arn:aws:iam::{Account-Id}:role/OrganizationAccountAccessRole
source_profile = default
region = ap-northeast-1
-
S3 バケット作成
デフォルト設定で S3 バケットを作成します。 -
bref のインストール
composer require bref/bref
- 関数の作成
vendor/bin/bref init
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
[1] Event-driven function
を選択します。
- template.yaml を作成
参考サイトの内容を参考に、以下のような template.yaml を作成しました。
AWSTemplateFormatVersion: 2010-09-09
Description: 'test'
Transform: AWS::Serverless-2016-10-31
Resources:
PhpFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: 'PhpFunction'
Description: test
CodeUri: .
Runtime: provided.al2
Handler: index.php
MemorySize: 1024
Timeout: 30
Layers:
- arn:aws:lambda:ap-northeast-1:209497400698:layer:php-81:25
- sam package
S3 バケット名や profile 名は適宜変更してください。
sam package \
--template-file template.yaml \
--output-template-file phpsl-output.yaml \
--s3-bucket my-s3-bucket-name \
--profile Study
- sam deploy
profile 名やリージョンは適宜変更してください。
sam deploy \
--template-file phpsl-output.yaml \
--stack-name phpsl-service \
--capabilities CAPABILITY_IAM \
--profile Study \
--region ap-northeast-1
デプロイ後、東京リージョン (ap-northeast-1) に PhpFunction
という Lambda 関数が作成されます。
Lambda コンソールからテスト実行すると、以下の結果が返ってきます。
"Hello world"
ポイント
template.yaml 内にポイントが 2 つあります。
1. Layer
Layer の部分には、Serverless Framework でデプロイした時に、Lambda コンソールから確認できる Layer の ARN を指定しました。
また、ARN 内のリージョンについても、bref のドキュメントにリージョンごとの ARN が記載されていたので、東京リージョンの ARN を指定しました。
2. Runtime: provided.al2
参考サイト通りだと、Runtime は provided
になりますが、実行すると以下のエラーが発生しました。
PHP Warning: require(/var/task/vendor/autoload.php): Failed to open stream: No such file or directory in /var/runtime/bootstrap on line 25
Serverless Framework でデプロイした Lambda 関数との差分を確認したところ、Serverless Framework でデプロイした Lambda 関数の Runtime は provided.al2
になっていました。
AWS 公式ドキュメントを確認すると、provided.al2
は OS が Amazon Linux 2
になるようです。
provided
では OS が Amazon Linux
なので、ここが原因でエラーが発生していたようです。
Runtime: provided.al2
と指定することで、エラーは解消されました。
IAM ユーザーの新規作成が不要
Serverless Framework を使用する方法で気になる点として記載した、デプロイ用の IAM ユーザーの作成ですが、SAM を使用することで既存の profile が使用することで解決できました。
IAM ユーザーは増えるごとに情報漏洩のリスクや管理の煩雑さが増すので、できるだけ増やしたくないものです。
まとめ
今回は Lambda で PHP を実行する際にハマったので、その解決策として、2 つの方法を紹介しました。
もしかしたら、AWS 公式の手順も Runtime が原因かもしれませんが、どこを変更すればよいのかわからないので、気になる方は試してみてください。
今回の内容が参考になれば幸いです。
Discussion