ユニファ開発者ブログ

ユニファ株式会社システム開発部メンバーによるブログです。

AWS Startup Architecture of the Year Japan 2020 で優勝しました!!

f:id:akanuma-hiroaki:20200923223808j:plain

皆様こんにちは、ユニファの赤沼です。

先日プレスリリースも出させていただきましたが、9/16 に行われた AWS Startup Architecture of the Year Japan 2020 Live Finale にて、ルクミー午睡チェックのアーキテクチャについてプレゼンさせていただき、ユニファが優勝することができました!これも日々社内でサービス提供のために取り組んでいる開発、ビジネス、コーポレートの全メンバーの努力が評価されたものですし、メンタリングいただいた AWS の松田さん、岡田さんのおかげですし、何より日々保育の現場で真摯に保育に取り組まれている保育者の方々のご尽力の成果でして、本当にありがたく思っています。

今回はどういったところが評価されて受賞に至ったのか、また、事前の準備や当日の様子などについてご紹介できればと思います。

AWS Startup Architecture of the Year とは

「AWS Startup Architecture of the Year」は2018年に日本で生まれ、今年から世界規模で展開されるスタートアップのためのコンペティションで、評価の対象はビジネスを成功に導く優れた「アーキテクチャー」です。そのアーキテクチャーがいかに AWS Well-Architected Frameworkの基準に適合しているか、ビジネスにインパクトを与えているかといった点が評価の対象となります。日本、米国、インド、欧州の各地域から、優れたアーキテクチャーでビジネスをけん引しているスタートアップが選出され、11月に開催予定の世界大会(オンライン)にて世界一を決定します。

Startup Architecture of the Year Japan 2n020

aws.amazon.com

評価されたポイント

さて、今回どういったところを評価いただいたかですが、受賞時に審査員の藤本さんからいただいたコメントから、派手さはないけれどやるべきことをしっかりやっているというところを評価いただいたと思っています。

ルクミー午睡チェックでは命に関わる業務の安心・安全をサポートするというプロダクトの性質上、 Well-Architected Framework の5つの柱の中でも、特に信頼性と運用上の優秀性が求められます。信頼性という点では、DynamoDB と SQS を使ってパフォーマンスを担保している点や、 Design for Failure を考慮した DLQ の仕組み、ネットワーク障害等が発生してもローカルのみで一定の業務が継続可能にしている点等で担保しています。また、運用上の優秀性といった点では、SORACOM Air Sim を用いたセルラー回線を使うことでの安定した接続や導入時の保育園側のハードルの低減といった点で考慮しています。

一つ一つは技術的に尖っているわけではないですが、サービスの特性を考えて求められる点を総合的にしっかりカバーし、そしてこれらが実際にプロダクトの導入実績と紐づいて、事業に貢献できているというところが評価いただけたものと思っています。

メンタリング

応募後に書類選考を通って Live Finale での登壇が決まった段階で、 AWS の松田さんと岡田さんにメンタリングいただき、5分間という短い時間でどういった点を伝えるのが良いかをアドバイスしていただきました。それをもとにプレゼン資料とシナリオを作成したのですが、5分間というのは思っていたよりもとても短く、その中で事業やアーキテクチャ、ビジネスへの貢献をしっかり説明するには、スライドで表示して理解してもらうことと喋って説明することを吟味して、不要なものをできる限り削る必要がありました。そして一旦作ったもので松田さんと岡田さんにレビューいただき、ダメ出しを経てなんとか5分間で伝えるべきことをまとめることができたと思います。松田さんと岡田さんには本当に感謝です。

当日の様子

当日のプレゼンの順番は社名の五十音順ということで、六社中一番最後だったのですが、ということは一番最後まで緊張してることになるので、正直他社のプレゼンをしっかり見てる余裕はありませんでした。見てると余計に緊張しちゃうので。。

またこれは完全に自社の事情なのですが、当日 Live Finale の直前に取締役会があり、どうしても外せなかったので、岡田さんに会議室を手配いただき、Amazon目黒オフィスの会議室からリモートで取締役会に参加させてもらいました。取締役会では自分のアジェンダもあり、 Live Finale のことを考えるとそわそわしながら参加していたのですが、なんとか無事に予定時間までに取締役会も終えることができました。岡田さんには私のわがままにご対応いただき、感謝です。

