Web アプリケーションを把握するためのコンソール

技術部開発基盤グループの鈴木 (id:eagletmt) です。 クックパッドではほとんどの Web アプリケーションが Amazon ECS 上で動く状態となり、またマイクロサービス化や新規サービスのリリースにより Web アプリケーションの数も増えていきました。 個々のアプリケーションでは Docker イメージを Jenkins でビルドして Amazon ECR にプッシュし、Rundeck から hako を用いて ECS にデプロイし、またその Web アプリケーションからは Amazon RDS、Amazon ElastiCache 等のマネージドサービスを活用しています。

このように多くの Web アプリケーションが存在し、また各アプリが別のアプリや AWS の様々なマネージドサービスを利用している状況では、どのアプリが何を使っているのかを把握することが困難になっていきます。 具体的には新しくチームに所属したメンバーが、どのアプリがどの GitHub リポジトリに存在するのか、どの Jenkins ジョブを使っているのか、どうデプロイするのかを把握することが難しかったり、また自分のアプリの調子が悪いときにどのデータベースのメトリクスを見ればいいのか、どの ELB のメトリクスを見ればいいのかが難しかったりします。 マイクロサービス化を推し進めて各チームに権限と責任を移譲していく上で、各チームが自分たちのアプリの状態をすばやく把握できる状況は不可欠です。 そういった課題を解決するために hako-console を昨年開発していたので、その話を書こうと思います。 なお今回の話は昨年11月に行われた Rails Developers Meetup #7 での発表と一部重複します。

https://speakerdeck.com/eagletmt/web-application-development-in-cookpad-2017

hako-console とは

hako-console はアプリケーション毎にそのアプリケーションに関連したシステムやメトリクス等の情報を閲覧することができる Web アプリケーションです。 たとえば

  • そのアプリの Docker イメージがビルドされている Jenkins ジョブがわかる
  • そのアプリのエラーログが蓄積されている Sentry プロジェクトがわかる
  • そのアプリが利用している RDS インスタンスがわかり、そのメトリクスも閲覧できる
  • そのアプリが stdout/stderr に出力したログを閲覧、検索できる

といった機能を持ちます。

hako-console app page hako-console ECS metrics page hako-console ELB metrics page

設計方針

Web アプリケーションの把握を手助けするための手段としてまず最初に挙がるのがドキュメンテーションだと思います。 しかしながら、人間が入力した情報は構成変更等があったときに必ず古くなり誤った記述になります。 README に書かれていたジョブを探したけど見つからなかった、ドキュメントに書かれていない別のデータベースにも実は接続していた、みたいな経験はよくあると思います。 これを解決するには「人間が入力しない」ということが重要だと考えていて、AWS のように API で情報を取得できるインフラを使っていたり、hako の定義ファイルのように機械的に読み込める情報があるので、これらの実際に使われている実態と乖離していない一次情報を自動的に集めることを念頭に置いて設計しました。

  • hako-console 自体は極力マスターとなるデータを持たない
    • 既に別の場所にあるデータやメトリクスを表示するだけにする
    • 人間が何かを入力することも極力しない
  • かわりに他のシステムからデータを取得して、それを機械的に処理する

アプリの状態を知るためのメトリクスは Zabbix、Amazon CloudWatch、Prometheus といったものに既に存在していたので、hako-console の役割は各アプリとメトリクスを繋ぐものにしようと考えました。 当初はサーバやマネージドサービスのメトリクスのようなものだけを考えていましたが、AWS X-Ray を使うようになって からは X-Ray のデータを使って通信があるアプリ間にリンクを表示する機能を追加する等 *1、そのアプリについて知るために役立つ情報を追加していきました。

開発に必要な情報を集める

クックパッドでの Web アプリケーションの主要な開発フローは以下のようになっています。

  1. GitHub Enterprise にリポジトリを作成し、そこで開発を行う
  2. 同リポジトリに Dockerfile を追加し、Jenkins ジョブでテストを実行し、docker build && docker push を実行する
  3. hako_apps という中央リポジトリにアプリケーション定義を追加する
    • たとえば example というアプリであれば example.jsonnet を追加する
  4. hako_apps リポジトリの webhook を通じて hako-console にアプリケーションが自動的に登録される
  5. hako-console から Rundeck にデプロイ・ロールバック用のジョブを作成する
    • デプロイ用のジョブは hako deploy example.jsonnet 、ロールバック用のジョブは hako rollback example.jsonnet を実行するように作成される
  6. ruboty deploy example と Slack で発言することで chatbot の ruboty を通じて Rundeck のデプロイジョブが起動され、ECS でアプリが動く状態になる

