全力で怠けたい

怠けるために全力を尽くしたいブログ。

ECS の Fargate で動かしてるコンテナが socket: too many open files で外部のサーバーに接続できないときにやったこと。

ECS の Fargate で動かしてるコンテナが socket: too many open files で外部のサーバーに接続できないときにやったことのメモ。

ECS で動かしてるコンテナが外部のサーバーに接続できなくなる

やったこと

ことの始まりはとある ECS の Fargate で動かしてるコンテナが突然外部のサーバーに接続できなくなるのに気が付いたときだった。

問題のコンテナは DB とかキャッシュで使ってるサーバーに接続していろいろやるのだけど、どうも問題のコンテナから DB サーバーとかキャッシュサーバーに接続できなくなることがあるようだった。 問題のコンテナからは常に DB とかの外部サーバーに接続できないわけではなくてちゃんとそのへんの外部サーバーに接続できている時間帯があるようなのだけど、接続できたり接続できなかったりという感じで時間帯と接続可否の状態には関連性はないっぽい。 問題のコンテナはいろいろと動作検証に使ってるけど外部には公開していないので、おそらく動作検証のなにかが影響して外部のサーバーに接続できなくなっている可能性が高い。

結論

コンテナのログを見たら一発で原因が分かった。

コンテナのログは外部サーバーに接続できない時間帯は socket: too many open files が大量に出力されていて、たぶんこれはコンテナ使うファイル数がファイルディスクリプタの制限に引っかかっていそう。

コンテナで設定する ulimits のリスト。このパラメータは、Docker Remote API の コンテナを作成する セクションの Ulimits と、docker run の --ulimit オプションにマッピングされます。

Fargate タスクは、デフォルトのリソース制限値を使用します。ただし、Fargate がオーバーライドする nofile リソース制限パラメータを除きます。nofile リソース制限は、コンテナが使用できるオープンファイルの数の制限を設定します。デフォルトの nofile ソフト制限は 1024、ハード制限は Fargate タスク用で 4096 です。これらの制限は、タスクでより多くのファイルを処理する必要がある場合は、タスク定義で調整できます。

コンテナは CDK で構築してるので ContainerDefinition#addUlimits()UlimitName.NOFILEsoftLimithardLimit が大きくなるようにこんな感じで設定した。

このあとコンテナを ECS にデプロイしたら socket: too many open files がログに出力することがなくなって問題のコンテナからちゃんと外部のサーバーに接続できるようになった。

container.addUlimits({
  name: UlimitName.NOFILE,
  softLimit: 6144,
  hardLimit: 12288,
});

参考サイト