朝から吐きそうに緊張してましたが、プレゼン自体もなんとか5分間に収めることができ、審査員のCTOの方々からどんなマサカリが飛んでくるかとびびっていた質疑応答も乗り越えて、やっとほっとした感じでした。

世界大会

今のところ世界大会については、11月にオンラインで開催、という以外にはまだ何も聞いていないので、プレゼン英語なのかなー、というぐらいなのですが、審査員の藤本さんや松本さんからはしっかりプレッシャーかけられたので、日本代表としてはがんばらねばと思っています。プレゼン自体は英語でもなんとかなりそうな気がしますが、質疑応答が英語でできるのか。。英語力を鍛える必要がありますね。。

まとめ

事前の準備は色々と大変でしたが、受賞できたことは本当に嬉しく、SNS等でも多くの方からお祝いの言葉をいただきました。本当にありがとうございます。また、社内のメンバーとしても自信につながるところもあると思いますし、社外に向けてのアピールになる点も大きいのではないかと思います。私自身も改めてアーキテクチャを見直して Well-Architected Framework について考えるきっかけにもなりましたし、今後より良いプロダクトを提供できるようにチャレンジしていこうというモチベーションにもつながりました。

そしてインフラエンジニアをはじめ、このチャレンジに一緒に参加してくれる方を募集してますので、興味のある方はぜひご連絡ください。一緒に保育をハックしていきましょう!!

herp.careers

Jamstackで動的サイトを作ってみる

こんにちは、サーバーサイドエンジニアの柿本です。

みなさんは Jamstack をご存知ですか??!!

先日知人が Jamstack について熱く語ってくれまして、私は「ナニソレオイシイノ?」と思って聞いていたのですが、彼があまりに熱く語るので「サゾカシオイシイニチガイナイ!」ということでいろいろ調べてみました。

「 SPA と SSR のいいとこ取り」や「動的サイトと静的サイトのいいとこ取り」といった魅力的な言葉が並ぶのですが、つまるところ、

サイトの中の静的な箇所は完全に静的ファイル化しておいて、動的な部分はAPIを叩いてよろしくやろうぜ!

ということのようです。

早速入門してみようとしたところ、 Jamstack の入門記事は主に ヘッドレス CMS や SSG (静的サイトジェネレータ)との繋ぎ込みなど 静的ファイル化部分 に主眼が置かれておりました。
動的によろしくやる方法を知りたかったので、自分でやってみることにします。

TL;DR

1クリックで Netlify にデプロイすることができます!

Deploy to Netlify

事前準備として FaunaDB のセットアップと Server secret の取得 が必要です。

デプロイ完了後に Netlify Identity の設定 が必要です。

目次

技術スタック

  • 静的サイトジェネレータ: Next.js
  • ソースコード管理: GitHub
  • ホスティング・CDN: Netlify
  • データベース: FaunaDB
  • ヘッドレスCMS: 利用なし(*動的部分をターゲットとしてるので使いません)

Jamstack の構成としては標準っぽい物を選定しました。

構想

動的サイトといえば ユーザーログインデータ保存が基本となるので、 『ユーザー登録制の掲示板サイトもどき』 を作ってみます。

ユーザーストーリー

  • ユーザーがログインできる
  • ユーザーが自分の名前でメッセージを投稿できる
  • メッセージ一覧を誰でもみれる

画面構成

/ フロントページ(メッセージ一覧)
└/ メッセージ投稿画面

非常にシンプルですね!

最終形態

f:id:unifa_tech:20200918003519g:plain
2人のユーザーによるログインから記事投稿まで

最終成果物

GitHub に公開 しました!
開発手順の詳細も README に記載してあるので、参考にしてみてください。

github.com

開発の流れ

  1. Next.js のセットアップ
  2. GitHub に push
  3. Netlify にデプロイ
  4. Netlify Identity の設定
  5. フロントコーディング
  6. FaunaDB の設定
  7. Netlify Functions コーディング

実装のポイント

フロントエンド

フロントエンドを構成するソースファイルは以下です。