社内では https://gist.github.com/eagletmt/f66150364d2f88daa20da7c1ab84ea13 のような hako の script を使っており、example.jsonnet の scripts に jenkins_tag を追加すると hako deploy -t jenkins example.jsonnet で最新の安定ビルドのリビジョンを Docker イメージのタグに指定できるようになっています。 そのため example.jsonnet を読めば example というアプリがどの Jenkins ジョブを使っているかが分かります。 Rundeck ジョブは ruboty から使われるため、hako-console を作成する前から Rundeck ジョブ名はアプリ名にすることが習慣となっていました。そのため、Rundeck のジョブを API で取得しアプリ名で寄せることで、どの Rundeck ジョブを使っているかが分かります。 hako-console ができてからは、この習慣に従って Rundeck ジョブが hako-console によって半自動的に作成されるようになっています。

hako-console はこのような形で情報を集めて、アプリケーション毎にリンクを表示しています。

運用に必要な情報を集める

Web アプリケーションが使っている ELB は、hako が hako-${app_id} という固定の命名規則で ELB を作成するため、それで見つけることができます。 たとえば example.jsonnet というアプリケーション定義であれば、hako-example という名前のロードバランサーやターゲットグループが対応します。

RDS インスタンスや ElastiCache インスタンスはどうでしょうか。 Docker コンテナで動かすアプリの場合、接続先の MySQL や memcached のエンドポイントといった設定値は環境変数で渡すことが多く、環境変数は hako のアプリケーション定義に書かれます。 したがって example.jsonnet の環境変数定義を調べて、その中に RDS のエンドポイントっぽい文字列 (つまり /\b(?<identifier>[^.]+)\.[^.]+\.(?<region>[^.]+)\.rds\.amazonaws\.com/ にマッチするような文字列) であったり、ElastiCache のエンドポイントっぽい文字列を探すことで、多くの場合うまくいきます。 こうすることで、各アプリケーションが接続している RDS インスタンスや ElastiCache インスタンスを見つけることができ、また逆に各 RDS インスタンスや ElastiCache インスタンスを使っているアプリケーションを知ることもできます。

hako-console RDS and ElastiCache list page hako-console RDS page

Sentry のプロジェクトについても同様で、Sentry 用の各種 SDK は SENTRY_DSN という環境変数で DSN を設定できるようになっており、API を通じてプロジェクトの一覧を取得できるので、 example.jsonnet に書かれた SENTRY_DSN と API の結果を突き合わせることで Sentry プロジェクトを見つけることができます。

ログの閲覧、検索

ECS で動かしている Docker コンテナのログは、log driver として fluentd を指定し fluent-plugin-s3 を使って Amazon S3 に送信するようにしています。 S3 に送信されたログはそのままでは閲覧しにくいので、hako-console 上でアプリ毎やタスク毎に閲覧や検索できるようにしています。

hako-console log list page hako-console log page

検索には Amazon Athena を使っており、そのためのテーブル定義は AWS Glue のデータカタログに作成しています。 fluentd が ${アプリ名}/${コンテナ名}/${日付}/ のようなプレフィックスで jsonl を gzip で圧縮したものを保存し、日次のバッチジョブがログの中身にあわせたパーティションを Glue のテーブル定義に追加していくことで、S3 にログが送信されてからすぐに検索対象になるようにしています。

まとめ

内製している hako-console について紹介しました。 Web アプリケーションを把握するためのコンソールを作ること、またそのようなコンソールを作成できるようなツールやインフラにすることは重要だと考えています。 hako-console は社内のインフラ事情と密接に関係しているため OSS ではありませんが、それぞれの環境にあわせてこのようなコンソールを作成することに意味があるんじゃないかなと思います。

*1:ちなみに、この「どのアプリとどのアプリが通信するのか」という情報はトレーシングではなくサービスメッシュによって達成しようと動いています https://speakerdeck.com/taiki45/observability-service-mesh-and-microservices

MR による料理サポートのための取り組み

研究開発部アルバイトの山谷 @kei_bility です。リモートアルバイトとして IoT やモバイル、VR, MR の領域で新規サービス開発に取り組んでいます。

その中で HoloLens を活用した MR (Mixed Reality) による料理サポートのための取り組みを少しだけ紹介したいと思います。

概要

HoloLens を装着したユーザーが空間上で AirTap と呼ばれるジェスチャーをすると、いま見ている状態をキャプチャしてその画像を API リクエストでサーバへ送信します。

そしてサーバ側で画像認識した結果を受け取りその結果を表示します。

背景

