Laravelプロダクト Fargate化への道
記事に整理したのでこちらはCloseします
#phperkaigi
(わかったこと・ぶつかった壁が多くなりすぎていて5分に収める工夫が必要なので立ち上げ)
前提
- コードリポジトリが docker-compose 化されている
- AWS を利用している
- PHP 7 系以上
- Laravel 5.8 以上
- セッションストアにRedisを使用
- フロントエンドは Vue.js で開発
Step 1 アプリケーションのイメージ化
・・・
build:
context:
dockerfile:
args:
・・・
↓
・・・
image:
・・・
ログ出力をファイルから標準出力へ
composer install を Dockerfile で
docker build 前に Vue.js のビルドを済ませるように
docker build の作業拠点を Amazon Linux Workspaces にしていたことは大きかったはず
(ビルド時間面。 Docker for Mac 辛い)
[躓いていたこと]
-
ディレクトリがない編
- storage 配下のディレクトリが足りてなくて
- 特に、 storage/framework/cache/data
- bootstrap/cache ディレクトリに書き込み権限がなくて
- storage 配下のディレクトリが足りてなくて
-
build 時には Redis と繋がってないので
- php artisan cache:clear をDockerfile中でやるとエラーになる
- php artisan config:clear しないと環境変数が古いまま
ログ出力をファイルから標準出力へ
この点、文化として浸透していない現場がそれなりにありそう
「セッションをファイルで持つ」のを Redis 等の共有ストレージに変えておく、のようなスケールアウトを意識した初動にもしておいた
Step 2 イメージ化したアプリケーションを動かす
-
docker-compose up
してコンソール出力とにらめっこ
Step 3 インフラ構築(ECS は cluster まで)
以下の順に module 化 しつつ順次 apply
-
network
- vpc
- subnet
- nat gateway
- (vpc endpoint : 後で追加)
- Gateway
- Interface
-
security
- public
- private
- storage
- (vpc_endpoint)
-
ecs-fargate
- ecs cluster
- alb
- iam role
-
data-store
- rds
- elasticache
[苦戦したこと]
- RDS cluster の構築
- Redis cluster の構築
数々の terraform apply 爆死
[思い出]
@chaspy_ 氏との 2月3日頃
終盤で ECR pull ができなくなって大苦戦
相当焦った
問題のポイントは、プライベートサブネットに 443 ポートの疎通を入れてなかったこと。
Fargate 1.4.0 での VPC Endpoint 設定が必要になったところが腹落ちしてなかった。
ECS cluster のキャパシティプロバイダー、オートスケールはまださわれていない
FARGATE_SPOT 把握したい
サービスディスカバリはチョットできた
Step 4 ecspresso で ECS サービス・タスク定義構築
- 手始めは
maintenance
service- nginx-proxy
- 次にDBマイグレーションをする用の
artisan
service- laravel-app
- そして、年末年始に学習しておいた、nginx - laravel 一体タスクを実装
だいたいの流れ
-
init
は特に使わず json でサービス定義・タスク定義を記述 -
verify
でシンタックスチェック -
--dry-run
でどういうタスク定義が作られるかを最終確認 - 初回は
create
でサービス作成 - 2回目以降は
deploy
- 作り直すときは一旦
scale --tasks=0
->delete
- マイグレーションは
run --skip-task-definition --overrides="{\"containerOverrides\":[{\"name\":\"laravel-app\",\"command\":[\"make\",\"migrate\"]}]}"
今のところ、rollback --deregister-task-definition
は使っていない
古くてもう使わないタスク定義の登録解除は今のところ手動
デプロイ後の整理問題、そこかしこにありそう
Step 5 デプロイ簡素化
今のところ、CircleCI 版のみ。近日中に Bitbucket Pipelines 版が生まれるはず。
だいたいのワークフロー構成
- check
- 開発メインストリーム ブランチのみで filter
- test-fresh-seed
- local 用の 環境変数を direnv で load
- Vue.js build
- docker build
- DB migrate:fresh --seed を走らせる
- (なぜか成功しないのでコメントアウト中)
- 完了時に Slack に通知
- test-fresh-seed
- 開発メインストリーム ブランチのみで filter
- ecr-update
- ステージング・本番環境用ブランチのみで filter
- パラメータ run_push を true にした API からのリクエストのみで発動
- build
- staging 用の 環境変数を direnv で load
- Vue.js build
- docker build
- docker tag
- ECR への push まで
- docker tag
- aws ecr login
- docker push
- 完了時に Slack に通知
- build
- ecs-deploy
- ステージング・本番環境用ブランチのみで filter
- パラメータ run_deploy を true にした API からのリクエストのみで発動
- 要承認 : CircleCI の管理画面で実施可能
- 開始時に Slack に通知
- ecspresso のインストール
- make jsonnet (タスク定義 ecs-task-def.json 作成)
- make verify
- make dry-deploy
- make deploy <- デプロイ本体
- 完了時に Slack に通知
- ecs-rollback
- ステージング・本番環境用ブランチのみで filter
- パラメータ run_rollback を true にした API からのリクエストのみで発動
- 要承認 : CircleCI の管理画面で実施可能
- 開始時に Slack に通知
- ecspresso のインストール
- make jsonnet (タスク定義 ecs-task-def.json 作成)
- make verify
- make dry-rollback
- make rollback (ecspresso rollback --deregister-task-definition) <- ロールバック本体
- 完了時に Slack に通知
- db-migrate
- ステージング・本番環境用ブランチのみで filter
- パラメータ run_migrate を true にした API からのリクエストのみで発動
- 要承認 : CircleCI の管理画面で実施可能
- 開始時に Slack に通知
- ecspresso のインストール
- make jsonnet ( "artisan" タスク定義 ecs-task-def.json 作成)
- make verify
- make mg-run (php artisan migrate 実行) <- マイグレーション実行本体
- 完了時に Slack に通知
今後の課題など
- Vue.js のビルドに時間がかかるのはキャッシュするなどして短縮したい
- 毎度、デプロイ用のエグゼキューター(Amazon Linux2 をカスタマイズした Docker イメージ)を pull している・・・
- CloudWatch にヘルスチェック ログが流れないように
- ノイズ感甚だしい
- バッチ処理実行コンテナ
- ecschedule を運用してみる?
- NGINX の resolver を入れたい
- サービスディスカバリ機能で DNS キャッシュのために疎通できなくなるのを避けたい
- ブルーグリーンデプロイ
- もっと気軽に検証できるように
- ECS Exec
- php artisan cache:clear をオンデマンドでしたい!!
- 接続元IP制限
- ステージング環境は内部公開にとどめたい場合