dynamic-jamstack (App root)
├── pages
│   ├── index.js           // ホーム(メッセージ一覧)画面
│   └── new_message.js     // メッセージ投稿画面
├── components
│   ├── Message.js         // 1つのメッセージ表示
│   ├── MessageList.js     // メッセージを一覧で表示&データ取得処理
│   └── MessageForm.js     // メッセージ入力フォーム&データ送信
└── utils
    └── netlifyAuth.js     // Netlify Identityの認証処理

/pages/ 配下は Next.js により静的化されるページです。
デプロイ時に静的化されるため、ここに動的な処理(データ取得&描画)を記述しても想定どおりに動きません。

/components/ 配下は React コンポーネントです。
動的な処理をここに記述し、 pages のファイルで読み込むことで動的な挙動を実現できます。

Netlify Functions (API)

API のロジックは以下で構成されます。

dynamic-jamstack (App root)
└── functions
    ├── messages-create.js       // メッセージ保存
    └── messages-read-all.js     // メッセージ一覧取得

Netlify Functions の中身は AWS Lambda なので、書き方は同じです。

/messages-create はログイン済みのユーザーのみに制限する必要があり、クライアントと Functions のそれぞれで以下の対応が必要です。

クライアント - Header に Netlify Identity Widget から取得した token をセットします。

// components/MessageForm.js

  generateHeaders() {
    const headers = { "Content-Type": "application/json" }
    if (netlifyIdentity.currentUser()) {
      return netlifyIdentity.currentUser().jwt().then((token) => {
        return { ...headers, Authorization: `Bearer ${token}` }
      })
    }
    return Promise.resolve(headers)
  }

Functions - context.clientContext.user でユーザー情報を取得することができます。

// functions/messages-create.js

  const user = context.clientContext && context.clientContext.user;
  if (!user) {
    return callback(null, {
      statusCode: 401,
      body: JSON.stringify({ "error": "You must be signed in to call this function" })
    })
  }

考察

今回は "Jamstack構成で動的な処理を実装する" を目的として Next.js をベースに

  • 動的な処理を React コンポーネントで記述
  • 静的ファイル化される箇所からコンポーネントを呼び出し

として実現しました。

わかったこと

  • Jamstack 構成で動的サイトは実現可能
  • ユーザー認証は Netlify Identity で実現可能
  • ローカル(静的ファイル内)でも API 内でもユーザー情報を取得可能
  • データ保存はサーバーレスのデータストアにより実現可能

課題

1) サイトによる向き不向きがありそう

いわゆる SNS のような動的な処理がメインのサイトの場合、静的ファイル化できる部分が限られるためあまり恩恵を受けられないかもしれません。

メリットを最大化するには静的化する箇所を適切に切り出す必要がありそうです。

例えば弊社サービスのルクミーフォトの販売画面(購入する写真を保護者が選択する画面)などは、販売写真の設定がされたタイミングで静的ファイル化すればハイパフォーマンスのメリットがありそうです。

そのためには incremental build が適切に実行されるようにする、などの複雑な設定も必要になるかと思います。

2) pages 配下は静的ファイル化される、と意識してコーディングする必要がある

Next.js の仕組み上当たり前のことなのですが、ローカルの開発サーバー上でホットビルドをしているとついつい忘れてしまいます。

これは慣れの問題だとは思いますが、 Netlify にデプロイしてから「あれれ?」となることが何度かありました。(笑)

まとめ

Jamstack で動的サイトを作ることが可能なことは分かりましたが、感想としては「ちょっと無理やり感が否めない」といったところです。

とはいえ Netlify などの CDN 経由で静的ファイルを配信できることのメリットは大きいので、サイトの向き不向きは選びますが、活用していければ良いなと思いました。


ユニファでは保育をハックするエンジニアを募集中です。 一緒にスマート保育園を実現しましょう!

www.wantedly.com

Appendix

FaunaDBの設定

https://fauna.com/ からアクセスし、 Signup します。 Netlify のアカウントでも Signup できます。

任意の名前で Database を作成し、以下を設定します。

  • Collection - Name: messages
  • Index - Name: all_messages

SECURITY メニューから key を作成し、 Server secret を取得します。
Server secret は2度と表示されないので、無くさないように保管します。

Netlify Identityの設定

Netlify の dashboard の Site 一覧から対象の Site を選択します。

Identity > Enable Identity の順にクリックしてアドオンを有効化します。

