1
/
5

Laravel on ECSでのバッチ実行基盤事例

こんにちは。エンジニアの佐々木です。
最近、映画アルゴの主人公のような密度が濃く整った髭を目指し日々手入れを行っています。

さて。以前、社内勉強会で発表した「北欧、暮らしの道具店」におけるSREについての記事を書きました。

エンジニアが夜も安心して寝れているのは、何のおかげ?北欧、暮らしの道具店のSREこれまでとこれから|Kurashicom Tech Blog|note
こんにちは。エンジニアの佐々木です。 Monthly hyggeと呼んでいる、月に一回開催している社内勉強会があるのですが、1月末にこんな↓ゴールとテーマで話をしました。 2020年でやってきたことをじっくり振り返り、これからの課題もメンバーと共有できたので、ここでも公開しておこうと思います。 1. SREって?2. 2020年を軽く振り返る3. 2021年の課題4. その先は ...
https://note.com/kurashicom_tech/n/n8f5466288001

今回は、上の記事の中のスライド内で少しだけ触れていた「コンテナ技術(ECS/Docker)への移行」について、バッチ実行まわりでの技術選定や注意した点について紹介したいと思います。

目次

  1. ECS/Fargate移行前の課題
  2. バッチ実行、どうするか
  3. バッチ実行で2つの基盤を採用した理由
  4. ECS Scheduled Task導入時注意したこと
  5. 移行してみて
  6. 最後に

ECS/Fargate移行前の課題

「北欧、暮らしの道具店」はこれまで、AWSのOpsWorks(Chef)を使用しEC2の構成管理を行ってきました。

エンジニア3人で作った月間1600万PVのECサイト「北欧、暮らしの道具店」を支えるシステムの裏側 | クラシコム
こんにちは、エンジニアの濱崎です。クラシコムが運営するECサイト「北欧、暮らしの道具店」は、2016年5月にそれまで使っていたASPサービスを離脱し、フルスクラッチで開発したオリジナルのシステムにリニューアルしました。 今回は、リニューアルプロジェクトの裏話や、クラシコムのエンジニアが開発しているシステムについてご紹介します。 ...
https://kurashi.com/journal/11086

インフラ側の変更を反映するためには新しくプロビジョニングしたEC2を毎回用意する必要があるため、そのときには以下の様な課題を抱えていました。

- Web・APIサーバーとして動いているEC2インスタンスは、その数だけプロビジョニングを実行し新規でEC2インスタンスを作成。その後ALBのターゲットグループで入れ替え、というような作業が発生。サーバーが増えると辛さが増す
- バッチ処理は冗長化ができておらず、重複実行されたり意図しない動作となってしまわないよう、サーバーにログインしてcronを停止するなどのオペレーションが必要
- キューワーカーに関しても変更内容によってはサーバーにログインして停止するなどのオペレーションが必要

ちなみに、バッチ処理はLaravelのartisanで自作したコマンドをcronで管理し、キューワーカーはLaravelが用意しているキューサービスをsupervisorで管理していました。

これらのトイルを解消し、メンテナンスもしやすい状態にしたいと考えたときに出てきたのがECS/Fargateの採用です。

開発するときはローカル環境にてDocker、Docker Composeを使用していました。いろんなエンジニアに相談したり記事を参考にした結果、本番・ステージングもECS/Fargateに移行してしまうことで運用負担を減らしメンテナンスしやすい状態にできるだろう、と考えプロジェクトを進めました。

実際にECS/Fargateに移行するにあたって、Web・APIサーバーに関しては、ログをどうするか、監視をどうするか、ステージングの認証をどうするかなどいくつか課題はあったものの、それぞれCloudWatch Logs、mackerel-container-agent、Amazon Cognitoの採用でクリアできました。

この記事ではその辺りは割愛し、バッチの実行基盤に関して説明をさせていただきます。

バッチ実行、どうするか

バッチ実行の基盤に関してはcronを使わずともいくつかとれる選択肢があります。その中で今回採用したのが以下の2つです。

- sqsjkr
- ECS Scheduled Task


