ECS/fargateでタスクが終了してしまう場合のデバッグ方法【Rails】

# はじめに

RailsアプリをEC2からECS/fargateに移行するに当たり、
なかなかタスクが起動できませんでした。

その大きな要因は
**`タスクが終了してしまうエラー原因`**を
**`AWSコンソール画面やCLIでどうやって確認するか`**が
分からなかった為でした。

という訳で、自己整理用に
**`ECS/fargateはどうデバッグしていけば良いか`**をまとめています。


# 使用技術
* AWS(ECS/Fargate)
* Rails6(Ruby2.7)
* MySQL8


# エラー確認方法
1. マネジメントコンソールのECS画面を確認する
2. マネジメントコンソールのCloudWatch画面を確認する
3. コンテナに接続後、Railsの本番用ログを確認する


# 1. マネジメントコンソールのECS画面を確認する

AWSマネジメントコンソールのESC画面に表示されるエラー文から
タスクが停止してしまった原因を確認する方法です。

では、以降はコンソール画面を参照しながら説明します。

まず、AWSの提供サービスからECSを検索します。
![スクリーンショット 2021-12-06 14.31.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/b3ddcd79-131e-e6b1-2cf8-fd10ab691f9f.png)


クラスターのタブを押して、対象クラスターをクリックします。
![スクリーンショット 2021-12-06 14.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/7def75a2-08ea-9631-09bd-c77bbc8ace19.png)

さらに対象サービスをクリックします。
![スクリーンショット 2021-12-06 14.35.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/cfc12a41-5c0a-d60a-9b43-28e8371c98ea.png)


対象サービスに関連するイベントを確認すると、大まかなエラー要因が確認できます。
（私の場合、ELBヘルスチェックに原因があった為、このエラー文が表示されています。）
![スクリーンショット 2021-12-06 14.37.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/177d03bd-0105-b7eb-0b77-0f3036854e10.png)

これだけでも思い当たる節があれば、デバッグできますね！！


# 2. マネジメントコンソールのCloudWatch画面を確認する

次はマネジメントコンソールのCloudWatch画面からエラー文を確認する方法です。

タスク定義内のコンテナ設定画面でCloudWatchLogsでログ収集する設定を行なっていれば、
アプリケーション側で発生しているログを確認できます。

■CloudWatchLogsの設定
![スクリーンショット 2021-12-06 16.04.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/a608837a-fcfa-c425-ae42-fd6d24dc53fb.png)


では、同様にマネジメントコンソール画面を参照しながら説明します。

まず停止したタスクのIDを確認してコピーしておきます。
![スクリーンショット 2021-12-06 14.37.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/9cf352a7-b812-57e5-357b-800e486bec1c.png)

コピーしたタスクIDを貼り付けて対象タスクのみ表示されたら、同タスクをクリックします。
![スクリーンショット 2021-12-06 14.51.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/b7734087-acfd-76f1-3c28-1cb8a094cb1c.png)

対象タスクの画面にページ遷移したら、
`下にスクロールして、`
コンテナ名の横にある`▼ボタン`をクリックして詳細を広げて、
`CloudWatchのログを表示`をクリックします。
![スクリーンショット 2021-12-06 14.59.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/f4b7db1b-1d46-b14b-0496-443ff00f2849.png)

すると、CloudWatchの画面にページ遷移します。
ここからアプリ側で発生しているログが確認できます。
（私の場合、ヘルスチェックの猶予時間が切れて強制的にサーバーが落ちています。）
![スクリーンショット 2021-12-06 15.02.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/2131f41f-9b12-0b2f-c325-ee97db640823.png)


# 3. コンテナに接続後、本番用のログを確認する

最後に、ECS Execを用いて、ローカルPCからコンテナに接続して
直接デバッグする方法を紹介します。

前提としてタスクのステータスが「RUNNING」でないと
コンテナにはアクセスできません。

では、先に準備として以下5つの作業を行います。

`⑴SessionManagerのインストール`
`⑵IAMでポリシーのアタッチ`
`⑶ターミナルでコマンド実行(対象サービスに操作許可を設定)`
`⑷サービス更新`
`⑸ターミナルでコマンド実行（コンテナに接続）`


## ⑴SessionManagerのインストール

まずAWS公式ページをもとに任意ディレクトリでSessionManagerをインストールします。

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html#install-plugin-macos


```shell:ターミナル

# 任意のディレクトリでインストーラーをダウンロード
% curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/mac/sessionmanager-bundle.zip" -o "sessionmanager-bundle.zip"

# 解凍する
% unzip sessionmanager-bundle.zip

# インストールする
% sudo ./sessionmanager-bundle/install -i /usr/local/sessionmanagerplugin -b /usr/local/bin/session-manager-plugin

# ちゃんとインストールができているか確認
% session-manager-plugin

```


## ⑵IAMでポリシーのアタッチ
次にマネジメントコンソールのIAMからタスク実行ロールにポリシーを追加します。

AWSサービス一覧からIAMを検索して選択します。
![スクリーンショット 2021-12-06 16.35.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/c0203a9a-9cfd-8dbd-4e49-823a27ccdde8.png)