Setting and usage > Registration > External providers で追加したい認証プロバイダーを選択します。

f:id:unifa_tech:20200918025325p:plain
Netlify Identity の External providers

TensorFlow Profilerを用いた学習時間の短縮

こんにちは。R&D改めデータエンジニアリングチームの宮崎です。 普段はTensorFlowを使って、Deep Learningを学習させて画像認識モデルを作ったりしています。

Deep Learningの悩みの一つとして、学習時間が数時間から数日に及び、非常に長いという点が挙げられます。 作業効率やマシンの費用を考えると、少しでも学習時間を短くしたいです。 そこで今回はTensorFlow Profilerを用いてDeep Learningの学習時間を短縮してみたいと思います。

TensorFlow Profilerとは

TensorFlow ProfilerはTensorFlowの計算時に、処理毎の所要時間などパフォーマンス情報を収集し、TensorBoard上で可視化してくれるツールです。 TensorFlow v2.2.0やv2.3.0で機能が強化され、より詳細な分析ができるようになっています。

続きを読む

コンテキストスイッチから思ったこと

こんにちは、プロダクトエンジニアリング部のちょうです。最近ミーティングでコンテキストスイッチというワードが出て、これについて思うことがあり、すこし話したいと思います。

ここのコンテキストスイッチはプログラムのコンテキストスイッチではなく、毎日の仕事や勉強の中、あることをやって、その後また別のことをやる、つまり仕事の切り替えということです。仕事の切り替えがいいとか悪いのかというと、はっきり言えません。仕事の切り替えができないとそもそも仕事ができないというイメージになり、ものすごく切り替えると効率が落ちるに違いありません。

開発メンバーから見て、ミーティングが多くなると、丸一時間、丸二時間の開発時間が取れなくて、「あれ、ミーティング前に俺何をやったっけ」ということもあり、進捗があまり進まないこともあります。とはいえ、ミーティングの時間はみんな空いている(ように見える)時間帯から決めたから、簡単に変えられないです。一つ解決策はあまり要らないミーティングをキャンセルし、任意参加なら時間があるかどうかで決めるのです。残りは自分で仕事をどこまで効率化できるのか。

一番簡単なのか、予定してた時間内で完了するのです。つまりコンテキストスイッチがないということです。仕事を30分内、1時間内で完了できる細かいタスクに分けるのも効果的です。

次は、コンテキストスイッチの問題というと、前回仕事の内容はすぐに思い出せないということです。プログラムのコンテキストスイッチでしたら、切り替える前にいまやっている仕事の内容をどこかに保存します。そのように、次の仕事に入る前に、現在の仕事を保存します。具体的には

  • Macbookでdesktopを活用して、仕事AのDesktopと仕事BのDesktopを分けるようにしましょう。
  • IDEにはチケット単位やブランチ単位で開いたファイルなどを覚えることができます。またはチケットに何をやっているかをコメントするのも良いでしょう。
  • もっと一般的なことはメモなどに書いても問題ないでしょう。
  • 特別に、現在やっている仕事まだ終わってないという気持ちでブラウザのタブを開きすぎるのはよくあると思いますが、あえてOneTabでタブをまとめたり、タブのリンクをメモなど(つまり現在の仕事と関係ないタブをすべて閉じる)に保存するのをおすすめです。あとでタブを探すのが大変のと複数の仕事のタブが混ぜるとお互い邪魔になるからです。

もう一つ効率的に仕事する方法は同じ種類の仕事を連続やるのです。同じ種類だとコンテキストが似ていて、スイッチしても影響は少ないです。具体的にはパソコンの前にやる仕事をまとめやったり、同じプロジェクトの仕事を連続やったりするのです。

いかがでしょうか。すこし自分の仕事の効率どうやって上げるのを分かるようになりましたか。最後に、本記事はいくつの方法を紹介したが、「ミーティングの合間」に頑張るより、連続で影響されない時間があれば一番いいということを忘れないでください。

Amazon ECS+FargateでRailsを動かす際の最適なパラメーターを考えてみる

こんにちは、最近野菜が高いのでもやしばかり食べているWebエンジニアの本間です。 そろそろレタスが食べたい...。

