💨

AWS CodeDeployでmigration実行したい(Laravel)

2024/02/09に公開

AWS CodeDeployでの自動デプロイにmigration実行を含みたい
1回のリリースでmigration実行が1回きりにされるようにしたい

背景

AWS CodeDeployのデプロイ処理の中にmigration実行を含めているが、複数のインスタンスでmigration実行されてしまい2回目以降のmigration実行で失敗する。
それにより以下の事象が発生。

  • デプロイの失敗
  • DBのデッドロック

結論 やったこと

deploy.shでhostnameを見て本番、STG、DEVそれぞれで1回ずつしか実行されないようにした

instances=('dev-hogehoge-1' 'stg-hogehoge-1' 'prd-hogehoge-1')
if echo "${instances[@]}" | grep -qw `hostname`; then
  # migrate
  sudo -u nginx php artisan migrate --force
fi

✌️

え、でもそれだとインスタンスの名前変わったらまた修正必要ジャン(ᵔᴥᵔ;)
と誰しも思うのですが、今回は以下案を検討した上で上記結論になりました。

考慮した案

デプロイ設定を直列型にする

CodeDeployのデプロイ設定がCodeDeployDefault.OneAtATimeになっているから全インスタンスで同時にmigrationが実行されている。
同時でなければmigrationは本来1度しか実行されない仕組みになっているので、デプロイをひとつのインスタンスずつにすれば2つめ以降ではmigration実行されない。

却下理由😢
デプロイ時間が長くなる。
そのトレードオフは許容できない。

migration実行用のデプロイグループを作成する

migration実行用のデプロイグループを作成して、各環境につき1つのインスタンスをそのグループに入れる。
グループに入れる用のタグはterraformで管理できるのでデプロイシェル内で直接インスタンス名参照するよりも対応漏れが防げそう

却下理由😢
migrationはソースコードのデプロイ後に実行しないといけないので、ソースコードデプロイ用のCodeDeployと切り離せない。

migration実行用のサーバーを作成

アプリケーション用のサーバーへデプロイする前に、migration用サーバでコードのデプロイとmigration実行をする。
おそらく本来はこの方法が安全そう。

却下理由😢
コストな。

感想

恥ずかしながらシェルスクリプトを書くと言う経験がなく、地味に構文(if文とか配列の書き方とか)で躓いた😇
今回は急ぎの対応(直近でマイグレーション実行が必要なリリースを控えていたため)だったので最も手軽な方法で修正しました。

Discussion