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

HANDS LAB

HANDS LAB ENGINEERS BLOG

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

カテゴリー: AWS

バッチ処理を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

バッチ処理を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

re:Invent 2018 参加レポート NPO HACKATHON FOR SOCIAL GOOD その1

Pocket

ラスベガスから日本に帰ってきました。人見です。

NPO HACKATHON FOR SOCIAL GOOD
なるものに参加して来たのでレポートします。

NPOハッカソンはre:Invent 2018のハッカソンイベントの中の1つで
複数のNPOから提示された課題の中からチームで一つ選んで開発するハッカソンです。
NPOは非営利団体のことです。

スケジュールでは9AM–MIDNIGHTと記載されており、
実際に朝8時開場で深夜1時になってもまだ終わらないという感じだったので
おそらくre:Inventのイベントの中でも最長のものだと思います。

朝のラスベガス

夜中のラスベガス

チームは5人までで、自由に組むことができます。

実は前日にハッカソンのチームを組むイベントがあったらしいのですが、
私は当日にチームを組みました。

こんな感じの紙を受付でもらって、

自分がどの役割なのかを自己紹介しながらチームメンバーを探します。
私はバックエンドエンジニアにしました。

メンバーが見つかるか不安だったのですが、
AWSの方もチームを探すのに困ったら手伝うよと言ってくれましたし、
当日オロオロしていたら、声をかけてもらえてチームに入ることができました。
すごいフランクな感じなので、英語が苦手でも大丈夫だと思います。

チームで席を決めてからは、自己紹介タイムで
自分が作ったことあるものや、使ったことのあるAWSのサービス
AWS利用歴などを話しました。
まだハッカソン開始前でお題は発表されていなかったのですが、
NPOならコストかけない方がいいからサーバーレスがいいよねとか、
DynamoDBがいいよねとか、課題を想像しながら戦略を話し合いました。

ハッカソン開始になってオープニングムービーが流れ、
各NPOから解決したい問題が発表されます。
この課題発表の英語のリスニングが超絶難しくて、ざっくりとしか概要をつかめず焦りましたが、
その後のチームメンバーとのディスカッションの時に聞いたり、
NPOの方に質問できる時間があったのでなんとか理解することができました。

私のチームはCompassionという団体の課題を選びました。
課題は「子供とスポンサーがスムーズにコミュニケーションすることができるツール」の開発です。

求められてる機能としては
・ 音声や動画のライブコミュニケーション
・ レスポンスが早いこと
・ 翻訳機能があること
・ 汚い言葉を検知して、除外すること
・ 発展途上国での通信環境も考慮すること

などなど、要件がたくさんありましたが、
ざっくりまとめると

「世界中の色々な言葉を話す子供たちと健全に会話ができるツール」

の開発です。

そんなこんなで開発がスタートしました。

その2へ続きます。

Pocket

re:Invent 2018 新機能!LambdaのCustom Runtimesを試してみた

Pocket

Hello, サービス開発チームの北野です。

re:Inventでラスベガスに来ています。とうとう最終日です。

今日はKeynoteでServerless関連が大きくアップデートしました。
LambdaのRubyサポート, Lambda Layers, API GatewayのWebSocket対応, ALB for Lambdaなどなど、
どれも使ってみるのが楽しみになるアップデートでした。

LambdaのCustom Runtimesの発表を見て、
「これはもしやハンズラボの謎技術ユニケージ on Lambdaができるのでは…?」
という悪魔のささやきが聞こえましたが、無視しました。

ちなみに私は業務でユニケージを触ったことはございません。

それはともかく、LambdaのCustom Runtimesが気になったので、公式チュートリアルに沿って試してみました。

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/runtimes-walkthrough.html

Lambdaの作成

まずはLambdaをマネジメントコンソールから作成します。
ランタイムに「独自のランタイムを使用する」という選択肢が増えているので、これを選びます。
名前とロールは適当に設定して関数を作成します。

独自のランタイムを使用する場合、プログラムはマネジメントコンソールで編集できないようなので、プログラムはローカルマシンで作成します。

bootstrapの作成

独自のランタイムを使用する場合、bootstrapシェルスクリプトを起点にLambdaが動くようです。
サンプルスクリプトを見ると、LambdaのRuntimeAPIに対してGETでHTTPアクセスしてLambdaを起動したEventを取得して、
LambdaのRuntimeAPIに対してPOSTでHTTPアクセスしてResponseを返す仕組みになっています。

今回はサンプルスクリプトをちょっとだけ変更して使います。

bootstrap

function.shの作成

bootstrapから呼び出して実行するシェルスクリプトfunction.shを作成します。
シェルスクリプトのfunctionには戻り値が無いので、標準出力を使って擬似的に戻り値があるような振る舞いをさせます。
シェルスクリプトに馴染みがないとよくわからないと思うので、bootstrapの振る舞いと合わせて後ほど解説します。

function.shもサンプルスクリプトを少し変更して使います。