さて、ここ1、2年、ユニファではAmazon ECS+AWS Fargateを使用して、Railsアプリケーションを本番運用することが増えてきました。 stagingでテストしたDockerイメージがそのまま本番で使えて安心だったり、オートスケールが簡単だったりとメリットが多く、大変便利だと感じています。

ただ、そのような環境を構築する中で、vCPU数やメモリ量、およびPumaの並行性に関するパラメーターをどうしようか毎回悩んでいたため、この辺で自分の中で整理しておこうと思います。

続きを読む

マルチAWSアカウント環境での構築をTerraformで行う際に待機する

おはこんばんちは

ユニファのインフラみてます、すずきです。

8月に入ってから猛暑と湿度で部屋から一歩も出たくない日々が続きますね。 涼しくなれ!

さて、Terraformでステータスが更新されるまで情報が取得できない、変更できないリソースなどは、Create後すぐに別のリソースで呼び出そうとするとエラーになることがあります。 ちょっと違うけど、ACMって検証が終わるまでELBやCloudFrontで呼び出せないので Resource: aws_acm_certificate_validation を利用して待機しますよね。

そういったことが起こりうるリソースで同じことをやってみようというものです。

続きを読む

緊急事態宣言下でのシステム運用振り返り

みなさんこんにちは。

ユニファでサーバーサイドエンジニアをしております田渕です。

新型コロナウイルスによる突然の生活の激変が起こってから、早くも半年近くが過ぎようとしています。 (居住している国、地域などにより、体感している期間は多少異なると思いますが。。。) 弊社でもこれまでに何度か、新型コロナウイルスにまつわる投稿をこのブログの中でしてきています。 経験したことのない状況の中、色々と試行錯誤をしながら進めてきたわけですが、今回は主としてここまでの「システム運用」について振り返ってみたいと思います。

前提

これを読んでくださっている方はおおよそご存知かと思いますが、ユニファは保育園、幼稚園、こども園様向けのプロダクト/サービスを提供しています。 したがって弊社では、新型コロナウイルスにおける緊急事態宣言のもとにおいても、平時と変わらない(あるいはそれ以上の)レベルでの安定したシステム稼働が必要でした。

どんな状況だったのか

勤務体制

何度かこちらのブログでも紹介している通り、ユニファのエンジニアは元々リモートワークが可能な勤務形態でした。 これまではリモートワークと言えばエンジニアがメインでしたが、緊急事態宣言に伴い、全社的に可能な限りリモートワークを行う体制に移行していました。

緊急事態宣言下における当社の業務に関するお知らせ

tech.unifa-e.com

エンジニアのリモートワーク状況については、下記の記事を参考にしてください。

tech.unifa-e.com

システムの利用状況

以前、弊社エンジニアの島田が、緊急事態宣言下での保育施設利用状況について、本ブログにてまとめてくれたことがありました。

tech.unifa-e.com

このブログの中でも書かれている通り、3月~5月は園児さんの欠席率が大きく上がり、保育園の稼働率も例年の同時期と比べると大きく下がっていました。

何が難しかったのか

ここまで聞くと、システム負荷が低いだけだし、そんなに問題はないのでは、……とお考えになるかと思います。 が、実は裏側では、日々バタバタしていました。

難しくしていた原因その1:いつもと違う利用のされ方

平常時と異なる状況なので、いつもとは少々異なる負荷の傾向が現れていました。 具体的な例では、先に紹介した保育施設の利用状況のデータをまとめたブログ中でもご紹介した「欠席コメント欄への記入率違い」などが挙げられます。

f:id:unifa_tech:20200603160824p:plain
[再掲]緊急事態宣言前後でのコメント記入率

緊急事態宣言が発令された2020年4月7日以降で、明らかに利用の仕方が変わっていることが分かると思います。 この様な事例が、幾つか見受けられました。

システム保守をしているサーバーサイドエンジニアならば多くの方がシステムの利用状況、負荷状況を日常的に気にされていることと思います。 通常、システム利用の予測というのは、これまでの利用データ、負荷状況、利用者数の増加予測などを元として行っていきます。 しかしながら、新型コロナウイルスに対しての様々な新しい対応が日々、各所で行われる中では、これまでの利用データがあまり参考にならず、かつ今後の利用者数の予測を行うことは非常に難しいことでした。 基本的にシステムというのは、ある一定の想定条件下で正常に動くように各所のパラメータが調整されているので、その条件を外れれば正常に動かない箇所も出てきます。 事前に考えられる事態に対して対策はしていましたが、やはり事前には予測していなかった状況に直面しました。 それらのうちの幾つかの要素を原因としたトラブルに見舞われる中、地道にデータを分析し、暫定対応、恒久対応を行っていくことで事態の収束を行いました。

