【Laravel & AWS】Elastic Beanstalkでアプリケーションサーバを構築 & CodePipelineで自動デプロイ【1日目】

せっかくAWSクラウドプラクティショナーになりましたので、忘れない内にAWSで色々ためそうと思う。
で、AWSのサービス縛りLaravelのインフラを組んだらどんな感じになるのか試してみることにした💡
一応、AWSが推しているコスト最適弾力性を目指していくつもり。
やりたい事をまとめると以下の通り。

  • アプリケーションサーバの構築
  • ビルド・テスト・デプロイの自動化
  • RDBに接続できる
  • cronを使える様にする(Laravelのタスクスケジュールのトリガー)
  • HTTPS対応
  • アプリケーションサーバのオートスケール&ロードバランシング
  • Redisに接続できる
  • リソースをCDNから配信する

アプリケーションサーバのコストについて、Price Calculatorで調べた所、低スペックサーバを水平に並べた方が安いっぽいので、これを基本の戦略とする。
ちなみに、CPU1個、メモリ1GBでリザーブドインスタンスにすると1年契約で月額1300円程度との事。

RDBについてはRDS for MySQLを使う。
db.t3.microでリザーブドインスタンスにすると1年契約で月額2000円程度

そんな感じでさっそくやっていく👏

Laravelアプリケーションを作る

まずはドキュメントを参考に空のLaravelアプリケーションを作成してGithubにプッシュする。
AWSにCodeCommitというコードのバージョン管理を行うサービスもあるけど、使われているケースを見たことがないし、まぁ餅は餅屋という事でここはGithubを使っておく。
念の為、ローカルで表示できる事を確認しておく👀

Laravelでスキャッフォルドされたトップページ

Elastic Beanstalkにデプロイしてみる

作成したアプリケーションをElastic Beanstalkにデプロイする。
Elastic Beanstalkはアプリケーションサーバに関するもろもろをよしなにやってくれる便利なやつだよ🤟

Deploying a Rails 5 App using Elastic Beanstalk and PostgreSQL
Elastic Beanstalkのアイコン

プラットフォームは一旦、PHPにする。
今後色々カスタマイズするならDockerでイメージを自作する必要があるかもしれない🤔

Elastic Beanstalkにデプロイしている図

ここで、デプロイするにはcomposer installしなきゃいけない事に気づいた🤨

CodeBuildを触ってみる

CodeBuildビルドやユニットテストの実行ができるらしいです。
ビルドで生成された一連のファイルはアーティファクトと呼ばれて、S3のバケットに保存されるとの事。
ちなみに、自前のDockerイメージでビルドすることも出来るようです。

AWS Developer Tools | AWS CodeBuild
CodeBuildのアイコン

buildspec.ymlというファイルがリポジトリに含まれている必要があるのでドキュメントリファレンスを参考に作成する。
PHPの場合、以下の様になった。
php7.3のランタイムを使って、composer installを実行して、全てのファイルをアーティファクトとして指定しています。

version: 0.2

phases:
  install:
    runtime-versions:
      php: 7.3
  build:
    commands:
      - composer install
artifacts:
  files:
    - '**/*'

で、ビルドプロジェクトを作成して実行した所、失敗になった😢

ログを見るとS3のアップロードまで完了している様にみえるが・・・?🤔

フェーズ詳細タブを確認するとエラーメッセージが表示されていた。
UPLOAD_ARTIFACTSというフェーズでS3にファイルをアップロードしているが、CodeBuildプロジェクトのリージョンとS3バケットのリージョンが一致してないため失敗しているらしい。
S3バケットを作り直してリージョンを合わせた。

CLIENT_ERROR: Error in UPLOAD_ARTIFACTS phase: AuthorizationHeaderMalformed: The authorization header is malformed; the region 'us-east-1' is wrong; expecting 'ap-northeast-1' status code: 400

またUPLOAD_ARTIFACTSフェーズで別のエラーが発生した😭

CLIENT_ERROR: Error in UPLOAD_ARTIFACTS phase: AccessDenied: Access Denied status code: 403

AccessDeniedと言っているので権限周りかなぁと思って、IAMのロールやポリシーをいじくり回したけど解決しなかった。
結局、ビルドプロジェクトを作り直したら発生しなくなった

これでS3にアーティファクトが保存される様になったが、今度は保存処理がタイムアウトする様になってしまった
なかなか多難やなぁ😰

BUILD_TIMED_OUT: Build has timed out.

どうやらアーティファクトのファイル数が多いとS3のアップロードが極端に遅くなるっぽいです。
例えばPHPのvendorフォルダが8000ファイル程あると10分待っても完了しませんでした。
以下の様にzip圧縮してからアップロードする様にすると数秒で完了する様になりました。

改めてElastic Beanstalkにデプロイしてみる

ソースのビルドが出来たのでアーティファクトが保存されているS3のバケットを指定して起動する

ElasticBeanstalkでアプリケーションを起動している図

Beanstalkにアプリケーションを作成できた
EC2にもインスタンスが作成されている。

ElasticBeanstalkにアプリケーションが作成された図
ElasticBeanstalkが作成したEC2インスタンスを確認している図

発行されたURLに/publicを付与してアクセスしてみるとLaravelのエラー画面が表示された
ソース自体は読み込めているっぽい。

内部の状態を確認するためsshで接続するする
eb sshコマンドで接続できるらしい。
こちらを参考にebコマンドをインストールする

