24
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Laravelのサーバレス環境構築入門

Last updated at Posted at 2021-02-04

LaravelのAPIとバッチをサーバレスに構築したく下記3つを使って
APIGatewayとLambda環境を簡単に構築してみます。

  • PHPをLambdaで動かす為のサポートをしてくれるbref
  • LaravelをLambda用に動作するようにしてくれるlaravel-bridge
  • AWSにサーバレス環境を自動構築してくれるnpm serverless

Lambdaとは

  • Lambdaとは
    • インフラの構築・管理を気にしなくてよく、コードをアップすればLambdaが動かしてくれる
    • 自動でスケーリングしてくれます
    • 処理した時間だけ課金(個人レベルの利用であれば無料枠を超えることはほぼない
  • httpリクエストをトリガーにLambdaを使うためにAPIGatewayを使います
  • デメリット
    • Lambdaに合わせた実装が必要になる
      • 最大15分の処理時間に合わせる
      • httpリクエストだと29秒
      • 容量512MBまでなのでそれに合わせる
      • リクエストとレスポンスのペイロードが6MBまでといった細かな制約も
    • 関数インスタンスの起動が遅い
      • 数百ミリ秒の遅延が発生する
      • 設定によって起動したインスタンスを再利用することで改善できるようです
        • 料金は別途かかる
        • プロビジョニングされた同時実行
  • Lambda+RDS使うときの注意→RDSProxyを使う
    • LambdaからRDSへの同時接続数に上限があるのでアクセス多いとエラーになる(db.t2.micro/メモリ1GBだと85)
    • Lambdaは全てのプロセスが独立してしまうので、コネクションが使い回せず同時接続数がどんどん増えます
    • RDSProxyで既存のコネクションを再利用することができるので、同時接続数をこれでセーブする

詳細

  • リクエストを処理している関数のインスタンスは、リサイクルされるまで数時間アクティブのままになる
  • 関数は、/tmpディレクトリ内のローカルストレージにアクセス可

Laravelでの構築の仕方

1.(npm)serverlessのインストール

awsの認証情報もインストール後設定します。

$ npm install -g serverless
$ serverless config credentials --provider aws --key <key> --secret <secret>

2.(php)brefとlaravel-bridgeインストール

PHPをLambdaで動かす為のサポートをしてくれるbrefと、LaravelをLambda用に動作するようにしてくれる
laravel-bridgeをインストールします。

$ composer require bref/bref bref/laravel-bridge

3.serverless.ymlを生成

下記コマンドでserverless.ymlを生成します。
serverless.ymlはどんなAPIGateway・Lambdaを作るかの設計図になります。

$ php artisan vendor:publish --tag=serverless-config

4.serverless.ymlを自分の環境に合わせる

ほぼ修正する必要なく利用できますが、下記自分の環境に合わせて修正します。

  • regionの変更
  • timeoutの設定(デフォルト120秒。最大15分(900秒))
  • cronの設定(events > schedules)
    • artisanコマンドの場合、inputで「"」で括る('"video:channel"')

functions:
    # This function runs the Laravel website/API
    web:
        handler: public/index.php
        timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds)
        layers:
            - ${bref:layer.php-74-fpm}
        events:
            -   httpApi: '*'
    # This function lets us run artisan commands in Lambda
    artisan:
        handler: artisan
        timeout: 120 # in seconds
        layers:
            - ${bref:layer.php-74} # PHP
            - ${bref:layer.console} # The "console" layer
        events:
          - schedule:
              rate: cron(0 0 * * ? *) # GMT
              input: '"video:channel"'
          - schedule:
              rate: cron(15 0 * * ? *) # GMT
              input: '"video:videolist"'

5.AWSデプロイ

下記コマンド実行するとLambda+APIGatewayが自動構築されます。

$ php artisan config:clear
$ serverless deploy

ファンクション単位でのデプロイ

$ serverless deploy function -f <yourfunction>