CloudWatch + SQS でバッチサーバー冗長化のために実装した「sqsjkr」の話 - KAYAC engineers' blog
Lobi の吉村(moulin)です。今回はCloudWatch + SQSのバッチサーバ冗長化のために作成した「sqsjkr」についてご紹介します。また、sqsjkrはGo実装です。 バッチサーバーとは、マシンリソースの消費が高い処理を定期的に実行させたい場合、本体アプリケーションに影響が及ばないようにするために建てられるバッチ処理専用のサーバーを指し、Lobiでも様々なバッチ処理を実行するサーバーを建てています。 バッチサーバーはcrontabが設定されているものが1台、バックアップとして同じ構成でc
https://techblog.kayac.com/2017/04/10/090000
スケジュールされたタスク
Amazon ECS は、スケジュールされたタスクの作成をサポートします。スケジュールされたタスクは、Amazon EventBridge ルールを使用して、スケジュールに基づいて、または EventBridge イベントへの応答として、タスクを実行します。 バックアップオペレーションやログスキャンなど、設定された間隔でタスクを実行する場合は、指定した時刻に 1 つ以上のタスクを実行するスケジュールされたタスクを作成できます。規則的な間隔 ( N 分、時間、または日ごとに実行)を指定したり、より複雑なスケ
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/userguide/scheduled_tasks.html

「北欧、暮らしの道具店」では基本的にsqsjkr、一部でECS Scheduled Taskを採用しました。それぞれの大きなpros、consを挙げると以下の通りになります。

sqsjkr
- pros
- Dockerイメージのpullが発生せず、常駐のプロセスが処理してくれるため処理開始までのオーバーヘッドが少ない
- cons
- 処理プロセスがタスク定義パラメータstopTimeoutの値以上かかる場合、デプロイ時にECSクラスターから強制停止されてしまう可能性がある
ECS Scheduled Task
- pros
- AWS公式の方法のため、ドキュメント・事例が多い
- タスクの実行が完了するまで基本的にコンテナが終了することはない(タイムアウトなどでの強制停止がない)
- cons
- コンテナとはいえ起動のオーバーヘッドがある。1minかかることも
- 毎回コンテナのpullが発生するため、NAT Gateway経由でpullした場合などはお金がかかる
- (退役したコンテナの履歴が大量に残るので邪魔に感じるときがある)

バッチ実行で2つの基盤を採用した理由

最初はすべてsqsjkrを採用し動かしていたのですが、本番切り替え前にconsに記載した強制停止する事象を発見し、ECS Scheduled Taskを追加で採用しました。

consに記載したstopTimeoutというパラメータは、コンテナが正常に終了しなかった場合にコンテナが強制終了されるまでの待機時間です。タスク定義パラメータの stopTimeout で設定できる最大値が120であり、デフォルトは30になります。

タスク定義パラメータ
タスク定義は、タスクファミリ、IAM タスクロール、ネットワークモード、コンテナ定義、ボリューム、タスク配置の制約事項、起動タイプの各部分に分かれています。ファミリーとコンテナ定義はタスク定義に必須ですが、タスクロール、ネットワークモード、ボリューム、タスク配置の制約事項、起動タイプはオプションです。 以下に示すのは、各タスク定義パラメータのより詳細な説明です。 タイプ: 文字列 必須: はい タスク定義を登録するときに、ファミリー (複数バージョンのタスク定義の名前のようなもの) を指定する必要がありま
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html

ECSのデプロイツールではecspressoを採用しているのですが、デプロイ時、コンテナの入れ替えのため古いコンテナを終了させる必要からECSクラスターが古いほうのコンテナに対してSIGTERMを送信します。しかし、バッチの処理内容によってはSIGTERMを受けてから処理が完了するまでに数分かかるなど、120秒を超えてしまうものもあります。

この問題によって、処理が途中で終了してしまったり、そのため排他処理のレコードが残り後続のバッチがいつまでも処理開始されなかったりといった問題を起こしてしまうことになります。

そこで、デプロイが発生してもコンテナが強制停止されないECS Scheduled Taskを採用しました。

