スパイスな人生

素敵な人生をおくるためのスパイスを届けていきたい、そんな想いで仕事をするspice lifeメンバーブログ

ridgepoleのapplyをECS RunTaskで実行するようにしました

staging deploy成功の様子

おはようございます。冪等性が大好きなうなすけです。

さて、つい先日にridgepole applyをECS RunTaskを用いて行うようにしたので、今までどのようにapplyしていたのか、RunTaskにする過程でハマッたことなどを書いていこうと思います。

ridgepoleとは

github.com

ridgepoleは、Railsのmigrationと同様のDSLでデータベースのスキーマを管理できるコマンドラインツールです。どのようなものであるかは、cookpadさんの以下のブログに詳細が書かれています。

techlife.cookpad.com

TMIXとridgepole

TMIXは、歴史的経緯により、複数のRails applicationが共通のRDBを参照しにいくという構成になっています。database schemaをridgepoleで管理するようになるまでは、複数のリポジトリ間で db/schema.rb のコピペを都度行なっていました。

ridgepoleのapplyについては、capistranoを用いて、アプリケーションの動作するインスタンスを間借りしてRDSに対してschema applyをするという形にしていました。理由としては、都度インスタンスを構築するのは面倒で複雑だし、schema apply用のインスタンスを起動したままにしておくのは無駄なコストが発生するためです。実際、この方法でのschema applyは後述する問題以外の不具合は発生することなく今まで動作していました。

簡単に構成を描いてみました。 以前の構成

インスタンス間借り方式の不具合

ある日のこと、schemaのapplyができなくなっていることに気づきました。Schemafileにtypoがまざっているというわけでもなく、開発用データベースへのapplyは正常にできるというのに、です。

原因は、間借りしているアプリケーションのサーバー側にありました。というのも、数日前にそのRailsアプリケーションの動作するRubyのバージョンを上げてしまっていたのです。その時にインスタンスを新規に作り直していたので、新しいバージョンのRubyのみが入っている状態になっていました。capistranoではdeployする際に指定されたバージョンのRubyを使用するように設定されているので、要求しているバージョンのRubyが存在せずdeployが失敗するようになってしまいました。

この問題については、ridgepoleで使用するRubyのバージョンをインスタンスにインストールされているものと揃えればいいだけ、と言ってしまえばそれまでです。

Docker化したときにどうするのか

また、今後TMIXのインフラをDocker化していくとなった場合には、いわゆる「Rubyがインストールされているインスタンス」というものが存在しなくなるため、今までのcapistranoを用いたschema applyは不可能になります。

ECSによるschema apply

前述の不具合と今後の懸念から、ECS RunTaskによるschema applyを行なうことにしました。では、ECS RunTaskによるschema applyのためには、どのような作業が必要になるでしょうか?

Docker imageの作成

まずは実行するためのDocker imageが無くては始まりません。一部加工しましたが、実際のDockerfileを以下に記載します。

localeをja_JP.UTF-8にしていますが、これは何故かというと、いくつかのcolumnのdefault値に日本語の文字列が含まれているため、schema applyのときにridgepoleがinvalid multibyte charで落ちてしまうためです。

CMDridgepole --applyではなく独自のRake taskになっているのは、schemaのapply結果を社内チャットツールに投稿するためです。

FROM ruby:2.4.1-slim

WORKDIR /var/schema

