はじめに
タイトルの通り、"AWS Batchで作られるEC2インスタンスがECSクラスターに入らない!"というハマり方をしてなんとか解決できました。
今後同じようになった人の解決の助けになればと思います。
TL;DR
- 選択するEC2は自分のリージョンで対応しているものを調べて選択しよう
- Batch実行環境に割り当てるサブネットがいずれかであるか確認しよう
- インターネットGWへのルーティングテーブルを持っていて、かつ、"パブリック IPv4 アドレスの自動割り当て"がYesである
- インターネットGWへのNATゲートウェイをルーティングテーブルに持っている
1つ目のハマったところ → 原因: AWS Batchで選択しEC2たインスタンスタイプが東京リージョン未対応だったため
現象
AWS BatchにてCompute environments、Job queue, Job definitionsを作成しJob実行後、"RUNNABLE"の状態で止まったままでした。
このとき、EC2インスタンスはできていませんでした。AutoScalingGroupの設定を見ると下記スクショのようなエラーメッセージが出ていることがわかりました。
エラーメッセージテキスト
a user request created an AutoScalingGroup changing the desired capacity from 0 to 1.
an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 1
原因と解決
これはAWS Batchで選択しEC2たインスタンスタイプ(a1系)が東京リージョン未対応だったことが原因でした。
[EC2]東京リージョンで構築可能なインスタンスタイプのアベイラビリティーゾーン別一覧表の記事を参考に対応しているインスタンスタイプを選ぶようにAWS Batchのompute environmentsを再設定するとこのエラーが解決され、次実行時にはEC2インスタンスが作成されました。
2つの目のハマったところ → 原因: Compute environmentsで選択したサブネットが外部ネットワークに接続できない状態だった
現象
1つ目の問題を解決でき、EC2インスタンスができましたが、そのEC2インスタンスがAWS Batchが管理するECSクラスター内に入らずBatchのジョブがRUNNABLEのままという状況になっていました。
原因と解決
調査
公式のAWS Batch ジョブ が RUNNABLE ステータスで止まっているのはなぜですか?の記事を確認しましたが、この記事上の項目はすべて問題なしとわかり、
それでもインスタンスが Amazon ECS クラスターに参加していない場合は、インスタンスに接続します。次に、 Docker デーモン と Amazon ECS コンテナーエージェントのステータスを確認します。
この手順を実施しました。
AWS Batchが作成したEC2インスタンスは Amazon ECS コンテナーエージェントなるDockerコンテナを自身に立ち上げこれが動くことがECSクラスターで動くことを意味していると知りました。
踏み台サーバを経由しAWS Batchが立ち上げたEC2インスタンスへSSHしDockerコンテナの状況を確認しました。
$ docker ps
これを確認すると、Dockerコンテナが作られては無くなっていることがわかりました。
そこで立ち上がっているときにコンテナ内のログを確認すると下記のようなエラーが出ているとわかりました。
$ docker logs -f ecs-agent
level=info time=2020-06-22T13:06:09Z msg="Loading configuration" module=agent.go
level=info time=2020-06-22T13:06:09Z msg="Image excluded from cleanup: amazon/amazon-ecs-agent:latest" module=parse.go
level=info time=2020-06-22T13:06:09Z msg="Image excluded from cleanup: amazon/amazon-ecs-pause:0.1.0" module=parse.go
level=info time=2020-06-22T13:06:09Z msg="Amazon ECS agent Version: 1.36.2, Commit: 0e4174f6" module=agent.go
level=info time=2020-06-22T13:06:09Z msg="Creating root ecs cgroup: /ecs" module=init_linux.go
level=info time=2020-06-22T13:06:09Z msg="Creating cgroup /ecs" module=cgroup_controller_linux.go
level=info time=2020-06-22T13:06:09Z msg="Event stream ContainerChange start listening..." module=eventstream.go
level=info time=2020-06-22T13:06:09Z msg="Loading state!" module=state_manager.go
level=info time=2020-06-22T13:06:10Z msg="Registering Instance with ECS" module=agent.go
level=info time=2020-06-22T13:06:10Z msg="Remaining mem: 3725" module=client.go
level=error time=2020-06-22T13:06:31Z msg="Unable to register as a container instance with ECS: RequestError: send request failed\ncaused by: Post https://ecs.ap-northeast-1.amazonaws.com/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)" module=client.go
level=error time=2020-06-22T13:06:31Z msg="Error registering: RequestError: send request failed\ncaused by: Post https://ecs.ap-northeast-1.amazonaws.com/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)" module=agent.go
明らかにネットワークの問題っぽい文言。
sudo yum update
を実行すると実行がされない。。ネットワークの問題なのが確定です。
ECSインスタンスがクラスターに登録されないの記事に出会い、ネットワークの様子を見ると私の場合は__ルーティングテーブルの箇所が悪く__、__AWS BatchのCompute environmentsが持つサブネットが外部ネットワークにつながらないものだった__ことが原因とわかりました。
解決方法
その1
__インターネットGWへのルーティングテーブルを持っていて、かつ、"パブリック IPv4 アドレスの自動割り当て"がYesである__サブネットを作成しそのサブネットにCompute Environmentを割り当てます。
その2
公式のパブリックサブネットとプライベートサブネットを持つ VPC (NAT)の記事を参考にNATゲートウェイがTargetになるルーティングテーブルを作成。そのルーティングテーブルを持つサブネットを作成し、そのサブネットをAWS BatchのCompute environmentsに紐付けると無事にJobが走るようになりました。
注意点として、こちらは既存でNATゲートウェイを持っていない場合、その分の料金が1つ目と比べてかかります。