ECS Scheduled Taskはecspressoでは管理できないため、ecscheduleというデプロイツールを別途採用しました。ecscheduleはecspressoにかなり影響を受けているというだけあって、使い勝手もよく導入はすんなりできました。

ecspresso handbook
Amazon ECS デプロイツール ecspresso の作者による解説本です。 チュートリアル、基本的な使いかた、応用的な使いかた、設計思想と実装、全コマンドのリファレンスを掲載しています。 ecspresso advent calendar 2020 に掲載した内容を再編
https://zenn.dev/fujiwara/books/ecspresso-handbook
ECSのScheduled Taskを管理するツールを作った | おそらくはそれさえも平凡な日々
その名もecschedule。だいぶ前から作っていたのだが、この度実戦投入した。 https://github.com/Songmu/ecschedule Nature社 では、ECS上でGoのサービスを動かしており、バッチ系の定期実行タスクもECS Scheduled Taskを利用している。 最近バッチの本数が増えてきて管理したくなり、このツールを導入しました。 便利だとは思うが、かなり社内事情にべったりであるため、フィードバック歓迎です。具体的には以下の制約を前提としています。 Rule名がユニーク
https://songmu.jp/riji/entry/2020-11-16-ecschedule.html

ECS Scheduled Task導入時注意したこと

sqsjkr、ECS Scheduled Taskどちらも仕組み上EventBridge(CloudWatch Events)、SQSを使用しています。

EventBridgeは仕様として、同じルールを複数回トリガーしてしまうことがあります。そのため、排他処理を行わないとバッチが多重実行されてしまい障害を起こしてしまう可能性があります。

CloudWatch Events のトラブルシューティング
このセクションの手順を使用して、CloudWatch Events のトラブルシューティングを行えます。 Lambda 関数に対する適切なアクセス権限が設定されていることを確認します。AWS CLI を使用して以下のコマンドを実行します (関数名を実際の関数に置き換え、関数がある AWS リージョンを使用します)。 aws lambda get-policy --function-name MyFunction --region us-east-1 以下のような出力が表示されます。 { "Policy":
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/CWE_Troubleshooting.html?fbclid=IwAR2rYOjBfgh0N6n_zt_7mnyjdWt5gqj7Ez2xSkEABV23vRdNAAcUYWAI4Ug#RuleTriggeredMoreThanOnce

sqsjkrに関しては多重実行されないよう、DynamoDBを使った排他処理の実装がなされています。

ECS Scheduled Taskに関しては自前で排他処理を用意する必要があります。

そのため、ECS Scheduled Taskで実行されるLaravelのarisanコマンドに関しては、排他処理を行うようDynamoDBにレコードをinsert/deleteする実装を追加で行いました。

移行してみて

ECS/Fargateに移行してみて、踏んだ課題はありましたがサーバーに入るオペレーションもなくなりバッチの運用がとても楽になりました。

sqsjkr, ECS Scheduled TaskどちらもEventBridgeを使っているので、サーバー内には入らずともecschedule/Terraformなどを使ってプルリクエストで特定のバッチだけを止めるということが可能になったり、AWSコンソール上から起動/停止の操作ができるのも、運用面ではとても大きいです。

最後に

クラシコムでは日々アプリケーション、インフラを改善し、継続し続けることができるシステム作りを目指しています。今回はインフラ面での話がメインでした。

クラシコムのインフラは、先日のISUCON11でも見事優勝した面白法人カヤックの fujiwara さんと週イチでMTGさせていただき、多くのアドバイスをいただいています。この記事のECS/Fargateまわりに関してもそうで、ありがたいことにコードレビューもしていただけています。

システムを良くしていくための土壌を今も作り続けてる途中ではありますが、一緒にアプリケーション・インフラ両面ともに改善を続け、良いサービスを提供していってくれる仲間を募集しています。

Invitation from 株式会社クラシコム
If this story triggered your interest, have a chat with the team?
株式会社クラシコム's job postings
8 Likes
8 Likes

Weekly ranking

Show other rankings
Like クラシコム 採用担当's Story
Let クラシコム 採用担当's company know you're interested in their content