ロールのタブを選択して、ecs実行ロール(ecsTaskExecutionRole)をクリックします。
![スクリーンショット 2021-12-06 16.37.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/11ae535d-8489-1fbf-0332-f8e8cd988271.png)

専用ポリシーを作成後に同ロールにアタッチする為、
`ポリシーをアタッチします`をクリックします。
![スクリーンショット 2021-12-06 16.39.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/9fdf6367-f58e-7a00-b3f6-ca98b998a323.png)

先に専用ポリシーを作成する為、
`ポリシーの作成`を押して、ポリシー作成画面に遷移します。
![スクリーンショット 2021-12-06 16.40.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/709b322a-7cfb-b161-b3a9-ea807380021a.png)

AWS公式ページを参考に専用ポリシーをコピーして、JSONタブを選択後に同ポリシーを貼り付けます。
その後に`次のステップ`をクリックします。

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-required-iam-permissions

![スクリーンショット 2021-12-06 16.42.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/1879f171-8491-4849-06eb-75ccd30c8781.png)

ここでは何も入力せずに、そのまま`次のステップ`を押します。
![スクリーンショット 2021-12-06 16.45.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/ecbec80c-e87a-3412-640b-d59a6fd8caf3.png)

ポリシーに任意の名前を付けて、ポリシーを作成します。
![スクリーンショット 2021-12-06 16.47.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/d1035c29-d8f8-d075-334a-b76c1d60e2a3.png)

最後にecsTaskExecutionRoleの画面に戻り、先ほど作成した専用ポリシーをアタッチします。
![スクリーンショット 2021-12-06 16.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/2392c4e8-ee06-2f23-6d30-32661fcdf08f.png)



## ⑶ターミナルのコマンド実行(対象サービスの接続許可)

続いて、ローカルPCのターミナルでコマンドを実行しておきます。

下記コマンドは、操作対象のサービスだけexecute-commandを有効化させるものです。
(マネジメントコンソールからリージョン名・クラスター名・サービス名は事前にメモしておいてください。)

```shell:ターミナル

# 対象サービスに関するexecuteコマンドを有効化する
% aws ecs update-service --region リージョン名 --cluster クラスター名 --service サービス名 --enable-execute-command

# 「Shift ＋　G」で一番下までスクロールしてenable-execute-commandを確認する
# 確認できたら、qを押して元のプロンプトに戻す

```


## ⑷サービス更新

次の作業は対象サービスの更新です。

理由はIAMで作成したecs実行ロールを更新させる為です。

ECSコンソール画面から対象サービスを更新します。
![スクリーンショット 2021-12-06 18.32.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/23d80c41-f7bb-38d4-d52c-44ffb61cda06.png)

忘れずに`新しいデプロイの強制`にチェックします。
それ以外は編集せずにサービス更新を完了させてください。
![スクリーンショット 2021-12-06 18.34.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/fefcf3a0-7fde-f4f6-3b25-331df88ff469.png)



## ⑸ターミナルでコマンド実行（コンテナに接続）

最後にコンテナに接続します。

まずコマンドに必要な`[クラスター名、タスクID、コンテナ名]`を確認します。

■タスクの画面
![スクリーンショット 2021-12-07 7.58.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1380401/de560559-a53b-0bb4-9884-cb1bc52b9dff.png)



あとはターミナルでコマンドを実行して接続します。

```shell:ターミナル

# 対象コンテナにexecuteコマンドでインタラクティブモードで接続する
% aws ecs execute-command --region リージョン名 --cluster クラスター名 --task タスクID --container コンテナ名 --interactive --command "/bin/sh"

###(参考まで：Rails)
# 本番環境で吐かれたログを表示する
/app # cat log/production.log

# 本番環境で設定できている
/app # echo $RAILS_ENV
production

# MySQLへの接続
/app # mysql -h RDSのエンドポイント -u RDSのユーザー名 -p
Enter password: パスワードを入力

# データベースが作成されているか
MySQL [(none)]> show databases

# app_dbというデータベースを選択する
MySQL [(none)]> use app_db

# テーブルが作成されているか
MySQL [(app_db)]> show tables

```
# ECS/Fargate構成のインフラ構築について

ここで、EC2からECS/Fargate構築に移行する手順をまとめています。

■第一部(ECS準備編)

https://qiita.com/Shuhei_Nakada/items/9e4c51bf9ae59f0b1a2b

■第二部(ECS起動編)

https://qiita.com/Shuhei_Nakada/items/247d6f1781d6a3765482

■第三部(HTTPS/固定ドメイン編)

https://qiita.com/Shuhei_Nakada/items/a7f2fd64f0af9663ed29

■第四部(CircleCI連携編)

https://qiita.com/Shuhei_Nakada/items/2e3a5afde0bd215b334d



# 終わりに

AWSマネジメントコンソールを使いこなすのムズイなぁ…と感じております。

~~ECS/fargate上にアプリをホストできたら、その手順をQiitaに投稿できたらなーと思っています。~~
→ ホスト完了したので、上記記事でまとめています。

最後までお読みいただき、ありがとうございました!