AWSインフラ構築時のエラー対処備忘録
ECSコンテナサービスを作成中、バックエンド(Rails、Nginx)のサービス作成時に発生したエラーについて記録します。具体的には、NginxのCloudWatchログに以下のエラーが発生しました。
connect() to unix:///app/tmp/sockets/puma.sock failed (111: Connection refused) while connecting to upstream, client: 10.0.3.73, server: localhost, request: "GET /api/v1/health_check HTTP/1.1", upstream: "http://unix:///app/tmp/sockets/puma.sock:/api/v1/health_check", host: "10.0.4.4"
使用技術
・フロントエンド
UIフレームワーク:Nuxt.js(Vue.js), Vuetify
HTTP通信:axios
コード整形:ESLint/Prettier
・バックエンド
言語・フレームワーク:Ruby 3.1.3・Rails 7.0.4
コード品質:RuboCop
テスト:RSpec
サーバー:Nginx, Puma
データベース:MySQL 8.0.31
・インフラ/デプロイメント
コンテナ:Docker
クラウド:AWS (ECR,ECS,Fargate,VPC,S3,Route53,ALB,RDS,ACM,SSM,CloudWatch)
IaC(インフラコード化) :Terraform
CI/CD :GitHub Actions
調査1: NginxとPuma間の通信確認
NginxとPuma間の通信に問題がないか確認するために、まずDocker Composeでコンテナを立ち上げ、その後コンテナ内でソケットファイルの存在やパーミッションを確認しました。
nginxコンテナにアクセス
docker exec -it english_app2-web-1 /bin/sh
/ # ls -al /app/tmp/sockets
total 8
drwxr-xr-x 2 root root 4096 Feb 10 03:28 .
drwxr-xr-x 7 root root 4096 Dec 5 00:59 ..
srwxrwxrwx 1 root root 0 Feb 10 03:28 puma.sock
rails側のコンテナにもアクセス
docker exec -it english_app2-api-1 /bin/sh
/app # ls -al /app/tmp/sockets
total 8
drwxr-xr-x 2 root root 4096 Feb 10 12:28 .
drwxr-xr-x 7 root root 4096 Dec 5 09:59 ..
srwxrwxrwx 1 root root 0 Feb 10 12:28 puma.sock
結果、puma.sock が nginx コンテナと Rails アプリケーションが動作している api コンテナの両方に存在し、それぞれのコンテナで同じパス /app/tmp/sockets にあることが確認できました。次に、ECS ExecでECS起動コンテナにアクセスしました。
以下コマンドでNginxコンテナにアクセスし、
aws ecs execute-command \
--region ap-northeast-1 \
--cluster myapp-prod-ecs-cluster \
--task b2e9b10e392b4094956a17071fa9d1da \
--container myapp-prod-container-nginx \
--command "/bin/sh" \
--interactive
ソケットファイルの存在とパーミッション確認:
コマンド
ls -lah /app/tmp/sockets/
実行結果
/ # ls -lah /app/tmp/sockets/
total 8K
drwxr-xr-x 2 root root 4.0K Feb 11 10:53 .
drwxr-xr-x 7 root root 4.0K Feb 11 10:52 ..
srwxrwxrwx 1 root root 0 Feb 11 10:53 puma.sock
Nginxの設定ファイル検証:
コマンド
nginx -t
実行結果
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Nginxのプロセス状態確認:
コマンド
ps aux | grep nginx
実行結果
/ # ps aux | grep nginx
1 root 0:00 nginx: master process nginx -g daemon off;
31 root 0:00 nginx: worker process
32 root 0:00 nginx: worker process
75 root 0:00 grep nginx
次に以下コマンドでrails側のコンテナにもアクセスし、
aws ecs execute-command \
--region ap-northeast-1 \
--cluster myapp-prod-ecs-cluster \
--task b2e9b10e392b4094956a17071fa9d1da \
--container myapp-prod-container-back \
--command "/bin/sh" \
--interactive
Pumaのプロセス状態確認:
コマンド
ps aux | grep puma
実行結果
root 1 0.1 15.4 242576 146992 ? Ssl 19:52 0:04 puma 5.6.5 (unix:///app/tmp/sockets/puma.soc
root 102 0.0 0.0 1608 764 pts/0 S+ 20:30 0:00 grep puma
ソケットファイルの存在とパーミッション確認:
コマンド
/app # ls -lah /app/tmp/sockets/
実行結果
total 8K
drwxr-xr-x 2 root root 4.0K Feb 11 19:53 .
drwxr-xr-x 7 root root 4.0K Feb 11 19:52 ..
srwxrwxrwx 1 root root 0 Feb 11 19:53 puma.sock
PumaとNginxの設定に問題はなく、両者間の接続も正常であることが確認できました。
調査2: コンテナ起動順序の確認
次に、RailsコンテナとNginxコンテナの起動順序に問題があるのではないかと考えました。Rails側(Puma)が先に起動する必要があるため、タスク定義でNginxコンテナのスタートアップの依存関係の順序に条件「START」を設定し、サービスを更新しました。しかし、エラーは解消しませんでした。
"dependsOn": [
{
"containerName": "myapp-prod-container-back",
"condition": "START"
}
恐らくpumaが完全に起動する前にnginx側のコンテナが起動してしまっていることが原因と考えました。下記の記事等を参考にして、Rails側のコンテナにpumaのヘルスチェックを追加した上で、nginx側のdependsOn設定の「“condition”: “START”」の部分を「“condition”: “HEALTHY”」に変更しました。
https://bluepixel.hatenablog.com/entry/2020/04/22/230721
記事を参考にタスク定義の設定を行いましたが、サービス作成時にヘルスステータスが異常となっていました。原因は、curlコマンドがRailsコンテナにインストールされていなかったためでした。RailsコンテナにcurlをインストールするようDockerfileを修正し、ECRにプッシュしてECSサービスを更新したところ、Nginxのログにエラーが表示されなくなり、問題が解決しました。
dockerfileにcurlを追記
FROM ruby:3.1.3-alpine
ARG RUNTIME_PACKAGES="linux-headers libxml2-dev make gcc libc-dev nodejs tzdata mysql-dev mysql-client git yarn libc6-compat curl"
以下略
・rails側
HealthCheckオプションの設定
コマンド CMD-SHELL,curl --unix-socket /app/tmp/sockets/puma.sock http://localhost/api/v1/health_check || exit 1
間隔 30秒
タイムアウト 5秒
開始期間 15秒
再試行 3
スタートアップの既存関係の順序
設定なし
・Nginx側
HealthCheckオプションの設定
設定なし
スタートアップの既存関係の順序
条件:Healthy
以上