6.自動デプロイ

ローカルでコマンドを打つのも手間なのでgit pushしたら自動で「serverless deploy」が走るようにします。
github actionを用います。

  • 1.S3のバケットに.envをアップロードする
    • .envはgit管理対象外にしたい
    • S3に.envアップロードしデプロイ時に利用する
  • 1.GithubのActions secretsを設定します。
    • AWS_ACCESS_KEY_ID
    • AWS_SECRET_ACCESS_KEY
    • S3_DOWNLOAD_BUCKET(.envファイル用
  • 2.workflowを作成

https://github.com/serverless/github-action
https://github.com/aws-actions/configure-aws-credentials

name: Deploy master branch

on:
  push:
    branches:
      - develop
defaults:
  run:
    working-directory: ./src
jobs:
  deploy:
    name: deploy
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [14.x]
    steps:
    - uses: actions/checkout@v2
    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ap-northeast-1

    - name: Download file from S3
      env: 
        S3_DOWNLOAD_BUCKET: ${{ secrets.S3_DOWNLOAD_BUCKET }}
      run: |
        aws s3 cp s3://$S3_DOWNLOAD_BUCKET/.env ./  --quiet

    - name: Output file contents
      run: |
        cat .env
    - name: Install Dependencies
      run: composer install --prefer-dist --optimize-autoloader --no-dev
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm ci
    - name: serverless deploy
      run: |
        npm i -g serverless@2.x
        serverless deploy
      env:
        AWS_REGION: ap-northeast-1
        AWS_VERSION: latest
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

あとはgit pushすればデプロイされます。

ローカル

開発環境

下記参考に実装しました。
/tmp以外ではコマンドからファイル生成できないので、やりづらい。(readonlyになる為)
https://bref.sh/docs/web-apps/local-development.html

version: "3"
services:
  db:
    image: mysql:5.7
    volumes:
      - ./db:/var/lib/mysql
      - ./initdb.d:/docker-entrypoint-initdb.d
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: vtuber
      TZ: "Asia/Tokyo"
    ports: ["3306:3306"]
  web:
      image: bref/fpm-dev-gateway
      ports:
          - '8000:80'
      volumes:
          - ../src:/var/task
      depends_on:
          - php
      environment:
          HANDLER: public/index.php
          DOCUMENT_ROOT: public
  php:
      image: bref/php-74-fpm-dev
      volumes:
          - ../src:/var/task:ro
          - ./tmp:/tmp

バッチ

ローカルからLambdaのバッチを実行する

# AWS_DEFAULT_REGION=ap-northeast-1 AWS_ACCESS_KEY_ID=[access_key_id] AWS_SECRET_ACCESS_KEY=[secret_access_key] vendor/bin/bref cli laravel-dev-artisan video:channel

php artisan migrateしたいときは下記です。
「--force」つけないと本番環境で「本当に実行しますか?」と入力待ち状態になってしまう為です。
https://mrkmyki.com/%E9%80%86%E5%BC%95%E3%81%8Dlaravel/laravel%E3%81%A7%E5%BC%B7%E5%88%B6%E7%9A%84%E3%81%ABmigration%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B

vendor/bin/bref cli laravel-dev-artisan -- migrate --force

AWS CloudWatchLogsの見方

REPORT RequestId: 3595eefc-ec9c-4021-a826-28453c0f5afd	Duration: 654.51 ms	Billed Duration: 980 ms	Memory Size: 1024 MB	Max Memory Used: 102 MB	Init Duration: 325.39 ms
  • Duration: 654.51 ms / 関数のハンドラーメソッドがイベントの処理に費やした時間
  • Billed Duration: 980 ms / 呼び出しの課金対象の時間
  • Init Duration: 325.39 ms / 最初に処理されたリクエスト(コールドスタート時)についてハンドラーメソッド外で関数をロードしてコードを実行するためにランタイムにかかった時間

24
29
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
29

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?