AWSの話題を中心に、日々の業務やプログラミングの徒然を綴るエンジニアブログです。

HANDS LAB

HANDS LAB ENGINEERS BLOG

ハンズラボエンジニアブログ

すごいVBAをLambda+HTML帳票+Puppeteerに置き換えた話

Pocket

CRMチームのyktakaha4です。

今日は、私たちが日々開発・運用しているハンズネットにおけるレガシーマイグレーションの現場をお届けします。

みなさんは、Excel、とりわけVBAはお好きでしょうか?

方々のエンジニアから親の仇のように忌避されながらもなぜだか中々無くならず、今日においても大小様々な企業で使われ続ける不思議な存在です。
嘘だとお思いでしたらInxxxxやレバxxxで「VBA」で検索してみてください。年収700万円も夢じゃないみたいですよ…?

私はExcelもVBAも好きです(でした)。

Officeの入ったWindowsがあれば使えるという可搬性に加え、
ユーザーフォームやExcel関数、CreateObjectやDeclareまで駆使すれば、控えめに言ってどんな処理でも実現できます。
また、Numbersやスプレッドシートの関数名、GASにおける各種オブジェクト名なんかを見ても、彼らがいかに広く浸透した概念であるか分かります。

前職では金融系の社内システムを開発していたのですが、資格を取得するくらいには活用していました。
もちろん不満・力不足に思う部分も沢山ありますが、エンドユーザと同じコンテキストを共有できて、どこでも使えて何でも作れるって、それ普通に全エンジニアの夢じゃないかと思うのですが…!

しかしながら、潮目は少しずつ、でも着実に変わってきています。
過去にはExcelでPythonが使えるようになるかもというニュースがあったり(結局JavaScriptになったんでしょうか?)、東急ハンズでも各種RPAツールの導入や、G Suiteの利用を推進していたりと、その利用の場は減っています。
令和の時代にはきっと新たな何かが世を席巻し、その陰に消えゆく運命にあるのでしょう…

そんなVBAに最後の餞として用意されたかのごとく、東急ハンズでExcelとVBAが大活躍する業務がありました。

そう、ハンズネットの荷札発送業務です。

ハンズネットは、すごーく大まかに言って、東急ハンズ新宿店の在庫をバックヤードで梱包してヤマト運輸経由で発送しています。
ヤマト運輸で商品を発送するためには、所定の送り状にお届け先の情報を印字してダンボールに貼り付ける必要がありますが、
この荷札の作成及び印刷をExcelとVBAマクロを駆使しておこなっていたのです。

図にあらわすと以下のような感じです。

出荷担当者目線では「梱包作業の時間になったらWebの画面にボタンが出るんで、押したら荷札が出てくる」程度のものですが、
システム担当者からすると、業務ロジックに基づいた荷札種類の決定、データへの書式設定、mm単位での微調整が必要なレイアウト、バーコードの生成、複数プリンタを指定する必要のある印刷処理などが渾然一体となったすごいやつ(尊敬)を保守し続けなければならず、
私含むエンジニアのほぼ全員がMacbook Proで開発を行なっている現状においては、環境を用意するだけでも一苦労…という状況でした。

そんな中、今年の10月に施行される消費増税、とりわけ経過措置としての軽減税率導入へ向けた対応の中で、当マクロの改修が必要なことが分かりました。
東急ハンズでは軽減税率対象となる食料品を一部扱っており、税率を分ける必要がある→荷札と一緒に添付する領収書で表示する税額を分けたり、商品ごとの税区分を明示する必要があったんですね。

現行のマクロを改修するという逃げの一手もありましたが、CRMチームのエンジニアリーダであるwatarukuraさんの判断もあり、この機会に保守が容易な別の仕組みに置き換えようという運びとなりました。
(私見ですが、こうした判断をエンジニアサイドから自発的におこなえるのは弊チームの良いところの一つだと思います。こちらもよければご覧ください)

今回は、マイグレーションによってコードを保守可能なものに置き換えることと、複数システムにまたがる税対応の中でスピード感を持って改修することを優先し、
外部サービスやパッケージを使うといった抜本的な運用変更までは考えず、既存と同等の荷札を別の仕組みで出力できるようにする…という方向性で改修方針を立てました。

改修後は以下のようになりました。

