ECSでのデプロイでコケる原因ざっくりまとめ
前提知識もそこそこにチャレンジした結果
ハマって色々勉強になったので簡単にまとめます。
自分がはまったところ、主にタスク周り中心です。
環境
イメージとしては以下のような感じです。
docker-compose
↓
GitHubActions→ESR
+
ecspresso
↓
ALB
↓
ECS
+
EC2
↓
RDS
awsの管理はterraformで行なっています。
ECSのタスク入れ替えが落ち着く時間
自分がはまったポイントとしてはecspresso deploy実行時なぜか以下のように
タスク定義の入れ替えがループして落ちるというものでした。
2022/05/02 09:25:49 test-service/sample-ecs-cluster Registering a new task definition...
2022/05/02 09:25:49 test-service/sample-ecs-cluster Task definition is registered test-service:98
2022/05/02 09:25:49 test-service/sample-ecs-cluster service attributes will not change
2022/05/02 09:25:49 test-service/sample-ecs-cluster desired count: 1
2022/05/02 09:25:49 test-service/sample-ecs-cluster Updating service tasks...
2022/05/02 09:25:52 test-service/sample-ecs-cluster Waiting for service stable...(it will take a few minutes)
2022/05/02 09:26:03 test-service/sample-ecs-cluster PRIMARY test-service:98 desired:1 pending:0 running:1
2022/05/02 09:26:03 test-service/sample-ecs-cluster ACTIVE test-service:89 desired:1 pending:0 running:1
2022/05/02 09:25:54 (service test-service) has started 1 tasks: (task xxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx).
2022/05/02 09:26:13 test-service/sample-ecs-cluster PRIMARY test-service:98 desired:1 pending:0 running:1
2022/05/02 09:26:13 test-service/sample-ecs-cluster ACTIVE test-service:89 desired:1 pending:0 running:1
2022/05/02 09:26:04 (service test-service) registered 1 targets in (target-group arn:aws
:elasticloadbalancing:ap-northeast-1:***:targetgroup/sample-http/xxxxxxxxxxxxxxx
)
2022/05/02 09:25:54 (service test-service) has started 1 tasks: (task xxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxx).
2022/05/02 09:26:23 test-service/sample-ecs-cluster PRIMARY test-service:98 desired:1 pending:0 running:1
2022/05/02 09:26:23 test-service/sample-ecs-cluster ACTIVE test-service:89 desired:1 pending:0 running:1
2022/05/02 09:26:04 (service test-service) registered 1 targets in (target-group arn:aws
:elasticloadbalancing:ap-northeast-1:***:targetgroup/sample-http/xxxxxxxxxxxxxxx
)
解決法
単純にecspressoのconfig.yamlのtimeoutをデフォルトの10分に伸ばしたら
6分30秒くらいでエラーなく通りました。
原因
おそらく他にも原因を色々探っていたのでどこかのタイミングでtimeoutをいじってしまっていたのがこのループの原因でした。
ecspresso deployの解説ページに詳細を書いてくださっていたので助かりました。
上記ページには「ECSサービスが stable の状態になるまで待つ」と書かれており
ECS上でサービスが安定するまでの時間timeoutを設定した方がよさそうです。
他に原因になり得るところ
自分で体験したものとしては以下がありました。
GitHubActionsの環境変数が読み込めていなかった
railsのMASTERKEYやAWSのKEY情報などはGitHubActionsのActions secretsに
登録することでCI上から環境変数のような形で呼び出せるのですがそこの設定が抜けていました。
(余談ですがこれらKEY情報はGitHubのリポジトリに上げてしまうと怖いので注意しましょう)
ロードバランサのヘルスチェック
ロードバランサのヘルスチェックでヘルスチェック用のURLを用意せずにデプロイしていました。
結果、タスクが立ち上がっては落ちを繰り返すという現象になりました。
ヘルスチェックのパスとHTTPステータスコード周り(リダイレクトしている時など)も原因になりますので注意です。
以下は自分では経験していないですが後述の参考動画で語られていたところです。
AWS他のリソースが原因の場合当然ながら
GitHubActionsやecspressoではエラーを検知できない場合もあるので
一つ一つ確認していく必要があります。
セキュリティグループ
前述のような構成だとサービス間でセキュリティグループが設定されています。
これらが適切に設定されていない場合。例えば
・VPCが違う場所に設定されていたり
・ポートが違っていたり(これはアプリ側で待ち受けるものも併せて確認が必要)
・サブネットが違っていたり
すると通信が通らずエラーとなります。
ネットワーク関連
セキュリティグループでも既に触れていますが
ネットワーク自体も構成要素が増えるとそれに伴い複雑化していくので一つ一つ丁寧にみる必要があります。
サブネットはパブリックなのかプライベートなのか
IWGのアタッチはされているか、ALBからの通信は通っているか
などまずはコンテナを使用しないで通信ができているかを確認しても良いと思います。
データベース
EC2まで通信が通っていればデータベース周りのエラーが出るので
エラーをよく読めばわかるケースも多いと思いますが
当然データベースにアクセスできなくてエラーが発生している場合もあります。
IAM権限まわり
こちらはKEY管理も含めて確認が必要ですね。
またCIで実行する際には実行ユーザーに対して付与する権限と
(プリンシパルに設定するアイデンティティベースポリシー)
EC2やs3などに設定する権限
(リソースベースポリシー)
この両方が適切に設定されていないと実行でエラーが出ます。
アイデンティティベースポリシーのアクション一覧は以下から参照できます。
ログの見方
自分の環境ではCloudWatchにロググループを作成して吐き出していたのと
GitHubActionsの実行ログを確認していました。
ログを繰り返しみると解決のヒントが浮かぶことがありますね。
参考
ECS公式ドキュメント
AWSの方とecspressoの作者の方がデモしてくれている貴重な動画
ecspresso公式ドキュメント
所感
デプロイ周りをローカルから本番まで整えるだけでも
結構前提知識が必要になりますね。もっと複雑な環境はたくさんあると思いますが
今回シンプルなRailsアプリを動作させるだけでも以下の前提知識を使っていました。
・Linuxのディストリビューション(Debian、Alpine Linux)
・Linuxコマンド、シェルスクリプト
・Docker
・Git、GitHub、GitHubActions
・AWS関連の知識
∟Route53
∟Certificate Manager
∟CloudWatch
∟IAM
∟VPC
∟ALB
∟EC2
∟ECS
∟ECR
∟RDS
・Railsなどアプリケーションの知識
∟HTML
∟CSS
∟JavaScript
∟Ruby
・DB設定周りの知識
∟MySQL
∟SQLite
ecspressoはBlue/Greenデプロイやロールバックもできそうで
他のCIツールとの連携も便利そうですね。
また時間を作って試してみたいです。
Discussion