https://hrbrain.connpass.com/event/157875/ でお話しした内容です
スライド内で紹介している記事 https://speakerdeck.com/yudppp/row-level-security-is-silver-bullet-for-multitenancy https://speakerdeck.com/yudppp/sqldef-introduction-for-psql-users
会社紹介資料 https://speakerdeck.com/hrbrain/introduction
2019年HRBrainの技術的挑戦
View Slide
⾃⼰紹介@yudppp株式会社HRBrain CTO好きな⾔葉: 冪等性 嫌いなモノ: 浮動⼩数点の誤差 Go / TypeScript書いてます
⽬標評価管理クラウド
HRBrainとは• ⽬標と評価を管理するクラウドSaaSを作っている会社です。• リリース開始からもうすぐで3年• Horizontal SaaS (業界を問わずに導⼊されるSaaS)
2019年⼈員推移• 1⽉• サーバーエンジニア: 3⼈• フロントエンジニア: 3.5⼈• デザイナー: 1⼈• 現在• サーバーエンジニア: 7.5⼈• フロントエンジニア: 7⼈• デザイナー: 1⼈• スクラムマスター: 1⼈• QAエンジニア: 1⼈2.33ഒ
2019年⾏ったこと• ⽬標評価管理クラウドのリニューアル(2019/3/18)• リリース後、週1~2でリリース(合計76回)• 初めての開発合宿@館⼭(2019/08/01~02)• クラウドベンダー移⾏(2019/12/29)• AWSからGCPに移⾏する• ⼈事DBの仕込み• 2020年3⽉リリース予定• 合わせてマイクロサービス化
⽬標評価管理について
なぜリニューアルしたかࢀՃऀݶఆެ։
リニューアル後の技術スタック• Go• TypeScript(not strict)• React• Docker• REST API• PostgreSQL• Swagger• Vue/Nuxt(LP/Help)• Netlify CMS(Help)• JAM Stack(LP/Help)
アーキテクチャ• マルチテナントアーキテクチャ• 1つのアプリケーションでデータベースを共有 (最も効率的な真のマルチテナンシー)
1つのクラウドサーバーに全ての企業اۀ" اۀ# اۀ$اۀ"͚ "1αʔόʔاۀ"͚ %#اۀ#͚ "1αʔόʔاۀ#͚ %#اۀ$͚ "1αʔόʔاۀ$͚ %#
1つのアプリケーションで異なるDBを使⽤اۀ" اۀ# اۀ$اۀ"͚ %#"1αʔόʔاۀ#͚ %#اۀ$͚ %#
1 つのアプリケーションでDBを共有اۀ" اۀ# اۀ$"1αʔόʔ%#
DBを共有した時のメリット• インフラのコストが安い• スキーマの更新が簡単• ⼀度のリリースで全てのテナントがリリースされる
DBを共有した時のデメリット• 実装難度が⾼い• DBの障害時に全テナントに影響がでる• セキュリティに不安がある• あるテナントが別のテナントのデータを⾒れてしまう可能性がある(data violation)
ձࣾ"ձࣾ#ձࣾ#ձࣾ$こんな感じのusersテーブルがあった時に
ձࣾ"ձࣾ#ձࣾ#ձࣾ$本来Where句を指定するところを4&-&$5'30.VTFST 8)&3&[email protected]ձࣾ#z
ձࣾ"ձࣾ#ձࣾ#ձࣾ$Where句を指定忘れてしまうと4&-&$5'30.VTFST
ձࣾ"ձࣾ#ձࣾ#ձࣾ$Where句を指定忘れてしまうと4&-&$5'30.VTFSTͪΖΜશͯͷձࣾͷϝϯόʔใ͕औΕͯ͠·͏
開発確認フロー•実装のレビューを2⼈以上必ず⾒る•モック化してテスト•QAによる確認 上記を⾏なっているが複雑になってくると指定を絶対に忘れないとは限らない。
PostgreSQLのRowLevelSecurity• データベーステーブル内の⾏へのアクセスを制御することで、このdata violationを防ぐことができる。• 詳細は「マルチテナント 銀の弾丸」でググってください(今年のBuildersconで話しました)
HELPページの仕様• カテゴリーごとに記事を投稿できる• 任意のキーワードで記事本⽂検索できる• 関連記事を登録できる• エンジニアいらず(リリース作業いらず)で記事の更新が⾏える• 弊社のサービスにログインしている⼈だけに⾒える• 公開しないのでSEOは考慮しなくて良い• リリース後の記事の更新頻度は週に1回程度の予定
HELPページの構成①→ Front Matter → Marked →contents/*.md contents.json--- id: 1 title:ヘルプページの作り⽅category: help --- ## はじめに { "attributes": { "id": 1, "title": "ヘルプページの作り⽅","category": "help" }, "body": "## はじめに¥n " }{ "id": 1, "title": "ヘルプページの作り⽅","category": "help", “body": "はじめに " }[{ "id": 1, "title": "ヘルプページの作り⽅","category": "help", “body": "はじめに " }, ]
HELPページの構成②• NuxtJSを利⽤• ①でできたcontents.jsonを⾷わせて、nuxt generateする• contents.jsonはNustのbuild:beforeのタイミングで⽣成させう
Netlify CMS• Headless CMS• サーバーを持たないStaticなアプリケーション• Githubをbackendに指定した場合にGithubのアカウントでログインし、GithubのAPIを叩きMarkdownや画像の書き込みを⾏う• 権限管理⾃体はGithubに準ずる• GithubのGUIをCMS向けに改造しただけのため、データはGithubに⼀元化される。
HELPページの構成③1.$4 /FUMJGZ$.4 PO/FUMJGZ(JU)VC $JSDMF$*%FQMPZFE&OHJOFFS /VYUPush content/*.mdnuxt generatePush
⽬標管理クラウドで良かったこと• ⽐較的安全にマルチテナントを作成できた• フロントエンドも型は⼤事• Netlify/Sentryがすごく便利• docker-compose upだけすればlocal動いて簡単(外部サービスをMock化)• サブプロダクト(LP/Help)のJAM Stackがイケてる
⽬標管理クラウドで気づいた課題• ドキュメントが全然運⽤されない• 仕様が複雑で新しく⼊ってきた⼈のオンボードが⼤変• SQLのマイグレーションFileでコンフリクトが⼤量発⽣する(goose)• フロントエンドも型は⼤事(最初からstrictにしておけばよかった)
⼈事DBについて
⼈事DBを作るにあたって• ⽬標管理クラウドで得た課題を解決しつつ作るべく⾊々考えていきました。
ユビキタス⾔語集• DDDに習ってユビキタス⾔語集を作成。• 英語もあらかじめ定義することによって表記揺れが減りました。
開発合宿@館⼭• ⼀泊⼆⽇で開発合宿を実施• 通常の業務を極⼒忘れて、⼈事DBのモデリングをサーバチーム⾏なった。
DDDとCQRS• DDDとCQRSのエッセンスを取り⼊れた開発• ドメインモデルに業務知識を凝集し、QueryとCommandを分けて実装
⼈事DBのシステム概要• Go• TypeScript(strict)• React• GraphQL• gRPC• sqldef• PostgreSQL
Schema駆動開発schema.graphqlgqlgenίʔυࣗಈੜResolverҎԼΛ࣮͢Δgraphql-codegenίʔυ/TSͷܕΛࣗಈੜͦΕΒΛͬͯը໘࡞
Schema駆動開発• メンテナンスのされなくなりがちなドキュメントがSchemaの受け渡しだけで可能に• 型が⾃動で共通化されるので安全• 無駄なHTTPリクエストを減らせることになるので嬉しい(GraphQL)
sqldef• SQLで羃等にDBスキーマ管理ができるツール• schema.sqlとdbの状態を⽐較してよしなにALTERしてくれる• PostgreSQLアンカンファレンスで話しているので詳細はこちら
マイクロサービス化
マイクロサービス• 1サービスの役割が明確になることによって、メンテナブルにしたい• 組織が拡⼤するにあたって技術的な責務を分けたい。• ユーザー情報や認証など共通化していきたい。
API GateWayاۀ" اۀ# اۀ$ඪධՁཧ Front ਓࣄDB FrontೝূඪධՁཧ API ਓࣄDB APIϩάΠϯը໘REST API GraphQL TwirpREST API GraphQLgRPCgRPC gRPCgRPC
マイクロサービスのルール• プロダクト間の直接のやり取りはしない• 内部のやり取りは基本的にgRPC• APIは全てAPI Gatewayを経由する
API Gatewayと認証・認可• Goで全て実装• API GatewayはHTTP/1.1だけ使える。• 極⼒プロダクトに依存しない設計• プロダクトが増えてもスケールするようにCloud Firestoreを利⽤
Kubernetes + Istio• マイクロサービスにしていくにあたってサービス間のネットワーク管理やスケールが容易である• デプロイフローを⼀元化しやすい
GCP移⾏について• なぜAWSに移⾏するのか• Kubernetesを使うにあたってGKEが使いやすい• Kubernetes使う上でのデファクトスタンダードである• 安い/ダッシュボードが標準/ログがいい感じ
⽬標評価管理のGCP移⾏• 年末は第⼀弾として⽬標評価管理ツールの移⾏を⾏う• アプリケーションはもともとDockerで動いていたので細かい⼿直しのみ• DBも移管も⾏う• 深夜にメンテナンスに振る(ご迷惑おかけします。)
Infra as a Code• Terraformで全てのInfraをGithub上で管理している(Kubernetesも含めて)• ⼿作業の運⽤を減らすことができ安全に
インフラで利⽤しているもの/概念• GCP• Kubernetes• Istio• Helm• Kustomize• Flux/Flagger• Terraform• GitOps
HRBrain UI Library• 各サービスで共通で使うボタンやDatepickerなどを提供するReactのComponent集• Storybookで管理していてプロダクトからimportして利⽤する。• デザイナーがSketchでカタログを作成。• 外部正式公開予定
HRBrain SDK• 各プロダクトで共通で使うモジュールのライブラリ• HRBrain UI Libraryと異なりHRBrain固有のもの• 例えばプロダクト⼀覧を出すパネルなど• マイクロフロントエンドの第⼀弾?
HRBrain SDKの技術• Web Component• TypeScript• SkateJS(with lit-html)• Lit ElementでやりたかったけどIE11で上⼿く動かせなかった。 (Vanilla Web Componentでもいいかも)• jsを読み込めばのタグが使えるようになる
総括• 2019年は昨年仕込み続けていたサービスリニューアルをリリースと、MonolithicなサービスからMicroServiceへと進化をするための仕込み期間でした。• 2020年は複数のサービスが同時に動き出すことにより慌ただしく楽しい1年になるかと思います。
全 職 種 積 極 募 集 中 ! !