のーずいだんぷ

主に自分用メモですが、もしかしたら誰かの役に立つかもしれません

<AWS>EC2のuser-dataでメインアプリケーションの実行をしてはいけない

はじめに

本記事はタイトルについての不具合の備忘録である。

正直、私の未熟さ故の不具合であり普通のエンジニアならこんな失敗はしないものと思うが、念の為書き記しておく。

システムの概要

業務でとあるシステムを開発しており、そのインフラとしてEC2を採用していた。

そしてそのシステムは常時タスクがあるようなシステムではなく、どちらかというとサーバレスアーキテクチャがフィットするような、逐次実行系のシステムだった。

本来ならば、Lambdaを使用するところなのだが、Lambdaの最大処理時間の関係上選択できなかった。仕方なくEC2をLambdaライクに使うことにし、具体的にはS3にファイルが置かれるタイミングをトリガとして、EC2を起動させるようなアーキテクチャとなる。

このアーキテクチャのポイントとして、実行するアプリケーションをインスタンスが立ち上がるたびに実行させるような仕組みをなんとかして作る必要があった。

私はその時に、EC2のuser-dataを使用した。

user-dataとは?

ec2の実行時にコマンドを実行するための仕組みである。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/user-data.html

これは非常に便利で、本来ならばsystemdでservice化しないと実行できないような処理を、シェルスクリプトを書くだけで簡単に実行できる。

例えば、起動するたびに実行するような設定は以下のURLを参考にするとよい。

aws.amazon.com

実際にはこのuser-dataはEC2のcloud-initというsystemdのようなブートプロセスタスクの一部として実行される。

cloud-initについては調べると色々情報が充実しているので見てみると良いだろう。

どういう問題が起こったのか?

本題の問題だが、今回実行させようとしたアプリケーションは処理対象のファイルサイズによって負荷が上昇するアプリケーションだった(ある程度は当然だが)のだが、 一定以上対象規模が大きくなると、途端にアプリケーションが重くて全く進まなくなるという問題だった。

厄介なことにある程度の規模(数件〜数千件)では問題なく、また負荷試験を行ったときは直接インスタンスにログインしてアプリケーションを実行したのだがその時は全く問題なかったため、気づくのが遅れてしまった。

この問題の特徴

多くの場合、アプリケーションの動作が遅くなったらCPUやメモリ、ディスクIO等のコンピュータリソースにいずれかがボトルネックになっていると想定するだろう。

私も今回、いくつかの主要なパラメータについて調べたのだがその結果が奇妙だった。

  • topコマンドの結果 → load-averageが1以上になっている(処理待ちが発生している。)
  • CPU、メモリともにどのプロセスも数%程度しか使用していない。
  • diskIOもボトルネックになっている様子はない。
  • ネットワークも帯域に対して余裕がある。

原因と解決策

正直言うと、真因はわからなかったがなんとなく予想がついた。それはブートプロセス中にメインアプリケーションを実行するのはまずいのではないか、となんとなく感じていたからだ。

おそらくではあるが、ブートプロセス中に実行すると、並列でいくつかの優先度が高いタスクが実行されるのではないかと思う。またuser-dataの実行タスク自体がcloud-initのタスクの一部なので、実行中ずっとブートプロセスが終了しないことになる。

今回は解決策として、本プログラムをsystemdのサービス化することで、無事に解決する事ができた。

真因が不明なのが正直かなりモヤモヤするので、今後ブートプロセス周りも勉強していこうと思う。