ElasticBeanstalkのCLIツールのリポジトリ

eb initでリージョンやアプリケーションを選択する
eb ssh --setupでインスタンスにキーペアを設定する(アプリケーションが再起動するので注意)

改めてeb sshする
接続できた!💯

ElasticBeanstalkにSSH接続した図

/var/www/htmlを確認してみるとソースコードが配置されている事が分かる。
CodeBuildでzip化してS3に保存したが、ちゃんと解凍されて配置されている

-rw-r--r--  1 webapp webapp   4497  4月 29 18:35 README.md
drwxr-xr-x  6 webapp webapp   4096  4月 30 07:41 app
-rwxr-xr-x  1 webapp webapp   1686  4月 29 18:35 artisan
drwxr-xr-x  3 webapp webapp   4096  4月 30 07:41 bootstrap
-rw-r--r--  1 webapp webapp    151  4月 29 18:35 buildspec.yml
-rw-r--r--  1 webapp webapp   1586  4月 29 18:35 composer.json
-rw-r--r--  1 webapp webapp 207511  4月 29 18:35 composer.lock
drwxr-xr-x  2 webapp webapp   4096  4月 30 07:41 config
drwxr-xr-x  5 webapp webapp   4096  4月 30 07:41 database
-rw-r--r--  1 webapp webapp   1013  4月 29 18:35 package.json
-rw-r--r--  1 webapp webapp   1197  4月 29 18:35 phpunit.xml
drwxr-xr-x  2 webapp webapp   4096  4月 30 07:41 public
drwxr-xr-x  6 webapp webapp   4096  4月 30 07:41 resources
drwxr-xr-x  2 webapp webapp   4096  4月 30 07:41 routes
-rw-r--r--  1 webapp webapp    563  4月 29 18:35 server.php
drwxr-xr-x  5 webapp webapp   4096  4月 30 07:41 storage
drwxr-xr-x  4 webapp webapp   4096  4月 30 07:41 tests
drwxr-xr-x 44 webapp webapp   4096  4月 30 07:41 vendor
-rw-r--r--  1 webapp webapp    538  4月 29 18:35 webpack.mix.js

/storage/logs/laravel.logを確認すると以下のエラーが出ていた

production.ERROR: No application encryption key has been specified.

.envファイルが配置されていないので、環境変数を設定する
ebコマンドで設定する場合は以下の通り。

# 環境変数を確認
eb printenv

# 環境変数を設定
eb setenv key=value

環境変数はスクリプト化したりしないし(本末転倒なので)GUIで管理したいなぁ。
公式ドキュメントによるとマネジメントコンソールから設定できるっぽい。

環境プロパティ。若干わかりにくい名前だなぁ

無事Laravelアプリケーションが表示された!🤟

ElasticBeanstalkでLaravelアプリケーションを表示した図

コードを更新するとどうなるのか?

トップページのHTMLを書き換えてPUSHする。
v2表記を追加した

トップページのHTMLを編集している図

CodeBuildを手動でトリガーして、S3に新しいフォルダが作られてソースコードが配置された
で、ElasticBeanstalkでデプロイしようとしたが、S3のフォルダを指定する項目が無いな・・・???
「ファイルのアップロード」しかない・・・。😢

ElasticBeanstalkでデプロイしようとしている図

デプロイを自動化する

どうやら手動でS3からデプロイできないらしいので、こちらを参考にCodePipelineを使ってデプロイを自動化する
ソースステージビルドステージデプロイステージの3ステップの設定を行う必要があるらしい。
ビルドステージでは既に作成済みのCodeBuildプロジェクトを指定する

CodePipelineのビルドステージを設定している図

デプロイステージも、既に作成しているElasticBeanstalkのアプリケーションを指定する

CodePipelineのデプロイステージを設定している図

CodePipelineを作成すると以下の画面が表示された。
パイプラインの進捗がリアルタイムで確認できる
男の子だからこういうのワクワクしちゃう・・・🎵

CodePipelineの詳細画面

パイプラインの実行が完了したのでBeanstalkのアプリケーションバージョンを確認してみる。
新しいバージョンが作成されている。

Beanstalkのアプリケーションバージョン一覧画面

Laravelのトップページを開いてみる。
エラーが発生した😱

Laravelのトップページ

環境変数が消えてる・・・・。なんで?
再設定しなきゃだめか・・・。数が多いから面倒なんだよな・・・。

eb setenvコマンドを使えば複数同時に設定できるらしい。

eb setenv foo=bar JDBC_CONNECTION_STRING=hello PARAM4= PARAM5=

コマンド叩いたらエラー出たわ・・・。
1度に設定できるのは最大4096バイトらしい。
キーは最大128文字値は最大256文字との事。
上記の制限満たしててもエラーになる事あったけど、時間置いたりコマンドを小分けにしたりしてなんとか登録した

ERROR: ServiceError - Configuration validation exception: Invalid option value

無事、デプロイの自動化が完了して画面も開けた

バージョンの切り戻しをやってみる。

うっかり誤ったリリースしてしまった時などにバージョンを戻す方法を確認しておく。
過去のバージョンが自動的に保存されていて、アプリケーションバージョンのページから簡単に切り戻しできる

今日はここまで!🙆
次回はRDBの設定をやっていく!

「【Laravel & AWS】Elastic Beanstalkでアプリケーションサーバを構築 & CodePipelineで自動デプロイ【1日目】」への9件のフィードバック

コメントする