ユーザ目線では、従来Web画面でボタンを押下した際に自動的に荷札が印刷されていたのが、
出荷対象の全ての荷札が印字されたPDFファイルがダウンロードされるのでそれを印刷する…という形になっています。
印刷方式についてはチーム内でも議論がありましたが、業務部門のOKをもらった上で、今回の作業スコープからは一旦外すこととしました。
(運用がこなれてきたらより良い形を考えて、改めて提案したいですね…!)

業務的な話とは別に、本対応のキモであるVBAをPDF生成APIに置き換えた部分をもう少し詳しく紹介しておきます。

大枠では、VBAに組み込まれていた業務ロジックとデータへの書式設定をNode.jsに置き換えた上で、Excelでレイアウトしていた荷札をテンプレートエンジンであるEJSを用いたHTML帳票として出力し、それを更にGoogle ChromeのヘッドレスブラウザのPuppeteerでPDF化する…という感じです。
HTMLならVBAよりは修正にかかる心理的負荷を軽減できますし(WinMergeを使えば…とかあるかもしれませんが、コードでそのまま比較できるのはデカいと思います)、PDFはフォントや画像埋め込みもできて環境差異が出づらく、かつ業務部門にとってもある程度扱えそうなものだったため、利用技術として選定しました。
Puppeteerを使ったのは、公式で活発に開発が行われていたからというのもありますが、東急ハンズではGoogle Chromeを社内標準のブラウザとして定めており、色々知見が溜まれば今後に活かせそうに思えたからです。

また、今回の業務要件特有の話になりますが、1日の間に締め時間が数回あり、その時点までに受け付けた注文をなる早で荷札出力する必要がある…という課題がありました。
一回の締め処理で扱う注文数は、業務的な繁忙期も考慮すれば最大で約1000注文程度を想定しなければならず、
処理量に応じていい感じにスケールアウトしつつ、出荷のない夜間帯などはお金が掛からない仕組みを構築したいと考えていました。
あと、細かい話ですが、プリンタがジャムったり締め処理後に注文情報が変更になった時用に、個別に荷札を再印刷する機能も作らなければならず、バッチ・Webの双方から呼び出し可能なAPIである必要もありました。

これについては、社内でも幾つかのプロジェクトで利用実績のあったServerless Frameworkを使って、APIとしてリクエストを受ける親のLambda関数と、EJSによるレンダリング〜PuppeteerでPDF出力までを担う子のLambda関数をそれぞれ別に定義し、処理量に応じて子Lambda側の並列実行数を増やして対応することとしました。

平行処理については、作る前は苦戦しそうかな…?と思っていた部分だったのですが、結果的にはほとんど詰まるところがなく、改めてマネージドサービスは便利ですごいな…と思い知りました。
また、Serverless Frameworkについても、ソースコードのパッケージングからデプロイ、関数毎のメモリ使用量やタイムアウト秒数まで面倒見てもらえるので、本番デプロイなどコマンド1発で済んでしまい、大変助かりました。

最後に。
ご参考まで、対応前後の荷札サンプルも貼っておきます。今まで単に荷札と説明してきましたが、右部は商品明細になっていて、切り取ってダンボールの中に入れるようになっています。
上が対応前(VBA)、下が対応後(PDF)です。開発中の写真で位置調整が甘いですが、なんとなく雰囲気は分かってもらえるのでないかと思います。

VBA版
PDF版

余談ですが、従来バーコードコントロール9.0でおこなっていたバーコード出力はJsBarcodeを使うようにしました。フォントもおなじみMSゴシックからNoto Sansに変えたので、なんとなく見やすくなった感じがしますね。

現在は、従来のExcelバージョンとPDFバージョンを双方出力できるような状態で本番化して、処理量と処理速度を監視しつつ、業務部門に不都合がないか最終確認してもらっている段階となっています。
消費税対応のためにはじめたマイグレーション作業でしたが、これをきっかけに、実は他にも荷札で直したいところがあって…というような依頼もいくつか頂くようになり、業務改善にも寄与できそうでいい感じです。

っていうか、ようやく税対応のスタート地点に立つことができたという話なので、
これがキャリア最後のVBA対応になることを強く願いつつ、もう一息頑張っていきます…!

Pocket

ボードゲーム「プロジェクトテーマパーク」をプレイ!

Pocket

こんにちは。前回の更新からだいぶ経ってしまっていました。松本です。