難しくしていた原因その2:全社的なリモートワーク

エンジニアのリモートワークはこれまでも行って来ていましたが、全社的に大多数の社員がリモートワークになるという状況は初めてのことでした。 どの会社でも同じだと思いますが、トラブルの発生の折には社内の関連部署への連絡が必須となります。 平時であれば誰かしら出社していたので、速報を口頭で伝えるということもしていたのですが、全員がリモートなのでSlackでの連絡が全てのきっかけになります。 元々エンジニアにリモート勤務が認められていた環境でしたので、Slackでの各所との話し合いは定着していたのですが、「口頭で速報を伝える」という手段を封じられるという状況はありませんでした。 もちろん、一番初めのきっかけ以降はリモートの会議体制に移行し、話し合いを行えますが、第一報はSlackです。 このことは、意外に緊急時に於いて、情報の速報性を妨げました。 というのも基本的にSlackは送ったからと言って必ずしもその場で読んでもらえるものでもないからです。

対策を考えてみる

緊急事態宣言が今後再び発令されるかは分かりませんが、少なくとも暫くの間はリモートでの勤務を継続することにはなるでしょう。 となれば、上記の困ったことを放っておく訳にはいきません。

いつもと違う利用状況に対して

必要となるのは、下記の要素だと考えています。

  • 問題が発生した際の検知の早さ
  • 影響の最小化に向けた取り組み
  • 適切な暫定対応を行うための早期の決断

このうち、「問題が発生した際の検知の早さ」に関しては、ログやシステム監視の検知条件の見直しなどを実施し、平時と異なる利用があった場合に検知が可能となるように改善を行いました。

「影響の最小化に向けた取り組み」については今回利用した暫定対策の手順等をまとめ、次回の類似事象発生時には即座に適用できるようにしました。 また、問題の原因分析、システムの状況がより分かりやすくなるように、検知ツール類の設定の見直しも行っています。 が、これに関しては実際は発生した事象ごとに必要な情報も異なってくるため、実際のところは発生ベースでの対応となってしまいます。

残る「 適切な暫定対応を行うための早期の決断」については、次項で詳細を記載する体制の整備の中で承認ルートの見直しを行っています。

リモート主体勤務時のトラブル対応体制の整備

トラブルが発生した際、「どこのチャンネルで」「どうやって」一報を流すのかについて、改めて整備と認識合わせを行いました。 これまでも基本的に一報を流すことはSlack上で行ってきましたが、自身のチーム内や直接的な関係者しかいないチャンネルを利用していることもあるなど、その方法が統一されていませんでした。 今回のことを機に

  • 一報を出す場所、メンション先、報告内容
  • システム利用者への連絡方法
  • トラブルによる緊急リリースが必要となった場合の承認ルート

の再整備を実施しています。

まとめ

今回は、今年2月以降で経験したことについて、備忘の意味も込めて記載してみました。 全く整備や準備が出来ていなかったという訳ではなかったのですが、非常時に於いてはほんの少し詰めの足りなかった部分が綻びとなり、顕著に形となって現れてくるものなのだなと感じています。 当たり前のことしか書かれていないのですが、当たり前のことが出来てないと非常時に困るんだ!ということを痛感した期間でもありました。 幸い、「もっとここが出来ていたらな。」という内容なので、今後も続くこの状況でもより安定してサービス提供を行えるように試行錯誤を繰り返して行こうと思っています。

自分たち自身も平常時と環境が異なる中、平常時以上のサービスレベルを保つと言うことはそれなりに苦労もありますが、一方で利用者の方から見て「動いていないと困るサービス」になれているのだ、と言うことが実感できた期間でもありました。 そのことは純粋に、有難いことだなと感じています。

ユニファでは現在も積極的に仲間を募集しています! ご興味のある方は、お気軽にお声がけください。

unifa-e.com