背景としては、Semantic ARのように HoloLens と画像認識モデルを組み合わせ画像認識結果を現実世界に重畳させてユーザーに提供したいというモチベーションがありました。 HoloLens で画像認識するには HoloLens 自体で画像認識モデルを動かすか、API を経由してサーバ側で画像認識した結果を可視化するかの2通りがあります。 前者の方法について TensorFlowSharp などを使ってモデルを動かせないか検討していましたが、 HoloLens の CPU/GPU では画像認識モデルの推論計算に時間を要する or モデル自体を圧縮する必要があるなど、すぐに試せなさそうなことがわかりました。 ということで、今回は HoloLens から画像を取得しその画像に対して API を通してその結果を可視化することにしました。

社内には Cookpad Computer Vision API (別名 See Food API) があります。ここにはクックパッドの画像認識モデルがAPI化されており、最新の研究成果を利用することができるようになっています。 今回はこの API と HoloLens を連携させてみました。

以下では Unity でのセッティング、HoloLens でのカメラ画像の取得、APIリクエストについて触れます。

Unity での UI セッティング

Unity で作る UI としては、キャプチャした画像を表示するパネルと、画像認識結果を表示するパネルの2つをユーザーの前に配置します。

f:id:kei_bility:20180328184731p:plain

カメラ画像の取得

HoloLens のカメラ画像を Unity で取得するため以下のように PhotoCaptureObject を使ってカメラパラメータを設定します。

void OnPhotoCaptureCreated(PhotoCapture captureObject)
{
    photoCaptureObject = captureObject;

    Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();

    CameraParameters c = new CameraParameters();
    c.hologramOpacity = 0.0f;
    c.cameraResolutionWidth = cameraResolution.width;
    c.cameraResolutionHeight = cameraResolution.height;
    c.pixelFormat = CapturePixelFormat.JPEG;

    captureObject.StartPhotoModeAsync(c, false, OnPhotoModeStarted);
}

APIリクエスト

ユーザーがジェスチャーをしたらイベント発火し、API へリクエストを送ります。Unity の WWWクラスを利用し、C# スクリプトとして以下のように実装します。 レスポンスの json データからインスタンスを生成するため、レスポンスデータに対応する [Serializable] なクラスを用意しておき、 Unity 5.3 から利用できる JsonUtility で json からインスタンスを生成します。

WWW www = new WWW(apiEndPoint);
yield return www;
string response = www.text;
var result_json = JsonUtility.FromJson<ImageRes>(response);

こうしてユーザーが AirTap すると目の前の画像に対して認識した結果を表示します。

f:id:kei_bility:20180328001905j:plain

まとめ

Mixed Reality を実現する HoloLens を活用した料理サポートのための取り組みを紹介しました。 今後は料理動画をキッチンの任意の場所に貼り付けて操作できるようになったり、食材を認識して下ごしらえの仕方を教えてくれるなど、 Mixed Reality によって料理の新しい体験やサポートができるようになればいいなと考えています。

いかがでしたでしょうか。 クックパッドでは、IoTやモバイル、VR, MRで新たなサービスを創り出そうとチャレンジしています。 興味のある方はぜひ話を聞きに遊びに来て下さい。

人工知能学会のトップカンファレンス派遣レポータとして NIPS2017 に参加しました

研究開発部の菊田(@yohei_kikuta)です。機械学習を活用した新規サービスの研究開発(主として画像分析系)に取り組んでいます。 最近読んだ論文で面白かったものを3つ挙げろと言われたら以下を挙げます。

人工知能学会の トップカンファレンス派遣レポータ という制度で NIPS2017 に参加しました。 学会への参加に加えて、その後の論文読み会や報告会での発表など様々な活動をしましたので、一連の活動を紹介したいと思います。

NIPS2017 の特徴的な写真として invited talk の一コマを貼っておきます。驚くほど人が多い...

20180327114113

また、参加して自分が面白いと思った内容(deep learning のいくつかのトピック)をまとめた資料も最初に紹介しておきます。

経緯

昨年 トップカンファレンス派遣レポータ という制度がアナウンスされ、新しい取り組みで面白そうな企画でもあるので応募しました。 学会に参加するだけなら応募せずに会社で申請して参加すればいいのですが、NIPS の内容に興味を持つ人が集まりそうな場での発表の機会が得られるということが主たるモチベーションでした。

レポータとして選ばれるのは3名で応募者の統計情報などは明らかにされていません。 3名の内訳は、大学の先生・大学院生・私、という感じでバランスも考慮されている印象を受けました。

応募自体はA4の資料を一枚程度作成すればよいもので(郵送ですが)、それで必要経費を全て出してくれるというなかなか太っ腹な制度だと思います。 今年も同様の内容で募集する可能性が高そうなので、興味がある方は申し込んでみるのもよいと思います。 昨年は5月上旬に人工知能学会のメーリングリストから応募者を募るメールを受け取りました。