ハンズラボではプロジェクト管理ツールとして、主にnulabさんのbacklogを活用させていただいています。backlogはプロジェクトごとに課題管理、ガントチャート、Wikiなどをまとめられるサービスです。
かわいらしいデザインが印象的ですよね。

そんなnulabさんがかわいさとプロジェクト管理要素をフルに活かしてなんとボードゲームを作ったそうです!
それがこちらの「プロジェクトテーマパーク」

レポート記事を書けばこの「プロジェクトテーマパーク」をプレゼント!というキャンペーンを見つけたので考えるよりも早く即申し込み。
幸運にも当選し、ゲームが届いたので社内有志と試遊会を開きました。
(※キャンペーン申込期間は終了しました)

その様子の一部

  • 「協同建築?ペアプロってこと?」
  • 「こういうことですよね?(突然ゲームルールのフロー図を書き始める)」
  • 「「リスケ前提?!」」

大変たのしかったのでレポートしていきたいと思います。

ハンズラボが解釈したゲームルール

読み違えてたらすみません・・・。

ゲーム概要

↓公式より転載↓

「プロジェクト テーマパーク」は、3名〜5名、30分程度でプレイする協力型ボードゲームです。サイコロや「ヤル気カード」を用いて、ジェットコースターや観覧車などのアトラクションを1ターンずつ建築していき、期日までに全てのアトラクションを完成させれば完全クリアとなります。「役割カード」や「イベントカード」などによってゲームの進行が左右されるなか、チームワークを高め合いながらテーマパークのオープンを目指します。

引用元:テーマパークを建設したら働きやすくなる!?🎲プロジェクト管理を学べるボードゲーム、いよいよ完成!


ゲームのルール

ゲームは主に2種類のフェーズの繰り返しで進んでいきます。

  • みんなで今月作れそうな建築物を見積もるフェーズ
  • プレイヤー(役割)ごとにサイコロを振って建築成否を決めるフェーズ

弊社の非公式サークル?モデリング部(仮称)のメンバーがスッと立ち上がって書いてくれた建築フェーズの流れ がこちら

「建築」はサイコロを振ることですね。 建築物ごとに必要な出目が決まっています。 プレイヤーは一人で建築するか、「協同建築」か選べます。 一人での建築の場合、ダイスロール成功で何度でも次の建築に挑戦できます。 「協同建築」の場合、他のプレイヤーとターンをシェアすることで、出目の合計が成否の判定値となります。つまり、大きな建築物を作りやすくなります。

建築成否を決めるのはサイコロの出目だけではありません。 プレイヤーたちに配られる「ヤル気カード」の値を加えた結果が、各建築物建造に必要な数の範囲内であれば建築成功となります。

見積もりフェーズでは手札の状況を見せずにそれとなく各自のヤル気具合を示しながら何を建築できそうか話し合います。自分のヤル気カードを他のメンバーに見せてはいけないのでロールプレイ力の見せ所となります。

さらにこの通常ルールに特別な影響を与えるのが「役割カード」というわけです。

今回プレイしたときのイカれたメンバーがこちら。

  • 0〜5の赤いサイコロしか使えない「新人」
  • 2〜7の青いサイコロしか使えない「完璧主義」
  • ヤル気カードの譲渡ができる「プロジェクトマネージャー」
  • 見積もりフェーズで喋ってはいけない「無口」
  • 赤・青サイコロ、そして普通の白サイコロのどれでも好きなものを振っていい「エース」

イカれたと言いましたが割とまともな顔ぶれでした。 役割カードは全9種類からランダムに配られます。 今回はたまたま入ってきませんでしたが「トラブルメーカー」とかいう不穏な名前の役割も存在するのです。こわい。

さて果たしてこの5人でアトラクションを必要数建築できるのか!?
顧客の信用を失わず!さまざまなアクシデントやラッキーを乗りこなしつつ!
期日内に!!

Let’s play!

プロマネ「どうですか皆さんのコンディションは、いけそうですか」
新人「ノリノリっすね」
プロマネ「ノリノリ!?まじすか」
新人「ノリノリっすね」
無口「・・・」

ノリノリの「新人」役、ロールプレイもノリノリ

プロマネ「でも今ちょっと力をセーブしておいてほしいんですよね・・・」

建築物はフリーセルのように重なっており、手前に来ているものしか建築できません。 ヤル気の出しどころは重要ポイント。

