エンジニア

2019.05.14

バッチ処理をECSに移行した話(GitHubActionsもあるよ)その1

バッチ処理をECSに移行した話(GitHubActionsもあるよ)その1

はじめに

こんにちは、ハンズラボの清水です。東急ハンズのECサイトを担当しています。今回はEC2上で動いている外部ECモール連携バッチをAmazon ECS ScheduleTaskに移行しました。そして、GitHubにpushした際にECRにイメージをpushできるようなGitHubActionsも作成しました。今回はECSのScheduleTask機能を使用してバッチ処理を作成していきます。

※外部ECモールとはyahooや楽天といったショッピングサイトのことです。

既存バッチ処理の内容

既存のバッチ処理ではEC2インスタンス上にバッチサーバーを用意、cronにスケジュールを登録してバッチを叩いています。
処理の内容としては、Auroraに追加された注文変更情報を取得して、注文情報商品の数量変更、注文キャンセル等を行っています。
今回は注文情報変更処理をECSに移行しました。

ECSへ移行

移行の理由

移行の理由としては以下の点が挙げられます。

  • AWSのサポートを受けられる
  • 各バージョンアップに対応できる
  • EC2を冗長化したい
  • dockerを使用するのでローカルでの開発が楽になる

注文情報変更の処理のみをdockerのイメージとして切り出し,ECR(Amazon Elastic Container Registry)にpushします。 Amazon ECS ScheduleTaskでスケジュールを指定して、処理を開始します。

ECRの作成

ECR(Amazon Elastic Container Registry)の作成を行い、ローカル開発環境にあるdockerイメージをECRへpushします。はじめにECRでリポジトリを作成しましょう。作成したらリポジトリ名をコピーしておくと後々楽です。

dockerイメージの作成&ECRへpush

ECR(Amazon Elastic Container Registry)へpushする用のdockerイメージを作成して,pushしましょう。以下のbashスクリプトで行いました。

#!/usr/bin/env bash
# DCTを有効化
DOCKER_CONTENT_TRUST=1
# ecrにログインする
aws ecr get-login --no-include-email --region ap-northeast-1
# 先ほど作成したリポジトリ名を使用する
docker build -t hogehoge .
docker tag hogehoge:latest <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge:latest
docker push <アカウントID>.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge:latest

のちのAmazon ECS ScheduleTaskで説明しますが作成したDockerfileENTRYPOINT"/bin/ash"のようにしておくとコンテナの挙動を変更できます。(今回はpython:3.7.3-alpine3.8を使用したのでashです)

クラスターを作成

ECSからクラスターを作成します。クラスターのテンプレートですが、今回は出て行くIPアドレスを固定したいためFargateを使用せずにEC2を利用しました。 クラスターの設定は各自お任せします。

後に気づいたのですが、NATGatewayにElasticIPをつけることでFargateでもIPアドレスを固定できます。

タスクを定義

ECSからタスクを定義します。起動タイプはEC2を選択。

コンテナ定義でコンテナの追加します。イメージには先ほど作成したECRのURLのパスを貼り付ければOK。

環境のコマンドに今回はテストとしてecho testを実行します。

ログ設定のAuto-configure CloudWatch Logsにチェックを入れておくとCloudWatch Logsにログを吐いてくれるのでチェックを入れました。

タスクを実行してみる

作成したクラスター→タスク→新しいタスクの実行からタスクを実行する。 先ほど作成したクラスターとタスク定義を選択をして実行しましょう。 実行ログはCLoudWatchLogsに吐かれるので確認しましょう。

成功です。

スケジュールを設定する

作成したクラスター→タスクのスケジューリングから作成します。
スケジュールタイプはCron式でも設定できます。タスク定義を先ほど定義したタスクを設定して作成完了です。

CloudWatchLogsでログを確認したところスケジュール通りに動いてくれています。

ハマったところ

タスクが実行されない(CloudWatchメトリクスにFailedInvocationsが出ている)問題がありました。調査の結果以下の二つが問題の原因でした。

  • インターネットに接続出来ていない(ElasticIPを付与したら解決)
  • コンテナインスタンス IAM ロールに権限が付与されていない(IAMロールからECSFullAccessつけることで解決)

終わりに

今回はECSのECS ScheduleTaskを利用してバッチ処理を移行しました。次回はGitHubActionsを利用したECRへのpushを紹介できればと思います。

一覧に戻る