NIPS2017

Neural Information Processing Systems (NIPS) は機械学習の主要な国際会議の一つで、私は2015年にも参加していて二回目の参加となりました。

昨今の機械学習ブームを牽引する学会でもあり、2017年は registration が8000人でそれもかなり早い段階で打ち切られたという状態でした。 投稿論文数も3240件(採択率21%)で2016年から30%程度増加しており、年々その熱量が増しています。 企業のスポンサーは84社にも上り、diamond sponsor に関しては展示会さながらの大々的な展示が繰り広げられていました。

論文採択に関しては面白いデータが紹介されていて、事前に arXiv にも submit されていた論文は43%に上り、レビュワーがそれを見た場合の採択率が35%という高い数字であったというものです。 レビュワーが見てない場合も25%と高い水準のため、そもそも質が高めの論文が arXiv に submit されるという傾向はあるかもしれませんが(例えば地力のある研究室がそういう戦略を取っているなど)、arXiv が機械学習分野にも高い影響力を発揮していることが伺えます。 学会では査読されてから publish されるまで時間も掛かるので、論文は arXiv などですぐに共有されて open review などで評価する open science 化が進んでいくかもしれません。

内容に関しては、NIPS において長らく主題の一つである algorithm が最多でありながら、deep learning や meta learning などの勢いが著しく、それ以外にも fairness や interpretability のような分野の台頭が目立つという、様々な側面で盛んに研究が進められているという印象でした。 個々の詳細な内容の説明はここでは省きますが、deep learning 関連のまとめに関しては冒頭の紹介資料にも記載しています。

NIPS2017 では新たな取組として competition track や DeepArt contest が開催されていました。 前者は kaggle のようなコンペを事前に開催して当日に上位入賞者に解説をしてもらうというような形式で、後者は style transfer を使って画像を artistic に変換して投票で入賞者を決めるという形式でした。 学会にこれらの要素が必要なのかということは議論の余地があるかもしれませんが、学会も世の中の動向に合わせて変化を続けていることが伺えるものでした。

その他にはネットでも話題になった苛烈な人材獲得競争のような話題がありますが、参加者としてはそこまで騒ぎ立てるほどではないと感じました。 一部でバブルを感じさせるイベントがあったりしたことは事実ですが、学会の性質を歪めるほどのものではないように思います。 学生としても自分が興味のある企業に直接アプローチする機会が増えて良いのではないでしょうか。

NIPS2017 論文読み会

せっかく参加したので、興味を持った論文をもう少し深く読んで発表しようと思い クックパッドで論文読み会を主催 しました。 読み会の様子です。

20180327114104

私は GAN の学習の収束性に関するいくつかの論文を読んで発表をしました。

本来はどこかで開催される読み会に参加して発表だけしようと思っていたのですが、観測範囲内で望ましいイベントが開催されなかったので主催するに至りました(その後いくつか同様のイベントが開催されました)。

イベントの主催は大変なところもあるのですが、機械学習に興味のある方々に参加していただき盛況でした。 こういったイベントを通してクックパッドに興味を持って頂ける場合も少なくないので、主催してみて良かったなと思います。

今後もこのようなイベントを開催していくことになると思いますので、興味のある方は是非ご参加下さい。

NIPS2017 報告会

派遣レポータの仕事として事前に開催が決まっていた 報告会 でも発表しました。 20180221に大阪大学中之島センターで、20180228に早稲田大学西早稲田キャンパスで報告会が開催されました。

有料イベントにも関わらず満員御礼状態で、特に企業の方々の参加者が多かったと伺っています。 久しぶりの大学での発表だし、NIPS の報告でもあるので、内容は思いっきり deep learning の理論的な話をしました。 参加者の目的と合致していたかは一抹の不安が残りますが、自分が聴衆として聞くなら悪くない内容だったと思っています(自分が話してるので当然ですね)。

その他

人工知能学会紙に参加報告を載せる予定です。 また、それ以外にも付随して何かやるかもしれません。

まとめ

人工知能学会のトップカンファレンス派遣レポータとして NIPS2017 に参加した話と、それに関連するイベントで何をやったのかという紹介をしました。 NIPS は理論的な色合いが濃い学会ではありますが、次々と新しいものが出てくる機械学習界隈ではこういった内容をキャッチアップしていくのは事業会社の研究開発でも重要だと考えていて、そして何より自分が好きなので、参加して得られた知見を今後の業務に活かしていきたいと思います。

いかがでしたでしょうか。 クックパッドでは、機械学習を用いて新たなサービスを創り出していける方を募集しています。 興味のある方はぜひ話を聞きに遊びに来て下さい。 クックパッド株式会社 研究開発部 採用情報