プロマネ「まぁちょっと落ち着きなよ(そっとヤル気カードを渡す)」

ヤル気カードにはマイナス値をもつものもあり、どうやらプロマネはそれを新人に渡したようです。

完璧主義「どうですか?」
新人「ちょっと落ち着きました笑」
無口「・・・」

ちょっと落ち着いた新人たちとじわじわ建築を進めていきます。

見積もり通りに建築できなかったときは顧客の信用1ポイントを犠牲にダイスロール権が復活するらしい・・・それってどういう仕組み???

完璧主義「土下座・・・?」
プロマネ「顧客に対する虚偽報告で帳尻をあわせる・・・?」
※だめです

信頼がある限り土下座をし続けて振り直しができるのか?などと闇の議論にはひとまずルール上は制約がなさそうなので「できる」と仮定して先へ進みます。

なかなが出目が合わず進捗具合はちょっとまずそう・・・。

と、ここで追い打ちをかけるように今月のイベント「インフルエンザ」!

一同「「「や っ ぱ き た」」」
完璧主義「ありそうだと思ったんだよな」

プロマネと無口がインフルエンザで出社できないことに・・・!

完璧主義「これヤル気の受け渡しどうなるんですかね」
プロマネ「いつでも譲渡できるみたいだから出社しなくてもできるんじゃないですか」

プロマネ「出社しなくてもヤル気の受け渡しはSlackで可能!!」
※インフルエンザのひとはSlackも見ないでしっかり寝ましょう

また通常ならターンの頭での有休取得宣言など、何らかの理由で建築せずにターンを終えた場合、ヤル気カードが補充されるんですが、出社しなかった場合もあてはまるのか?という疑問はひとまずあてはまるだろうということで進めます。

プロジェクトに復帰したプロマネ、再び見積もりフェーズ。 ちなみにプロマネ役割のひとが見積もりを仕切る必要はありませんが、みんなロールプレイがしっかりしていたためかなんとなくそういう流れになっています。

プロマネ「うわーどうしよう、けっこうきついな」

プロマネ「でもできれば次観覧車いきたいからポップコーンやっときたいんですよね」
無口「・・・」
プロマネ「無口にポップコーンいけるかききてぇー…」
無口「・・・」
無口「見積もりでしゃべれないのめっちゃつらいです笑」

ロールプレイで沈黙を守ってくれていますがご本人はとてもしゃべりやすい方です!
見積もりでは話に入れてない無口、プレイの順番が後ろにまわされがちのためか、たびたびプレイせずにターンが終わったりしてさみしい。

ヤル気カードがどんどん補充され、物理的にヤル気いっぱいに。

無口「建築成功するとヤル気カード2枚出せる建築物があるんですね」
プロマネ「あ、ほんとだ」
無口「こういうの協同建築した場合は後手でサイコロを振ったほうが2枚出せるようになるみたいです」
プロマネ「なるほど」

無口、エース、完璧主義ががんばるもなかなか進捗はぎりぎり・・・!

プロマネ「信用ポイント4を犠牲にリスケすれば・・・」
一同「「「リスケ前提?!」」」
プロマネ「いやだってしんどいんですもんー・・・」
※かわいく言ってもリスケ前提はだめ絶対

プロマネがダークサイドに落ちそうになりましたが 新人のヤル気が炸裂したこともあり一気に勝利! 完全勝利はできませんでしたがなんとか無事に顧客の信頼を失いきらずに終われました。

疑問点まとめ

  • 信頼がある限り連続で振り直しができるのか
  • 出社しなくても能力は使えるのか(主にプロマネの)
  • 出社してない=建築してないとしてヤル気が補充されるか

上記疑問はひとまず「YES」で仮定して進みました。

考察

