PHPとAWS Lambdaと私

本記事は、[サムザップ Advent Calendar 2019 #2](https://qiita.com/advent-calendar/2019/sumzap2) の12/14の記事です。

# はじめに
本記事では、AWS LambdaとSAM(Serverless Application Model)の学習と、「Lambdaって、PHP使えないんでしょ！？PHP使えたら、触ってみようかな」っていうPHPer向けに、Lambda怖くないよ！って伝えられればと。

# 主な要素
そもそもLambda(とServerless Application Model)って使い方は良くころがっている気がするのですが、何から始めれば良いか、何を覚えれば良いかみたいなのがまとまったサイトがない気がしますので、まとめたいと思います。
※チュートリアル見れっちゅー話ですが、それもハードルが高い方向けです。

- [ ] **lambdaのレイヤー**
  - 既存のものを利用する場合は不要
  - 今回は、Stackery社が提供しているcustom runtimeのレイヤーを使用
- [ ] **lambda関数**
  - 今回はaws-sam-cliを利用して生成
  - AWSのマネジメントコンソールから手動でポチポチ作成しても良し
- [ ] **APIGateway**
  - 今回はaws-sam-cliを利用して生成
  - AWSのマネジメントコンソールから手動でポチポチ作成しても良し
- [ ] **aws-sam-cli**
  - コードのデプロイ
- [ ] **S3バケット**
  - lambdaで実行するPHPのコードの保存場所
- [ ] **lambdaで実行するPHPのコード**

要素が結構多く見えますが、最低限でいうと、マネジメントコンソールで「APIGateway」と「lambda関数」さえ作ってしまえば、外部からAPIで実行可能です。
またCloudWatchやS3、AWSBatch等と組み合わせて実行することも可能で、多種多様な用途に利用可能です。

今回は、aws-sam-cliを使って簡単にServerless Applicationを構築したかったので、以下3点と、aws-sam-cli(及び各種awsリソース)を利用するため、[EC2(とIAM)](#ec2準備)を利用します。

- [aws-sam-cli](#aws-sam-cliインストール)
- [S3バケット](#s3バケット作成)
- **lambdaで実行するPHPのコード**

# EC2準備
まずはaws-sam-cliを実行するEC2インスタンスを作成しましょう。
最初にEC2に割り当てるIAMを作成します。

### IAMのロール作成
[IAMのロール](https://console.aws.amazon.com/iam/home?#/roles)のページより、「ロールの作成」を押下
<img width="1230" alt="スクリーンショット 2019-12-11 23.29.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209922/e2759fd6-b0c3-a234-49e6-392377cdc474.png">

その後ナビゲーションに沿って、

1. 「このロールを使用するサービスを選択」にて、「EC2」を選択し、「次のステップ」
1. 「Attach アクセス権限ポリシー」にて、以下5つのポリシーを選択し、「次のステップ」
  - AmazonS3FullAccess
  - AWSCloudFormationFullAccess
  - IAMFullAccess
  - AWSLambdaFullAccess
  - AmazonAPIGatewayAdministrator
1. 「タグの追加 (オプション)」は特に何もせずに、「次のステップ」
1. 最後に「ロール名」を適当に決めて、「ロールの作成」ボタンを押下

以上で、IAMのロール作成は完了です。
※各ポリシーがどういったものかは今回説明しませんが、IAMはAWSを利用する上で必須の知識なので、知っておいて損はないと思います！

### EC2インスタンスの作成
[EC2のインスタンス](https://console.aws.amazon.com/ec2/home?#Instances)のページより、「インスタンスの作成」ボタンを押下
<img width="1217" alt="スクリーンショット 2019-12-11 0.13.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209922/53b88478-8524-9d1e-3217-afe966d508e6.png">

その後ナビゲーションに沿って、

1. Amazonマシンイメージは、「Amazon Linux 2 AMI (HVM)」を選択
1. インスタンスタイプは、「t2.micro」を選択(無料利用枠の対象)し、「確認と作成」ボタンを押下
1. 選択したものが間違っていないか確認し、「起動」ボタン押下

続いて、IAMを割り当てます。
先程作成したインスタンスを選択し、「アクション」→「インスタンスの設定」→「IAM ロールの割り当て/置換」をクリックします。
<img width="1245" alt="スクリーンショット 2019-12-11 0.29.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209922/3033445f-2ed0-64a8-045f-de0e221ce590.png">

IAMロールに先程作成したIAMのロールを選択し、「適用」ボタンを押下します。

以上で、EC2の準備は完了です。

# aws-sam-cliインストール
続いて、先程作成したEC2上にaws-sam-cliをインストールしていきます。

先程作成したEC2へログインし、[こちら](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install-linux.html)のページを順に進めます。
※EC2には、[EC2のインスタンス](https://console.aws.amazon.com/ec2/home?#Instances)のページにて、該当インスタンスを選択し、「接続」から「EC2 Instance Connect (ブラウザベースの SSH 接続)」を利用すると簡単です。

Step1と2は既に完了していると思いますので、Step3からStep5までを実行しましょう。

# S3バケット作成
あともう少しです。お付き合いください。
S3バケットは、[こちら](https://s3.console.aws.amazon.com/s3/home)から「バケットを作成する」を押下後、ナビゲーションに沿って、任意の「バケット名」を入力するだけです。

（。。。てっ、手抜きではありません

ただしバケット名は、「Amazon S3 内の既存バケット名の中で一意」である必要があります。全世界共通です。

# sam用のテンプレート作成
今回は、lambdaのレイヤーとして、[php-lambda-layer](https://github.com/stackery/php-lambda-layer)を利用させてもらうので、そちらをコピペしてきて、EC2上にtemplate.yamlとして保存します。

合わせて、「lambdaで実行するPHPのコード」も任意のディレクトリに以下のような構成で、index.phpとして保存します。
今回は単純に「Hello World!!」と出力させます。

```directory.structure
.
├──template.yaml
└──src
　　└──php
　　　　└──index.php
```

```template.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: My PHP Application
Transform: AWS::Serverless-2016-10-31
Resources:
  phpserver:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Sub ${AWS::StackName}-phpserver
      Description: PHP Webserver
      CodeUri: src/php
      Runtime: provided
      Handler: index.php
      MemorySize: 3008
      Timeout: 30
      Tracing: Active
      Layers:
        - !Sub arn:aws:lambda:${AWS::Region}:887080169480:layer:php73:3
      Events:
        api:
          Type: Api
          Properties:
            Path: /hello
            Method: ANY
```

```index.php
<?php

  echo 'Hello world!!';
```

テンプレートについては、分かりやすいように、今回Path部分だけ「/hello」に書き換えています。

# デプロイ
テンプレートまで用意できたら、あとは2手順(コマンド)で完了です！

1. パッケージ化
1. デプロイ

### パッケージ化
まずはtemplate.yamlのあるディレクトリへ移動します。
続いて以下のコマンドを実行します。

```
sam package --template-file template.yaml --output-template-file serverless-output.yaml --s3-bucket バケット名
```

するとパッケージ化して、S3へアップロードしてくれます。
合わせてtemplate.yamlのCodeUriをS3のオブジェクトのURIに書き換えてserverless-output.yamlを出力してくれます。

### デプロイ
以下コマンドを実行します。

```
sam deploy --template-file serverless-output.yaml --stack-name スタック名 --capabilities CAPABILITY_IAM --region ap-northeast-1
```
※スタック名は、任意の名称でOKです。

初めて実行する場合は、もろもろのリソース作成等がありますが、次回以降は、コードの差分のみがlambdaにデプロイされます。
※何が作成されているかは、コマンドの出力を確認すると分かりますので、興味のある方は見てみるとより理解が深まると思います。

それでは早速アクセスしてみましょう！！

APIエンドポイントは、[こちら](https://console.aws.amazon.com/lambda/home)より、今回作成したlambda関数を選択し、「APIGateway」をクリックすると確認できます。
![screencapture-ap-northeast-1-console-aws-amazon-lambda-home-2019-12-12-00_40_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209922/10ea3dee-1bf2-41f5-e2c1-2e1c8e9aa4ea.png)



「Hello world!!」と表示されていればOKです！

# まとめ
いかがでしたでしょうか。何となくLambda(とServerless Application Model)が見えてきたでしょうか。意外と簡単に使えそうだなって思えてもらえましたか！？

ここまで記載しておいて何ですが、[php-lambda-layer](https://github.com/stackery/php-lambda-layer)にも記載がありますが、まだこちらは実稼働向きではないようです。（stay tuned for production-ready version comming soonとも言ってますが)

とはいえ、とりあえず動作させることが出来たならば、後はちょとアレンジして他の使い方を試してみたり、PHP以外の言語に置き換えてみたりできそう…ですよね！？

それでは皆様、素敵なハックライフを！！

明日は @chrno001 さんの記事です。