Kubernetes Meetup Tokyo #14 における発表です https://k8sjp.connpass.com/event/104450/
Quipper のマイクロサービス化への道のり@yuya-takeyama
View Slide
➔ 技術的にエッジな話は少なめかも...➔ 本番運用にまつわる泥臭い話多め今日話すこと
0102030405Agenda | 自己紹介Quipper の紹介Kubernetes への移行Kubernetes の運用Microservices 化への道のり
01 自己紹介
@yuya-takeyama➔ 2015年9月~: Web Developer at Quipper◆ Rails/Backone.js/React.js/React Native などなど➔ 2018年4月~: SRE at Quipper◆ Kubernetes への移行や Kubernetes の運用およびその効率化◆ Kubernetes 環境への移行に向けた開発者のサポートもミッション◆ インフラ・SRE としてはまだまだ修行中
@yuya-takeyama➔ 好きな言語は Ruby, Go, TypeScript◆ Elixir を勉強中, Rust は挫折気味
02 Quipper の紹介
Quipper のプロダクト➔ Quipper◆ フィリピン、インドネシア、メキシコ、日本で展開する教育サービス◆ 先生は宿題を出せて、生徒が問題を解くとその進捗が管理できる➔ スタディサプリ◆ 基本的に機能は Quipper と同じだが、日本ではスタディサプリというブランドでやっている◆ かつての受験サプリ。2016 年にリブランディング◆ 日本では「神授業」の CM でおなじみ◆ 漫画「ドラゴン桜2」にも登場
Quipper とスタディサプリ➔ ソースコード的にはほぼ同一◆ 環境変数等のフラグでスタイルや機能の出しわけが行われている◆ AWS のアカウント自体別で、別々のリージョンにデプロイ
Quipper SRE チームの紹介➔ メンバー◆ 東京 3 名 (うち 1 名は Web Developer からのコンバート (私です))◆ マニラ 1 名 (Web Developer からのコンバート)◆ ロンドン 1 名 @masatomo (CTO/Engineering Manager)➔ 役割◆ Quipper のインフラに関わることは基本的に全て◆ インフラ・クラウド周りのコスト管理、セキュリティ等
Quipper SRE チームの紹介➔ ツール◆ 基本的にあらゆるリソースが GitHub 上でコード化されている◆ Pull Request でのレビュー、マージによるデプロイがかなり徹底されている◆ Ansible/Ansible Tower/Terraform/CircleCI/Codenize.tools
03 Kubernetes への移行
Quipper における Kubernetes 移行の位置づけ➔ CTO の @masatomo がトップダウンで始めたプロジェクト◆ 開発者への共有を GitHub Issues やオフライン・オフラインのセッションを行いフィードバックを集めながら◆ 現在はプラットフォームとしては CTO を含む SRE が中心となって進めている➔ とりあえず既存のアプリケーションを Deis から Kubernetes にそのまま移行◆ Deis: OSS の Heroku クローン的なやつ
Quipper における Kubernetes 移行の位置づけ➔ Microservices 基盤としての移行ではあるが、Microservices 化はこれから➔ Kubernetes への移行が完了してからが本番!◆ Microservices 化◆ それに伴う様々な権限の開発者への移譲◆ リソースや運用の最適化◆ 様々な技術的チャレンジ
Quipper とスタディサプリのインフラの変遷➔ Quipper◆ 2012(?)年~: Heroku◆ 2018年2月~: Deis Workflow (Deis v2 にあたる)◆ 2018年8月~: Kubernetes (本番も含めて移行済み、絶賛運用中)➔ スタディサプリ◆ 2016年2月~: Deis v1◆ 2018年11月(?)~: Kubernetes (ステージングを移行中、本番も今月中)
Deis から Kubernetes へ移行する/した理由➔ Deis が既にメンテ終了!!! (2018年3月)◆ Quipper の Heroku -> Deis Workflow の移行計画は 2017 年 3 月から進んでいた◆ 同じく 2017 年時点で Microservices 基盤としての Kubernetes の検証もCTO による R&D プロジェクトとして平行して進んでいた◆ 結果的に Deis Workflow EOL 直前というタイミングでの Deis Workflow 環境のリリースになってしまった...◆ Deis v1 (非 Kubernetes) からいきなり移行するのに比べれば、段階的移行としての意味は十分あったと言える
Deis から Kubernetes へ移行する/した理由➔ Deis Workflow を使い続けるメリット自体薄いという判断◆ Hephy という fork による後続プロジェクトも存在◆ Deis Workflow は事実上 Kubernetes の超薄いラッパー➔ Microservices をやる上では機能的に足りない◆ リソース等含めた細かいコントロール・コード化◆ アプリケーション単体ではなく集合としての管理
移行の流れ➔ 基本的にはガッツと根性!そして粛々やり続けるだけ➔ Dockerfile を書く◆ 元が Heroku Buildpack なので変わったイメージはそんなにない◆ Twelve-Factor App なのでアーキテクチャ的に変なやつも基本ない➔ 環境変数を ConfigMap に切り出し➔ 先にテスト用のドメインを別途 Reverse Proxy に追加して確認する➔ 前段にある Reverse Proxy で Deis から Kubernetes にひとつずつスイッチ
Monorepo への移行➔ Quipper における現役のサービスのほぼ全てを含む巨大な単一リポジトリ➔ Web Developer の @mtsmfm の意見を元に CTO が実現➔ 元は個別リポジトリだったものを git subtree add でインポートしていった◆ 便宜上元の個別のリポジトリを classic repos と呼んでいる
Monorepo への移行➔ 現状は Quipper は Monorepo で完結、移行が完了していないスタディサプリはclassic repos で開発中➔ Classic repos で行った変更は日次で monorepo に同期◆ git subtree pull を全サービスに対して実行◆ Jenkins Job から Pull Request が作られ、マージすると同期が完了➔ Monorepo -> classic repos への同期はなんかうまくいかないのでできていない➔ どうせ移行が完了したら monorepo に一本化するので放置
04 Kubernetes の運用
方針➔ できる限り全てを GitHub リポジトリで管理◆ Pull Request ベースのレビュー◆ マージによるデプロイ (CircleCI)➔ 大きなツールやミドルウェアの導入は本当に必要になるまで控える◆ manifest は基本 YAML + kustomize● Datadog Agent のようなカスタマイズがそんなにないものは Helm◆ 負債化を避けるため (バランスは難しい)
方針➔ 移行をやりきるまでは移行に集中!◆ 現状は割とコスト度外視でじゃぶじゃぶ Node を投入している状態...
リポジトリ➔ quipper/kubernetes-clusters◆ kube-aws で生成したクラスタ定義ファイル (CloudFormation の StackTemplate 等も含む)◆ Quipper 用、スタディサプリ用、それぞれのステージング・本番、それらの複数世代◆ Deis 用のものも現状含まれている (もうすぐ消せる)◆ 基本的に SRE のみでメンテナンス (Pull Request は誰でもウェルカム)
リポジトリ➔ quipper/kubernetes-clusters◆ Jaeger や Datadog Agent のような各クラスタで共通となるコンポーネントのmanifest● 素の YAML, Helm, kustomize, envsubst◆ それらを CD するためのデプロイスクリプト (Bash)◆ Pull Request ベースでクラスタの構築や manifest の apply が行える
リポジトリ➔ quipper/monorepo◆ 前述の「Quipper における現役のサービスのほぼ全てを含む巨大な単一リポジトリ」◆ 基盤としては SRE が中心に構築しているが、中での開発は全ての開発者で行っていく● Dockerfile/Kubernetes manifest 等は GitHub の CODEOWNERS により SRE のレビューを必須とする
リポジトリ➔ quipper/monorepo◆ Dockerfile◆ 各サービスの Kubernetes manifest 及び kustomize overlays◆ それらを Pull Request ベースで CI/CD するためのデプロイスクリプト(Bash)
リポジトリ➔ その他にも Ansible/Terraform/Codenize.tools 等のためのリポジトリがそれぞれ存在
クラスタ内のアプリケーションの配置➔ 本番クラスタ◆ 基本全サービスが単一の production Namespace 内に存在◆ production 内には service-router と呼ばれるコンポーネントも存在● 中身はただの Nginx● 各サービスのアプリレイヤに近い部分の Reverse Proxy 的役割● これまで SRE がメンテしてきた Reverse Proxy (Kubernetes 外) の一部を切り出して Web Developer に移譲していくため
クラスタ内のアプリケーションの配置➔ ステージングクラスタ◆ Develop, release, pr-*** といった複数の Namespace 内に、全サービスがそれぞれ存在● これらを便宜上 Service Environment と呼ぶ (Quipper 独自の用語)● develop: devlop ブランチをデプロイする環境● release: release` ブランチをデプロイするリリーステスト環境● pr-***: Pull Request を作るたびに作られるステージング環境
クラスタ内のアプリケーションの配置➔ ステージングクラスタ◆ branch-router というコンポーネントが branch-router Namespace に◆ URL を元に適切な Service Environment の Namespace 内のservice-router に橋渡し◆ これも中身はただの Nginx● service-router から先は本番クラスタとほぼ変わらない◆ Jaeger や Datadog Agent 等のコンポーネントについても本番クラスタと同様
クラスタのアップグレード➔ 実は現状ほぼできていない (!!)➔ ようやくアップグレードのための仕組み・運用方針が今週 (!!) 出来上がったところ◆ クラスタ毎に kube-aws のバージョンを変えて CD する仕組み◆ クラスタに世代の概念を導入し、複数世代を並行して構築・デプロイ
クラスタのアップグレード➔ クラスタの世代◆ クラスタ名の末尾に 01, 02 といった連番を付加◆ クラスタ名の例: quipper-staging◆ 世代番号を含む完全クラスタ名の例: quipper-staging-01➔ サービスごとに前段の Reverse Proxy から切り替えたりする予定
現状の課題➔ クラスタの継続的アップグレード➔ Audit ありで Rails Console を解放するための仕組み (heroku run 的な)➔ CI/CD パイプラインの改善◆ デプロイスクリプト壊れやすい問題◆ Spinnaker?◆ 秘密情報の管理の改善
現状の課題➔ リソースの最適化 (特にステージング)◆ オートスケーリング◆ ステージングデプロイ時、変更のないサービスは develop Namespace にForward➔ Service Mesh◆ Observability の向上、認証・認可、Canary Release、Circuit Breaker、Fault Injection などなど...
@mumoshu (Yusuke Kuoka) さんが Technical Advisor に!➔ kube-aws をはじめとした、Kubernetes エコシステムの数多くのOSSに貢献➔ 世界に 5 人、日本に 1 人しかいない AWS Container Heroes の 1 人➔ Kubernetes に関するあらゆることの相談、議論、レビュー➔ Quipper では珍しい副業という関わり方でバリューを出してもらっている
@mumoshu (Yusuke Kuoka) さんが Technical Advisor に!➔ とはいえまだまだ深いところを議論していきたい!という話をご本人ともしている◆ まずは移行を終わらせて時間と余裕を確保しなくては...
05 Microservices 化への道のり
組織構成➔ Service Unit◆ 主にビジネスごとに分割されたチーム (B2C, B2B2C, 拠点ごとのビジネス)◆ Service Owner (= mini CEO), Product Manager, Developer, Designer◆ Service Unit ごとに裁量を持つ➔ Technical Project◆ Data Restructure (データ処理基盤)
組織構成➔ 現状は結局それぞれのチームが共通のコードベースをさわっている◆ 分断されたモノリス
分断されたモノリス➔ Quipper VPoE の @kyanny が Rails Developers Meetup 2018 において提唱した概念◆ Quipperにおける「関心の分離」の歴史https://docs.google.com/presentation/d/1ZNDGuDQGbq2TliUukExUmUicKUJXjWejBD2zd_E8SFU/edit#slide=id.g357c6cbf64_0_63
分断されたモノリス➔ 用途毎に (マイクロではない) サービスに分割されてはいるが...◆ 学習者用サービス、先生用サービス、コンテンツ制作者用サービス、カスタマーサポート用サービス...➔ データベースは基本的に単一の巨大な MongoDB にそれぞれのサービスが依存している◆ データベースを抽象化するモデル層も同様 (private な gem になっている)➔ 分割が適切でないため、技術的負債および組織的課題となっている
Microservices 化の状況➔ Kubernetes 移行と同時に実験的にいくつかのサービスの切り出しを行った◆ grpc-ruby による Microservices と、それを集約する API Frontend (Rails)◆ 一部の API を新旧両方のレスポンスを比較しつつ移行◆ GitHub の Scientist を用いて結果を比較、データベースに残してダッシュボードで見える化
Microservices 化の状況➔ Kubernetes 移行と並行して進む Technical Project◆ Data Restructure● サービスと分析の双方に信頼性の高い学習データを用意するための処理基盤● Elixir/OTP/Amazon Kinesis/Amazon Aurora◆ Kubernetes 移行として進む新規事業プロジェクト● 前述のマイクロサービスを GraphQL で集約して API として利用
まだまだ採用中➔ Kubernetes や、AWS をはじめとしたパブリッククラウドに強い SRE・インフラエンジニア➔ Microservices やアーキテクチャのスペシャリスト➔ その基盤上で最高の教育サービスを作っていきたい開発者 (Web・モバイル)➔ Twitter で @yuya_takeyama まで DM くれれば話をしたり適切な人に繋いだりします