参加者感想から抜粋したものがこちら

  • いくら頑張って見積もりしても、外部要因で色々くつがえるという、理不尽さを学べた
  • リスケに逃げずに納期を守る事の尊さを学べた
  • 序盤は信頼が2しかないので失敗が許されず、より堅実に組んで信頼を得ていく必要があるが、堅実に行けばいくほどその分プロジェクトの進捗は遅くなる
  • 見積もりで意思表示がなく成果が見積もれないメンバーはどうしてもリスク扱いになる
  • 工数負荷的にはエースと完璧主義にだいぶのしかかってた気がする。建てた建物を手元に置くのにはそれを可視化させる意味もあったのかも
  • めっちゃくちゃ問題児キャラは今回いなかったけども迷惑な人もいるにはいるからそこのケアが必要(多分信頼2ポイント消費でのメンバー交代かな)
  • プレイする上では、迷惑役を引いてしまったリアルメンバーのケアも含めてチームマネジメントだと思う
  • ソリティア的な感じで決められた順番にしか着手出来ない&工程のツリーも複数本あるので、どのクリティカルパスをいつまでに処理すれば納期までに間に合うかってのを自然に考える仕組みになってた

プレイしてみて振り返るとランダム要素がけっこう多いなという印象を受けました。

  • 建築物の種類(コスト)・並び順
  • 役割カードの種類
  • イベントカードの内容・順番
  • ダイスロールでの建築成否判定

多少制御できるのはヤル気くらいでしょうか。

役割カードの組み合わせでゲームがけっこう変わる気がしたのでプレイヤーたちのレベルごとに役割カードの組み合わせを提案してもいいかなと思いました。ドミニオンのアクションカードの組み合わせ例みたいなイメージ。そして現実でいえば採用によるメンバーコントロールですね。

例)初心者グループ4人向け組み合わせ案
⇨プロマネ、エース、新人、愛されキャラ

まとめ

手に汗握る展開があったり、思いあたるところのある細かい設定にニヤリとしたり、とてもおもしろかったです!

30分程度でプレイできるはずが、ゆっくりロールプレイしたりルール解釈したりしていたらあっというまに90分くらいかかっていました・・・笑

現実のプロジェクト管理にも当てはまるような反省点がでてくるところが魅力のこのゲーム。

プレイの際はぜひ感想戦の時間も考慮してスケジューリングしましょう!

参考

Pocket

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

Pocket

こんにちは、ハンズラボの清水です。東急ハンズのECサイトを担当しています。今回は前回の続き、GitHubのリポジトリにpushしたらECRへpushを行うGitHubActionsを紹介します。

前回の記事はこちら
バッチ処理をECSに移行した話(GitHubActionsもあるよ)その1

前回の記事の追記(Fargateになりました)

前回の記事のクラスターを作成にEC2を利用しましたが、その後、NATGatewayにElasticIPをつけることでFargateで出て行くIPアドレスを固定することができたのでFargateになりました。

IPアドレスを固定する理由は外部ECモール(yahoo, 楽天など)のAPIを利用する際、IPアドレスの制限があるのでIPを固定しています。

GitHubActionsを作成する

