🔖
怪奇!ECSのタスクをFargateで実行するとたまに起動失敗する!(ヒント:SubnetSelection)
TL;DR
CloudFormationにおける AWS::Events::Rule
- AwsVpcConfiguration
- Subnets
は必須プロパティだが、CDKでは必須ではありません。
CDKで指定しなかった場合、VPC内から適当なサブネットが選択される(私の場合8つ)が、NAT Gatewayがアタッチされているかは考慮されないようです。
ECRのイメージをプルするには、PrivateLinkを使わない場合はインターネットへの接続が必要となるため、イメージが取得できずに起動に失敗していました。
事象
CloudWatch Rulesで定期実行に指定しているバッチ処理が3回に1回起動しませんでした。
単に起動しないだけではなく、
- CloudWatchのメトリクス(TriggeredRules および Invocations)は記録されている
- CloudTrailで ECSのRunTaskイベントのログを見ると、container のlastStatusは PENDING
- CloudWatch Logsへのアプリケーションログは記録されていない
と、CloudWatchからの呼び出しは成功しているのに、アプリケーションは立ち上がらない 、という状況でした。
どうやって原因究明したか
ECSタスクのイベントの変更をLambdaでCloudWatchに記録した上で、証拠が出るまでバッチ処理を走らせました笑
ECSタスクの記録方法は以下のチュートリアルに従いました。
結果、以下のようなログが得られました。
...省略
"containers": [
{
"containerArn": "arn:aws:ecs:ap-northeast-1:******:container/******",
"lastStatus": "STOPPED",
"name": "web",
"image": "******.dkr.ecr.ap-northeast-1.amazonaws.com/******:******",
"reason": "CannotPullContainerError: Error response from daemon: Get https://******.dkr.ecr.ap-northeast-1.amazonaws.com/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)",
"taskArn": "arn:aws:ecs:ap-northeast-1:******:task/******",
"networkInterfaces": [
{
"attachmentId": "******",
"privateIpv4Address": "******"
}
],
"cpu": "256"
}
],
...
はい。ECRからイメージをプルできていませんね。
対応としては、CDKのタスク起動時の定義でSubnetSelectionを明示的に指定しました。
反省
- CloudFormation → CDKに移行した環境では、CDKがよしなに処理してくれないこともある
- CDKで作成したリソースのCloudFormationテンプレートは確認しよう
Discussion