ECSでRakeタスクを実行する
ECS環境でRailsサーバを運用する場合、コンテナにSSHするのは一般的ではないので、 従来的な手法、即ち稼働しているサーバインスタンスに入ってそこからrakeタスクを起動したり、RailsConsoleを起動して何かしたり、といった運用は現実的ではありません(よね?)
では運用に必要なジョブをどうやって実行すれば?という事で、 任意のRakeタスクを起動させる方法に関して見てみたいと思います。
Rakeタスクを起動する
方法はとても単純です。
Railsサーバを起動させるためのタスク定義がすでに存在する前提ですが、これは通常満たされているものと思いますので、残る手順はこれだけです。
- (Railsサーバを起動させるためのタスク定義で) タスクを起動させる
- その際に、コンテナのコマンドを
bundle exec rake hoge:fuga
で上書きする
ECSでは個々のタスク
と、タスクを複数束ねたサービス
という概念があります。
アプリケーションサーバーは通常サービスとして構成され、その中のタスクではサーバプロセスが起動(bundle exec rails server
)します。
Rakeタスクを実行させる場合は、サーバーのタスクとは別個にタスクを起動させ、その中でRailsサーバと同じコンテナを起動させ、でも実行させるコマンドを別モノにする*事によって、任意の処理を実行させる訳ですね。
*なのでRakeタスクを起動させる以外の事も可能
マネコンからのタスク起動 (少々難有り)
実際の、マネコンからの手順は以下です。
- タスクの起動
あるいはタスク定義一覧からもタスクを起動できます - コマンドの上書き
以上なのですが、マネコンからの実施には少々難があります。
- 新しいUIはコンテナオーバーライドの設定に対応してない (2022/4/13時点) ので、旧UIを使う必要がある
- VPCやセキュリティグループ設定などは記憶されないので、実行の都度指定する必要がある
- 上書きするコマンドに、
カンマを含むコマンド
を指定できない- ↑に添付したように、コマンド文字列をダブルクォーテーションで囲まずに指定する必要があります。このため、コマンドの中でカンマを使いたい場合*でも、それがエスケープされずに区切り文字と認識されてしまい、期待したようになりません。
*Rakeタスクに複数の引数を取りたい場合など。フォームにbundle,exec,rake,hoge:fuga[arg1,arg2]
と入力しても"bundle","exec","rake","hoge:fuga[arg1","arg2]"
に分解されてしまうため
特に3番目が予想外ですよね。どうしてこんな事に??と思わざるを得ないのですが、この辺りが問題になる方は、現状ではCLIやSDKを使う他無いようです。
新UIが早く諸々綺麗に対応する事を期待したいです。
検討しておきたい事
ここまで紹介したのは 一つのタスク定義をRailsサーバとRakeタスクとで共有する やり方ですが、タスク起動時に上書きできる設定項目は限られているため、制約もあります。
- LogGroupを分けられない (LogStreamに別個のPrefixを設定する事も出来ない)。
- 対策:自分で識別子をセットする
- デフォルトLoggerの progname を使用するのが良さそう(出力側も対応する必要あり)
namespace :hoge do task fuga: :environment do Rails.logger.progname = "rake:hoge:fuga"
- 対策:自分で識別子をセットする
- その他、↓に載ってない全ての設定は共通になる
全く自由に設定等を変えたい要望があるのなら、タスク定義を別個にするという選択肢も有りだと思います。
普通に考えると管理コストが増すだけで良い事は少ないと思うのですが、CI等で自動化すれば事故も減らせるかなとは思います。
但しそこまでコンテキストを分けたいのであれば、それはもう同じアプリバンドルでは無いのでは?という気も。。
定期起動させるには?
タスクを起動させるスケジュールを設定する事ができますので、そちらからどうぞ scheduled_tasks
別解として、サーバタスク内でCronをセットする手もありますが、あまりお薦めはしません。
- コンテナイメージにCronが必要 ←alpineなどのイメージには入ってないので、自分で追加する必要がある
- Cronへの登録処理が面倒 ←wheneverなどのGemを
- タスクが複数起動する場合は冪等性への配慮が必要
- 負荷の高い処理を行うと、本来の用途であるサーバ性能が悪化する
上記を踏まえて、限定的用途であれば有りかもしれませんね。