ここから本題!GitHubのリポジトリにpushしたらECRへpushを行うGitHubActionsを作成していきます。
参考にしたもの(https://github.com/actions/example-aws)

主な流れはこんな感じ

  1. GitHubのリポジトリにコードをpushする
  2. docker buildを行う
  3. dockerにタグをつける
  4. AWSのアカウントにログイン
  5. ECRにpushする

GitHubのリポジトリから作成します。
作成を行うとプロジェクト内に.github/main.workflowというファイルが作成されます。GitHubActionsのGUIで作成も出来ますし、main.workflowを編集して作成もできます。

個人的にはGUIで大まかな流れを作成して、main.workflowを編集するやり方が個人的には作成しやすいです。

main.workflowの見方

がっつりmain.workflowを書くことはありませんが、GUIである程度作成してしまえばいいので編集するのはenvargsくらいです。
usesは使用するdocker imageです。(独自の環境での実行もできます)

作成したもの

各説明(処理の流れ)

1. ブランチをフィルタリングする

pushされたブランチがmasterの時のみ下に処理を流します。
GitHubActionsでは条件分岐ができないのでFillterを使用しています。

2. イメージのbuild, ECRへのログイン, slack通知

ここではイメージの build、ECRへのログイン、slackへの通知を並列で実行します。

やっていることはdocker build -t test-python . –build-arg STAGE=$STAGEのコマンドを実行しています。

ECRへのログインも先ほどのdocker build同様にawsのコマンドを実行しています。secretsAWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYをセットすることでECRにログインできます。

secretsの登録は割と簡単です。

slack通知はsecretsにwebhookのURLをセットしてargsにチャンネルに通知するメッセージを設定します。

3. dockerイメージにタグをつける

行なっていることは上記のコマンドと同じですコマンドではバージョンをlatestとしていますが、GitHubActionsではバージョンにブランチ名が適応されます。

4. ECRへpushする

dockerイメージのタグ付け、ECRへのログインが終わり次第ECRへpushを行います。

行なっているコマンドは同じですがバージョンのlatestは今回masterになっています。ECSのタスク定義でイメージのURLをlatestにしている場合はmasterに変更しましょう。

5. 完了通知をslackに飛ばす

2. の工程で説明を行なっているので省略します。

masterへpushを行うと、リポジトリのActionsタブから実行ログを見ることができます。

GitHubActionsを使って見ての感想

良い点

  • 作成が簡単
  • 処理の流れが見やすい
  • Dockerとの相性が良い

悪い点

  • ブランチごとにActionsを定義できない
  • 条件分岐が使用できない(失敗したら~~するとか)
  • AWSの複数アカウントに対応できない(Keyを1セットしか登録できない)

現在GitHubActionsはPublicBetaなので今後の機能追加に期待しています。

Pocket

CRMチームの技術展望

Pocket

CRMチームのエンジニアリーダー(仮称)の倉嶋です。
(仮称)としているのは、今年度からできた役職で名称がまだ固まってないからです。
チームの組織課題について責任を負っています。

さて。自チームの技術展望について、過去・現在を元に書きます。
免責事項として、社全体の展望ではありません。自チームに閉じたものです。

過去 (2015年度以前)

  • 外部ベンダ製のパッケージから内製化への移行期。
  • オンプレミスなサーバからAmazon EC2へ移行。
  • Web・Web API・バッチの全てをユニケージ開発手法(以下、ユニケージ)で開発。
  • 開発・運用とも元販売員エンジニアが実施。

現在 (2015年度〜2018年度)

  • ほぼ内製移行が完了。AWS移行も完了。EC2以外のサービス利用が増加。
  • ユニケージが不向きと判断したシステムについては言語をPHP/Node.jsへ、データストアをDynamoDB/RDSへ移行。
  • 東急ハンズ出向者が減り、中途採用の専業エンジニアによる開発・運用。
  • ハンズラボ社としての新卒採用を開始。

過去と現在の差分

  • 内製化により、ブラックボックスとなっている箇所がごく少ない状態になった。
  • AWS化により機器故障等のハードウェア運用作業がほぼゼロになった。
  • AWS化・多言語化・NoSQL/RDB化により、必要な技術知識の幅が大きく広がる。
  • 「業務知識>技術知識」な開発者から「業務知識<技術知識」な開発者へ。

近い未来

  • 開発者が業務知識を持つ状態から、コードが業務知識を表す状態へ遷移する。
  • コードレビュー・モブプログラミングによる暗黙知の継続的な転移。
  • コンテナ技術の利用による開発言語・ツールの選択肢の増加とdeploy単位の細分化。
  • 新規参画メンバーの早期戦力化のためのオンボーディングプロセスの改善。

まとめ

より、エンジニアにとって魅力あるチームへ変えていくことが自身のミッション、と捉えています。
自チームを「参画すると成長できる」「他社・他チームから入りやすい」「休みやすい・在宅勤務しやすい」「自分が選んだ技術を使える」ものへ変えていきたいです。
先日の清水の記事「バッチ処理をECSに移行した話(GitHubActionsもあるよ)その1」はその実践の一つです。

まだ残っている2015年度以前に開発したアプリケーションもあり、順次マイグレーションを進めています。開発プロセスの改善を継続しながら、近い未来をより早く引き寄せるために、マイグレーションの速度も加速させていきたいです。

まだ、「遠い未来」については描けてはいませんが、チームのメンバーと一緒に考えていきます。
新規メンバーの募集と受入のため、「チームのJobDescriptionの作成」「OnBoardingプロセスの文書の作成」を並行して作成しています。
こちらも、いずれ公開したいです。
生煮えのプライベートリポジトリ版にご興味のある方は、ぜひ中途採用にご応募ください。その時点の最新版をお渡し致します。

※アイキャッチはフリー写真素材ぱくたそhttps://www.pakutaso.comさんの画像です。

Pocket

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

Pocket

はじめに

こんにちは、ハンズラボの清水です。東急ハンズの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スクリプトで行いました。

のちの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を紹介できればと思います。

Pocket