RUN apt update \
    && apt install -y \
      gcc \
      libmysqlclient-dev \
      locales \
      make \
      wget \
    && rm -rf /var/lib/apt/lists/*

# set locale to ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
RUN echo ja_JP.UTF-8 UTF-8 > /etc/locale.gen \
    && locale-gen \
    && update-locale LANG=ja_JP.UTF-8 LC_ALL=ja_JP.UTF-8


COPY Gemfile /var/schema
COPY Gemfile.lock /var/schema
RUN bundle install

COPY . /var/schema

CMD bundle exec rake apply:$DATABASE_ENV

task definitionの作成

Docker imageができていれば、task definitionは悩むことなく簡単に作成できるでしょう。今回はproduction用とstaging用の2つのtask definitionを作成しました。

テストの実行

ただschemaの定義がされているリポジトリですが、もちろんテストは存在します。どのようなテストなのかというと、そのschemaが実際にapplyできるかどうか、ということを確認するものです。tableやcolumnの名前のtypoは防ぐことができませんが、DSLの文法が間違っていないかなどの確認をすることができます。

運用をDockerに寄せるのであれば、テストもDockerで行なうのが筋というものでしょうか。なので、CIで稼動するMySQLに対してridgepole --applyを実行する形式から、docker-composeでlinkしているMySQLのコンテナに対してridgepole --applyを実行する形式に変更しました。

ただ、手元のマシンで実行したり、CI上のMySQLに対して実行したりするのとは違い、docker-composeでの実行は、mysqldが上がってくる前にridgepole --applyを実行しようとして落ちてしまうこともあります。

そこでCIで実行するテストは、事前にdocker-compose up -d mysqlMySQLのコンテナを立ち上げた後、mysqladmin pingが成功するまで数秒間隔のループを回すことにしてこの問題を解決しています。

Deployする

さて、本命のdeployについてです。deployは特定のbranchへのmergeがされた時に実行するようにしていますが、具体的に何をしているかというと……

  1. ridgepole applyを実行するDocker imageのbuild
  2. buildしたimageにcommit hashのtagを付けてECRにpush
  3. 今buildしたDocker imageのtagが指定されたtask definitionの作成
  4. 作成したtask definitionを用いてRunTaskの実行

となっています。Docker imageのbuildをmaster branchへのmergeのタイミングで実行していないのは、deploy用branchからはテストがpassしている最新のcommit hashがわからないためです。deploy branchは常にテストがpassしているmasterからmergeされるので、mergeされた時点でのcommit hashを用いることにしています。

(厳密に言えば、git rev-parse masterを実行すればmasterのcommit hashは判明しますが、deployのタイミングでCI側にgitがインストールされていないため、環境変数に設定されている現在のcommit hashを使用しています)

ECS RunTask化成功

喜びの様子

deployが成功すると、前述したRake taskによってこのようなメッセージが投稿されます。これによって、ECS RunTaskでのdeployが成功したことが確認できました!

今後の課題

さて、schema applyのDocker化はつつがなく終えることができましたが、Docker化という意味ではまだ課題が残っています。その一番大きなものが、「schemaがapplyされているMySQLのDocker imageを作成する」というものです。なぜこれが必要なのかというと、TMIXを構成する各Rails applicationは、ridgepoleにschemaの運用を移譲した結果、db/schema.rbの中身が空なのです!

そのため、各Rails applicationでテストを実行したいときには、まずschema repositoryをcloneしてridgepole --applyを実行するようにしており、ここで大幅な時間がかかっています。そのため、schemaが適用されているMySQLのimageをpullしてこれれば時間短縮になるのですが、まだ手が出せていません。

まとめ

課題は山積みですが、この調子でどんどんコンテナ化をやっていきたいと思っています!

RailsアプリをECSで運用するまでにやったこと、これからしていくこと

構築したインフラの簡易的な図

おはようございます。一番よく使うemojiは 👀 (:eyes:) のうなすけです。

さて弊社では、最近社内Railsアプリをひとつ構築しました。それをECSで運用することにしたので、そこに至るまでの経緯、つまづき、これからの課題などなどを記事にしていこうと思います。上の図は現時点での簡単なAWS上での構成図です。

以下、見出しは時系列順でやったことを記録していきます。

社内Railsアプリ、一体どんなもの?

ここで新規に構築することになった社内Railsアプリですが、特に凝ったことはしていない単純なRailsアプリです。初めからECSで運用することにしていたので、開発環境も全てDockerで構築しています。Railsのバージョンは5.1.0、Docker imageのFROMにはruby:2.4.1-silmを採用しています。

Docker imageのtagについて

development環境のdocker imageですが、手元でbuild/pushさせるのは属人化しやすく、また継続的に実行したいので、CircleCIでbuildしてECRにpushすることにしました。そのときのimageのtagですが、push毎にgit commit hashをtagとして付与し、master branchでのbuildではそれに追加でlatestを付けることにしました。

これにより、「とりあえずlatestなら動く」という状況にしています。

共通部分を切り出し、production用のDockerfileをつくる

さて稼動させようかという状況になりましたが、この時点ではdevelopmentのDockerfileしかありませんでした。そこで、DRYになるように共通部分(OSのパッケージインストールなど)を切り出してbase imageとし、developmentとproductionはそれらをFROMにするDokerfileに分割することにしました。

app
config
db
docker/
  └ app-base/
      └ Dockerfile
  └ app-development/
      └ Dockerfile
  └ app-production/
      └ Dockerfile

ディレクトリ構造はこのような感じです。base imageはcontainer/baseにmergeされたときにbuild/pushを行なうようにしました。

assets配信どうする問題

production運用といえば、assetsの配信をどうするか、ということも当然考慮する必要があります。Dockerで運用をするとなれば、imageの少サイズ化も見込めるので、AssetSync/asset_sync を採用する場合が多いかと思います。

ですが僕達は、amakanの構成に倣って、assetsをcontainer内に含めることにしました。その思想については、id:r7kamura 氏の以下の記事に詳しく記載されているので、ここで詳細に述べることはしません。

r7kamura.hatenablog.com

リバースプロキシどうする問題

Railsアプリに限らず、Webアプリを運用していくとなるとアプリの前段に行ないたい処理は出てくるものです。主な処理としては以下が挙げられます。

  • スロークライアント対策
  • SSL/TLS の終端処理
  • 静的ファイルの配信

スロークライアント対策、SSL/TLSの終端処理についてはALBを利用することで達成されます。また、静的ファイルの配信については先述のamakanと同様の構成(Railsによる配信 + CDN)にすることで達成されます。一度リバースプロキシは不要になるかと思われましたが、その他細かい要件として以下が挙げられました。

  • HTTP → HTTPSへのリダイレクト
  • Basic認証
  • Cache-Control Headerの書き替え
  • assets配信用ドメインでの/assets/*以外のアクセスに対して400系のレスポンスを返す

これらをRack middlewareで行うことも検討したのですが、アプリ層で行うべきではないと判断し、前段にNginxを設置することにしました。これが後に問題を引き起こすのですが……

app
config
db
docker/
  └ app-base/
      └ Dockerfile
  └ app-development/
      └ Dockerfile
  └ app-nginx/
      ├ Dockerfile
      └ nginx.conf
  └ app-production/
      └ Dockerfile

このNginxもDocker containerとして動作させ、その設定はアプリのリポジトリに含めることにしました。container/nginxにmergeするとbuild/pushが行なわれます。

Deployどうする問題

さあ、productionのimageもできましたし、Nginxの設定も終わりました。となると残すはDeployです。

この時点で、社内にはもうECS上で動くアプリがありましたが、それはNode.jsで動作するアプリであり、Deployもaws-sdk-jsを使用したJavaScriptによるスクリプトを実行するというもので、今回のRailsアプリでは同様の仕組みを利用することができません。

それに、今後TMIXやSTEERSをECSで運用することを視野に入れると、汎用的に使える新しい仕組みを構築したほうがよさそうです。

ECS Deploy tool選定

僕達がECS deploy toolに求める要件は、主に以下の4つでした。

  • Service / Task Definition を一元管理する
    • awslogs の設定等をインフラチームで管理したい
  • Task Placement Constraints は Task Definition で管理する
    • Task Placement Constraintsの変更によるServiceの作り直しを避けたい
  • Service の Task Definition や Task Definition の Image はコードで管理せず、外部パラメータを用いて更新できるようにする
  • 環境を問わずデプロイできるようにする
    • 例えば gem にしてしまうと Ruby 以外のアプリケーションのデプロイでも Ruby 環境を用意する必要がある

そして、ECSのdeploy toolというと、これらが挙げられるでしょう。

これらを触ってみて、自分達の要件に合うかどうか調査して……自前で実装することに決めました。

esaのコメント

それが、こちらになります。

github.com

このgemを使い、あるひとつのリポジトリで全てのアプリのTask DefinitionとServiceの定義を含むDocker imageを作成し、Deployはdocker execすることによって実現させる、という風にしました。

まだまだ扱いはWIPなgemですが、そろそろversion 1.0をリリースしたい気持ちはあります。

db:migrateができない問題

database schemaを変更した際には、deploy前にdb:migrateを実行してやらなければなりません。

しかし、ECSのRunTask経由で実行すると、なぜかbundle exec rails db:migrateは実行できず(SIGTERMで死ぬ)、試行錯誤の結果/bin/sh -c bundle exec rails db:migrateだと実行できることがわかりました。

これについてAWSのサポートに問い合わせたところ、同Taskで動作しているNginx contaierがすぐに落ち(何もさせないようtrueを実行するようにしていた)、Task Definitionにessential: trueを指定しているためにそれに引き摺られてRailsのcontainerも落ちる、という動作になっていることが判明しました。

これについては、RunTask用にNginxを含まないTask Definitionを用意し、それを使用することで回避しました。Nginxの存在によって構成が複雑になってしまっているため、本来アプリ層でやるべできはないことをアプリ層でやることとのトレードオフですが、NginxをやめてRack middlewareを使用することでTask Definitionの二重管理をやめることを検討しています。

ログが見たいけどCloudWatch Logsは面倒

Railsのログは、STDOUTに吐いて、それをawslogs log driverでCloudWatch Logsに保管しています。これでは手元でgrepawsを使ったログの解析ができません。

この問題は、現在実行中のコンテナのログを取得する次のようなscriptを作成することで解決しました。(一部省略しています)

#!/usr/bin/env ruby

require 'aws-sdk'

ecs    = Aws::ECS::Client.new
cwlogs = Aws::CloudWatchLogs::Client.new

service    = ecs.describe_services(cluster: CLUSTER, services: [SERVICE]).services.first
deployment = service.deployments.find { |d| d.status == 'PRIMARY' }
task_arns  = ecs.list_tasks(cluster: cluster, started_by: deployment.id).task_arns

events = task_arns.flat_map do |arn|
  cwlogs.get_log_events(
    log_group_name: LOG_GROUP_NAME,
    log_stream_name: "#{LOG_STREAM_PREFIX}/#{CONTAINER}/#{arn.sub(/.+\//, '')}"
  ).events
end

events.sort_by(&:timestamp).each do |event|
  puts event.message
end

現状では時間帯の指定等ができず大量のログが流れてきてしまうため、引き続き改善を行っています。

Docker imageの共通化をやめる

Dockerでは、言語環境やOSのパッケージなどの共通部分は、別Dockerfileに切り出してFROMで参照することによってfull build時間の短縮やイメージサイズの削減を図るのは常識であり、僕達もこのアプリのDockerfileはbase、development、productionの3つに分割していました。

具体的にbaseに含めているのは、以下に例として示す通り、developmentでもproductionでも共通のgemのインストールまでです。

FROM ruby:2.4.1-slim

RUN apt update && \
    apt install --assume-yes \
      make \
      curl \
      略

COPY package.json /app
COPY yarn.lock /app
RUN yarn install

COPY Gemfile Gemfile.lock /app
RUN bundle install --without development test

しかし、このような構成にしてしまった結果、gemを追加するのに一度container/base branchへmergeしてからでないとdevelopmentのコンテナでgemを使えなかったり、developmentにのみ含めたいOSパッケージの存在があったりして、少しやりすぎた共通化なのではないか、という認識がチーム内で発生しました。

なので、base imageは廃止し、productionでもdevelopmentでもFROMはruby公式のDocker imageを指定しています。これによる弊害は、今のところチーム内では認識できていません。

Docker imageのbuildが遅い

今までのDocker imageのbuild/pushは全てCircleCI 2.0にて行っていましたが、Docker layer cacheが効いたり効かなかったりして、buildに長時間かかることがしょっちゅうでした。そこで、layer cacheが有効になるように、CI serviceの乗り替えを検討しました。

Dockerを使用できるCI Serviceとして以下を検討しましたが、それぞれ記載する理由により採用を見送りました。

次にオンプレミス環境で動作するCI Serviceを検討しました。それらに代表的なものとしてJenkinsとDrone.ioが挙げられるでしょう。

どちらも試用して検討し、上記理由からDrone.ioを採用しました。

Drone.ioはserverとagentに役割が分かれていて、agentをスケールさせることでbuild時間の短縮が目論めます。もちろん、Drone.ioもECR上に構築しました。

Drone.ioのserverとagent間の通信が切れる

drone-agentのみをスケールさせるために、drone-serverとdrone-agentは別Task Definition、別Serviceにしました。しかし、drone-agentからdrone-serverへのWebSockert通信がALBのIdle timeoutで強制的に切断されてしまい、この問題を解決することがどうしてもできませんでした。

なので、drone-serverとdrone-agent間の通信は、ALB越しではなく、インスタンスに割り当てられたPrivate IPによって行なうことにしました。弊害として、Dynamic Port Mappingを用いたdrone-serverのスケールアウトはできなくなりましたが、drone-serverをスケールアウトさせることに大した意味は無さそうなので、この構成で運用していこうと思います。

現時点のまとめ

  • Rails 5.1 の新規社内アプリをECR上で運用している
  • assetsはcontainerの中に含め、CDNから配信している
  • NginxをRailsの前段に配置しているが、Rack middlewareに置き替えることを検討している
  • developmentとproductionの共通部分をまとめたbase imageを採用していたが、廃止した
  • CI ServiceをCircleCIからオンプレミスのDrone.ioに移行した

Docker化って、難しいですね。ログの解析やdb:migrateなど、今までの運用と大きく変更しなければならない部分だったり、思わぬ落し穴があったりして、インフラ構築の最中はずっとああでもない、こうでもない、どのような方法がいいか、もっといいやり方があるはずだ、と議論を重ねていました。とても面白かったです。

さて、僕のインフラチームとしての仕事はここまでで一旦終わり、今月からTMIXチームに復帰することになりました。今回の記事は、今までのインフラ部での仕事を振り返るために書いたというのが正直なところです。

TMIXでやっていくぞ!!!!!

DIST.16 「esa meetup in Tokyo〜情報共有Night」で発表してきました

こんにちは、CTOの赤松 aka ゆーけーです。

6月23日に開催された、DIST.16 「esa meetup in Tokyo〜情報共有Nightにて「サービス開発を加速させる情報共有」というタイトルで発表させて頂きました。

弊社では色々なesaの使い方をしていて、例えば私のesaの使い方とマーケティングチームやカスタムサポートチームでの使い方が結構違ったりします。

今回、DISTの沖さんから「サービス開発」というテーマを頂いていたので、私が今メインで携わっているSTEERSの開発でのesaの活用事例について話をしました。

DISTのイベントは初参加でしたが、沖さんの進行が上手で最後までスムーズでとてもよかったです。

本編も懇親会もたくさんの参加者がいらっしゃってとても楽しいイベントでした。今回登壇の機会を頂けたことをありがたく思います。

Tシャツを提供させて頂きました

STEERSからスピーカー様と参加者様のプレゼント用に10枚程度ですがTシャツを提供させて頂きました。

こちらSTEERSで購入可能ですので、よければお買い求めください。前回の名古屋でのTシャツも販売中です。

今後ともSTEERSをよろしくお願いいたします。

【全品送料無料】esa meetup in Tokyo ~情報共有Night 記念Tシャツ | オリジナルTシャツ販売 STEERS(ステアーズ)

f:id:ukstudio:20170626162739p:plain

【全品送料無料】esa meetup in Nagoya @ Misoca | オリジナルTシャツ販売 STEERS(ステアーズ)f:id:ukstudio:20170626162800p:plain

発表の補足

発表内容については資料を見ていただくとして、当日発表後や懇親会などで質問頂いたりしたのでその辺について少しまとめてみようと思います。

中間成果物として書いた仕様は全部ストック記事に整理していますか?

していません。というのも、大体のことはコードなりでサービスそのものに実装されているので、出来上がっているモノ自体が仕様になるためです。

どちらかというと資料に書いたとおり、調べようとしてサクッとわからなかったらという感じで必要になったときにまとめることが多いです。他にも誰かから(例えばステークホルダーとか)質問されたときにも記事にしたりしています。

中間成果物に書いた仕様と実装をあわせるの大変じゃないですか?

基本的に中間成果物として書かれた仕様は「とっかかり」ぐらいのものです。開発するためにお互いの認識をある程度揃えるためのスタート地点的ぐらいのつもりで書いています。

なので、実際に実装に入ってしまえばあとはチャットだったりプルリクエストでのやりとりだったりします。ちょっとぐらい認識のズレがあってもそこで実装を修正してしまう感じですね。

もしかしたら「仕様」という言葉でちょっと重たく捉えた方もいるかもしれませんが、ノリ的にはホワイトボードでちょっと情報を共有するのとあまり変わりません。

今のところそれであまり混乱も起きていませんが、中間成果物の仕様と実装の食い違いで混乱があった場合はある程度中間成果物の仕様も更新したりする必要もあるかもしれません。

README使っていますか?

使っています。結構好きな機能ですね。カテゴリのREADMEはトップにあるREADMEより目立たないのがちょっと残念ですが、今のesaだとカテゴリをクリックしたときにそのカテゴリの記事一覧がでるので仕方ない気もします。

READMEには主にストック記事へのリンクをまとめています。どこどこのカテゴリにあるよというよりは、READMEにまとめてあるよの方がわかりやすいと思うので。

STEERSの場合だと、例えばTシャツの印刷位置・印刷サイズの大きさや、返品時の対応のルールといった業務上のことだったり、開発環境の構築といったような開発用ドキュメントへのリンクがはってあったりします。

他にもプロジェクトカテゴリの各施策で重たい施策ではREADMEを置いていたりします。施策の概要やチェックボックスで施策の進捗状況をメモしていたり、施策を進めるにあたって必要なドキュメントへのリンクや、打ち合わせなどで決まったことをまとめたりしています。

AWS CloudWatch Eventsをcronとして使う powered by maekawa

f:id:yu_suke1994:20170308012920p:plain

おはようございます。cronは「クーロン」と読むうなすけです。

実は2月頭からTMIX開発チームを離れ、インフラチームに所属しています。そして、インフラチームとしての初仕事として、AWS CloudWatch Eventsを用いたバッチ処理行基盤の構築を行いました。

バッチ処理基盤の要件

Webサービスがある程度の規模に成長すると、一定の期間で定期的に実行するバッチ処理が必要になるでしょう。もちろんTMIXでもバッチ処理は必要で、それはアプリケーションサーバーのひとつにcronjobの実行を任せることで行っていました。

しかし、TMIXを将来Dockerで動かすことを考えると、いつ破棄されるか不明なコンテナでcronを実行させる訳にはいかず、この方法はいずれ使えなくなります。なにかしら別の方法を考える必要があります。

そして、次のような要件を定義しました。

処理自体は ECS Task で行う (MUST)

処理に関わる環境の構築について考えることを減らせるので、これは必須要件です。

実行ログ (MUST)

言わずもがな、これも必須要件です。

コードベースでの管理 (SHOULD)

Pull Requestを経由して、レビューを行ってからジョブの登録をしたいので、javan/whenever のようなDSLでも、もしくはcrontabそのものでも、とにかくジョブがコードで管理されている状態にしたいです。

マネージドサービスであること (SHOULD)

運用コストを削減したいからDocker化するのであって、ここで新たに管理対象が増えるのは避けたいところです。

ただ、ECSで運用できるのであればマネージドでなくてもよいことにしました。

実行時エラーを検知したい (SHOULD)

エラーが発生したことは何らかの方法で知る必要があります。

ワークフロー管理 (MAY)

cronサーバの代替なので、ワークフロー管理は必須ではありませんが、あれば言うことはないでしょう。

その他にもいくつかの要件がありましたが、大きなものは以上です。これらの要件を満たすかどうか、いくつかのジョブスケジューラーを比較・検討してみました。

検討したもの

kuroko2

cookpad/kuroko2 は、cookpadで開発されたジョブスケジューラ、ワークフローエンジンです。

techlife.cookpad.com

kuroko2はよくできたジョブスケジューラですが、ジョブのコード管理ができず、ECS上で動かすことが困難であった(ように見えた)ので採用はしませんでした。

rundeck

rundeckは、オープンソースで開発されているジョブスケジューラで、有料のマネージドサービスもあります。

rundeck.org

rundeckは公式なDockerfileが見当らず、マネージドサービスは高価すぎるので採用はしませんでした。

AWS Batch

AWS BatchはAWSが用意しているフルマネージドのバッチ処理基盤です。

aws.amazon.com

AWS Batchはスケジュールに従って実行する機能がないこと、また僕が評価のために試用したときにいくら待ってもジョブが実行されずに評価不可能だったので採用しませんでした。

AWS CloudWatch Events

AWS ClowdWatch EventsはAWSが用意している、AWSのリソースの変化をトリガーとして様々な機能を呼び出すことのできるサービスです。

docs.aws.amazon.com

ClowdWatch Eventsは定期的、もしくはcron書式によるイベントを定義することができ、そこからAWS lambdaを経由してECS RunTaskを実行することができます。

しかし、コードによる管理は、それを行うツールが調べた限りでは存在しませんでした。

maekawaというCLI toolの開発

どのようなジョブが登録されているのか、どのようなジョブを登録しようとしているのかをPull Requestベースで管理したいので、 定義ファイルに従って状態を変更する、 codenize-tools/miamcodenize-tools/roadworker のようなべき等性を持つCLI toolが必要でした。

そこで、べき等性を持つ、CloudWatch Eventsを管理するCLI tool、maekawaを作成しました。

github.com

maekawaによって……

  • CloudWatch EventsのRuleとTargetの組み合わせをYamlによって管理
  • Yamlの定義に従ったRuleとTargetの登録もしくは削除

が可能になり、Pull Requestをベースとした、CIによるジョブスケジュールの定義が可能になりました。

maekawaは単なる社内ツールとしてではなく、OSSとして公開することにしました。また。個人的にチャレンジしたかったので、Golangで書いています。Golangで書いたことによって、CI環境へのセットアップが容易にできるようになったのは、予期しない利点でした。

全体的な処理の流れ

まず、cron書式などによって定義された時刻に、CloudWatch Eventsによってlambda functionが実行されます。lambda functionは、それ自体はECS RunTaskを実行するだけの薄い層として存在するだけです。lambdaを通じて実行されたECS Taskによって、目的のバッチ処理が実行される、という流れになっています。

なにに使用しているのか

こうして新しくなったバッチ処理基盤ですが、これで何を実行しているのかというと、現状は

などです。

今後、様々なジョブが登録されていくと思います。

以上、僕のインフラチーム移籍後の初仕事でした。今後ともTMIXならびにSTEERSをよろしくお願いします。

社全体で使うrubocop.ymlを定義して、TMIXとSTEERSに適用しました

f:id:yu_suke1994:20170221192927p:plain

おはようございます。Style/TrailingCommaInArgumentsconsistent_comma派のうなすけです。

さて、ちょっと前からspicelifeでは、TMIXとSTEERSの両方でrubocopを用いたLintのチェックをCIで実行するようになりました。

導入背景

そもそもrubocopによる文法の統一ですが、最近になってようやく導入したわけではありません。 STEERSでは2015年10月にrubocopをCI上で実行するPull Requestがmergeされています。

それ以降、STEERSでは継続してLintチェック、rubocop.yml更新が行われてきました。

さて一方のTMIXは、もともとが古いプロジェクトであること、関わってきた人数の数などもあり、コードの統一性は全くありませんし、そしてそのようなコードが大量に存在している状態です。 だからこそrubocopが力を発揮できる、ということが言えるでしょうが、しかしそれでもdefaultの設定でrubocopを実行すると、無限に警告が発生してしまい途方に暮れてしまうので、なかなか導入できずにいました。

しかし今後追加されるコードも無秩序でいいという理由はなく、導入しないという選択肢はないので、重い腰を上げてようやく導入に踏み切ったというのが、つい先日のことになります。

どのようなルールを使っているのか

会社全体で使用するルールを決め、基本的には各プロジェクトでそれに従うことにしています。そのルールは公開しており、どなたでも閲覧することができる状態になっています。

github.com

また、各プロジェクトにおいて、そぐわないルールを上書くこともしています。

TMIXでの運用

TMIXでは、先述のようにCIでrubocopを実行すると警告の嵐になってしまいます。rubocop_todo.ymlを生成してもいいのですが、放置されてしまうことも考えられます。

なので、CIではrubocopを実行せず、hound ciを導入し、新しく書かれるコードにのみrubocopでのチェックを行なっています。

https://houndci.com/

hound ciにした理由は人数とリポジトリ数で各CIサービスを比較した場合に高価すぎないためです。

雑感

これまで個人の好みによって文法の指摘がされていたのが、統一した規則ができ、かつbotによって指摘されるので、開発環境がよりよいものへと改善されたように思います。

複数人での開発においてこそ、rubocopは真価を発揮すると考えているので、みなさんも、Rubyによる共同開発をしていて、導入していないのならrubocopを導入することをオススメします。

第3回日本ネット経済新聞賞のオムニチャネル賞をTMIXが受賞!

f:id:tmix:20161125132401j:plainf:id:tmix:20161125132409j:plain

ご無沙汰しています、ヨシカワです。

日本ネット経済新聞の2016年11月24日号の紙面にて 第3回 日本ネット経済新聞賞が発表されました。 その中のオムニチャネル賞を弊社TMIXでいただきました!

tmix.jp

ちなみに同賞受賞企業はナノユニバース日本トイザらスというメジャーカンパニー! いやーほんとうにびっくりしてます。

第3者の評価、とりわけ新聞というメディアから賞をいただき評価されたのは素直に嬉しいですし、TMIX関係者の励みになります!

思えば社内にTMIXショールームを併設したのは2015年3月2日でした。

blog.tmix.jp

そして、その後EC発ショールームストアの記事を書いたのが2015年3月12日。

blog.spicelife.jp

オムニチャネルと言えばリアル店舗を持つ企業の話ばかり取り上げられていた時期にネット企業のオムニチャネルとして記事を書いたことが珍しかったためか、ブログを読んだ方からの反響がすごかったのを覚えています(シェアもFBだけでも3000シェア以上とすごかった)。

またネットメディアだけでなく新聞雑誌などのメディアからの取材依頼も多数ありました。

http://spicelife-jp.tumblr.com/post/118326458799/月刊マテリアルフロー2015年5月号にtmixショールームストアと逆オムニ戦略についての取材記事を掲載
spicelife-jp.tumblr.com

http://spicelife-jp.tumblr.com/post/119745598079/雑誌掲載-日経デジタルマーケティング6月号にtmixショールームについて取材していただきました
spicelife-jp.tumblr.com

http://spicelife-jp.tumblr.com/post/144274148304/通販新聞第1557号のなんと一面記事にtmixショールームの取り組みについて紹介されました
spicelife-jp.tumblr.com

http://spicelife-jp.tumblr.com/post/145250430824/月刊ネット販売6月号の特集1にてtmixショールームについて取り上げていただいています
spicelife-jp.tumblr.com

弊社のオムニチャネル戦略は正直現在の2016年11月の時点ではあのころ考えていたような理想の形まで進められてはいなく、 難しさも感じていますが、世の中のこの流れは止まらないので自分たちのペースでしっかり進めていきたいと思います。

これからも精進いたします。

Dockercon 2016に参加してきました

f:id:yu_suke1994:20160620085646j:plain

最近はTMIXよりもSTEERSのTシャツを着ていることのほうが多いうなすけです。ねむい | オリジナルTシャツ作成・販売 STEERS(ステアーズ)がお気に入りですが、なかなか着て街なかを歩く勇気が出ません。

さて、6/19から6/22にかけて、アメリカ、シアトルでDockercon 16が開催されました。このイベントに、リモートライフ制度を活用して訪問してきたので、感想などをまとめていきたいと思います。

モートライフ制度とは?

モートライフ制度とは、社員が1年に一度、好きな場所で勤務でき、諸費用を会社が負担してくれる、というspice lifeの社内制度のことです。CTOの五十嵐が沖縄、台湾によく行っているのを知っている方も多いかと思います。

花粉症の人は「沖縄で働いていいよ!」 ITベンチャーspice lifeが「リモートライフ制度」導入 | キャリコネニュース

沖縄リモートライフ - スパイスな人生

Dockerとは?

Dockerconの感想の前に、そもそもDockerとは何か?ということに軽く触れておきたいと思います。

Docker - Build, Ship, and Run Any App, Anywhere

Dockerとは、オープンソースの仮想化技術であり、平たく言えば「アプリケーションの実行環境を、コンテナみたいにひとまとめにして実行が簡単にできるようになったもの」です。

使用している技術上、現在サポートされているのはLinuxのみとなりますが、MacWindowsの上でもVirtualboxを使用してDockerを利用することができます。また、Virtualboxの必要ないbetaバージョンも開発中です。

Dockerconは、そのDocker自体の開発者、Dockerを利用している技術者が集まって情報交換、交流を行うイベントです。

感想

発表内容については、国内ニュースサイトでもすでに翻訳済みの記事がいくつか発表されており、内容も詳細まで正確に書かれていると思われますので、ここではあえて解説はしません。

そのかわりに、初めてアメリカを訪れて、Dockerconに参加しての感想をここでは書きたいと思います。

シアトル

シアトルに着いて初めて思ったのは、「寒い!」でした。それもそのはず、シアトルの緯度は北海道よりも高いのです。夏だからと油断してTシャツ1枚で行ったのですが、現地は日本でいうところの秋くらいの気温でした。パーカーを持って行って良かったです。

交通網は豊富で、電車とバスの本数も多く、移動に困ることはありませんでした。支払いも、ORCAというSuicaPASMOのような非接触の決済が可能なのでとても便利でした。

観光らしい観光はしていないのですが、Dockerconが終わったあとに、会場で話したGoogleの方に勧められた場所、Lake Union Parkに行きました。ベンチがあり、噴水もあり、休日なんかにここでボーッとして過ごしていたいような雰囲気の場所でした。 f:id:yu_suke1994:20160621184020j:plain f:id:yu_suke1994:20160621184409j:plain f:id:yu_suke1994:20160621184548j:plain

Dockercon 2016

f:id:yu_suke1994:20160618123416j:plain

まずは会場がデカイです。参加者が多いのでデカくないとそもそも……なのですが、わかっていても驚きです。また、無限コーヒー、朝食、昼食が提供されました。英語を聞いているととにかく疲れて眠くなるので、コーヒーのサービスは特に嬉しかったです。

仕掛けとして、来場時にリストバンドが配布され、参加者同士でぶつけあうとポイントが貯まり、ランクアップできるというゲームがありました。そのおかげで、知らない人に話しかけるきっかけができたのでとても嬉しかったですし、楽しかったです。ちなみにレベル2まで上がりました。 f:id:yu_suke1994:20160619163917j:plain

発表内容ですが、主にオーケストレーション(複数のアプリケーションをどのように協調させるか)についてのトークを聞きに行きました。やはりkubernetesやMesosphereの名前がよく出てきましたが、このDockerconで、オーケストレーション機能が同梱されるようになったのが今後どうなるか興味深いです。

最終日のHack's talkで、resin.ioの方々が飛行中のドローン上に展開されているコンテナを文字通り「無停止で」アップデートするデモを行っていて、まさにノンダウンタイムデプロイだと思いました。できるということはわかっていても、やはり目の前でそれが行われると一味違う感動があります。

帰ってきて、これから

実はTMIXでは、一部環境にDockerを導入しています。しかし、現在様々な技術的問題があり、全環境をDocker化することが難しい状況にあります。それらの問題をどのように解決し、Dockerを導入していくかを考えていきたいと思います。

また、今回の旅で痛いほど英語力の無さ、特にヒアリングの弱さを思い知ったので、何かしら英語の勉強も少しずつやっていきたいと思います。

追記

  • 2016-06-24 15時36分 リモートライフ制度について、Dockerconの感想について追記しました