function.sh

bootstrapとfunction.shの振る舞い

シェルスクリプトの動作について少しだけ解説します。
まず環境変数$_HANDLERには、Lambdaで設定しているハンドラが設定されます。
今回はfunction.handlerという値が設定される想定です。

そしてbootstrapの6行目
source $LAMBDA_TASK_ROOT/”$(echo $_HANDLER | cut -d. -f1).sh”

echo $_HANDLER | cut -d. -f1
で、function.handlerを”.”で文字列分割した1つ目を取得しています。
これを展開すると、
source $LAMBDA_TASK_ROOT/function.sh
ということになります。

17行目も似たような形で、
RESPONSE=$($(echo “$_HANDLER” | cut -d. -f2) “$EVENT_DATA”)

echo “$_HANDLER” | cut -d. -f2
で、function.handlerを”.”で文字列分割した2つ目を取得しています。
これを展開すると、
RESPONSE=$(handler “$EVENT_DATA”)
ということになります。
このhandlerはfunction.shで定義したfunctionで、handler実行時の標準出力がRESPONSE変数に格納されます。
$()を使ってfunctionの標準出力を変数に格納することで、擬似的に戻り値があるような振る舞いをさせています。

Lambdaのコードアップロード

作成した二つのファイルはzip圧縮して一つのファイルにします。

  • bootstrap
  • function.sh

マネジメントコンソールを開いて、コードエントリタイプで「.zipファイルをアップロード」を選択します。
アップロードボタンを押して作成したzipファイルを選択し、ハンドラを修正して保存ボタンを押します。

これで動かす準備が出来ました。テスト実行してみましょう。

Lambdaのテスト実行

右上の方にあるテストボタンを押します。

テスト用のEventを作る必要があるので、名前だけつけて適当に作成します。

作成したEventが設定されていることを確認して、再度テストボタンを押します。

「実行結果:成功」でちゃんと動いています。やったね!

終わりに

LambdaのCustom Runtimesを動かすことができました。
便利だなと思う半面、せっかくのシンプルなLambdaにだいぶ管理しなければならないことが増えてしまう印象があり、Custom Runtimesの使用は慎重に検討したいところです。
選択肢が増えたことはとても良いことだと思うので、本当にCustom Runtimesを使う必要があるのか?他にもっと良い方法が無いか?と自問自答して、適切な技術選択をしていけたらと思います。

Pocket

re:Invent 2018 Cloud9でAWS CLI v2 を動かそう

Pocket

Hello, サービス開発チームの北野です。

現在、re:Inventでラスベガスに来ています。勝手にブログ強化週間中です。

ハンズラボCLI大好き代表としては聞き逃がせないなと思って、
DEV322-R – [REPEAT] What’s New with the AWS CLIのセッションを聞いてきました。

以前からv2の話は少しずつでていましたが、ついにv2のdeveloper releaseが出たようです。
https://github.com/aws/aws-cli/releases/tag/2.0.0dev0

現在のCLIと互換性が保証されないものの、補完機能が強力になって、wizard機能がつき、yaml出力に対応するので、とっつきやすくなるんじゃないかと期待しています。

Cloud9とAWS CLI

実はCloud9とAWS CLIの相性がすごく良いと思っていて、私はIDEとしてよりブラウザで動かせるシェル環境としてCloud9を愛用しております。

Cloud9でAWS CLIを動かすときは、AWS_ACCESS_KEY_IDとAWS_SECRET_ACCESS_KEYを意識する必要がなくなります。
Cloud9がうまいことやってくれて、ログインしたユーザーが操作できる範囲の権限を持った一時的なCredentialsを生成してくれるのです。

どうなっているのかというと、Cloud9のここの設定をONにしておくと(デフォルトON)、

Cloud9が~/.aws/credentialsに一時的なCredentialsを生成して設定してくれます。便利。

Cloud9にAWS CLI v2をインストール

まずは最初にCloud9にインストールされているawscliをアンインストールしちゃいます。

AWS Developer Blogを参考に、GitHubリポジトリをソースにしてpip installします。

https://aws.amazon.com/jp/blogs/developer/aws-cli-v2-development/

最後に、ダウンロードされたソースの中身をec2-userがさわれるようにchownします。

awsコマンドのバージョンを確認して、2.0.0dev0になっていたら無事インストールできました。

AWS CLI v2を使ってみる

DynamoDBのテーブル名まで補完してくれるらしいので、DynamoDBを作って確かめてみます。
適当な名前のDynamoDBのテーブルを作ります。

補完を適用するためのコマンドを実行して、テーブル名が補完できそうな
aws dynamodb describe-table --table-nameまで入力します。

ここで<TAB>キーを押すと…先程作ったDynamoDBのテーブル名が補完されました。すごい!

終わりに

互換性が保証されていないという点には注意が必要そうですが、補完が強力になってCLIが使いやすくなりそうです。
v2正式リリースまで情報を追っていこうと思います。

Pocket