🐕

Offers 技術組織の課題 a.k.a 誰か手伝ってリスト - バックエンドと DevOps編 | Offers Tech Blog

2022/07/07に公開

こんにちは、Offers を運営している株式会社 overflow CTO の 大谷旅人 です。

Offers を正式リリースしてもうすぐ 3 年。コードベースの増加とともに取り組む必要のある多くの技術課題が存在するようになってきました。

そこで、今回は進行中または予定のプロジェクトを具体的な課題とともに開示し、技術組織としてどのような事に取り組んでいるかを書いてみます。

バックエンド - 過渡期な Ruby/Rails スタックの磨き上げ

GraphQL APIへの全面移行

Open APIでスキーマ駆動開発 を行っていますが、コードベースや対応メンバーが増えるにつれいくつか管理上の問題が発生しています。

  • Backend/Frontend の境界部分
    • API ドキュメント/スキーマ管理の課題
      • YAML 巨大化に伴うコンフリクトの発生頻度
      • $ref 生成がつらい
      • 謎の OpenAPI Generator エラー
  • Backend
    • JSON 出力用の処理が大量生成されている
      • フロントエンドから要求によってエンドポイントごとに細かいカスタマイズ入るなど Serializer 処理が複雑化していく
      • 共通で使用されているものを変更した際に、N+1 が発生したりと余分な確認工数を取ってしまっている
    • オーバーフェッチ問題
      • Serializer の共通使用等を起因として、過分なデータが出力されてしまっている
      • 不足分はテストでチェックしているが、過分に追加されてしまう

スキーマ管理の問題は中間ファイル構造を見直すことで対応できそうですが、API への要求に対して柔軟な対応をするにも限度があるという出力処理の問題は解決が難しく、私達のユースケースには合わなくなってきていました。

これらを解消するためにはバックエンドの主な関心をスキーマ設計に集約でき、オーバーフェッチやクライアントサイド要求への対応はフロントエンド主導でフィールド定義の合意形成が可能になる GraphQL がベストと判断し、サービス全体での移行を進行中です。

もちろん導入によってすべてが解決する銀の弾丸ではありません。Schema Driven Development をどのように開発フローに定着化させるのか、我々のチームにおいて進行段階のどこで定義の合意を取れば手戻りなく開発できるのかなど足並み揃えつつ進めています。

モノリシックなコードベースを複数のモジュールに分けるリファクタリング

モノリシックなリポジトリに API(GraphQL)、3rd Party からのデータ取得、メディアサイト用構成、バッチ処理やらが混在しています。

そのため、一部変更するにも全体リリースが必要となってしまってる状況を改善しようと、順次モジュールへと切り出しを進めていってます。

また、Ruby/Rails 資産を必要としないデータ処理などでは、ポータビリティを考えて Go でのリプレイスも予定しています。[1]
いきなり大規模なリプレイスを予定しているわけではなく、役割を考えて適材適所で進めていくのでまだまだこれからです。レイヤー設計などに知見ある方の参画を求めています。
とりあえず話を聞いてみたい!という方はぜひ カジュアル面談 よろしくお願いします。

認証、認可基盤の独立/マイクロサービス化

Offers 以外の新しいサービスも展開するにつれて認証、認可をサービス共通で管理できるよう、独立した基盤が求められるようになってきました。この問題への解決方法としては

  • SSO 作るか使う
  • 共有ストア管理
  • トークン管理(JWT)

などがあります。現在は、共通ストア管理となっていて情報を切り離してはいますが、今後は API 層のルーティング含めて構成できるよう独立したサービスとして実装と運用が必要になる機運が高まっています。

Ruby/Rails に静的解析導入

https://zenn.dev/offers/articles/20220509-ruby3-type-interpretation

まだまだ試行錯誤中ですが、静的解析は品質だけでなくレビュー精度も上がるため導入コストかけて損がなくむしろ最適。導入タスケテください。

サービス分析と PDCA サイクルの刷新

サービスの分析には今まで Redash を使用してきました。
アドホックな状況分析や、ダッシュボードによる指標可視化を行っており、クエリの総数は 2,000 個ほどもあります。

そして、これだけクエリ数が多いと以下の課題もあり

  • 同じような SQL クエリが乱立
  • テーブル構造の変更に追従できずダッシュボードが意図せず破損する
  • テーブル増加に比例して正しい分析するための知識習得にも時間かかる
  • 謎に増えるスケジュール実行クエリ
  • 分析データを使用したアクションが見えない
    • API 経由でデータ取得されていたりと何に使われてるのか分からない
    • 下手に変更できないので同じようなクエリ増殖

全部まとめて解決しようと Looker を導入し、モデリング言語を整備することでビジネスサイド含めて誰もが容易に分析できるような環境づくりを進めています。
そもそものサービスデータ構造にも課題はあるため、分析しやすいデータ構造にするための見直しもしています。

テストカバレッジと実行速度の向上

カバレッジが 87%と微妙に全体をカバーできてないので、地道にカバレッジを上げていますが、開発スケジュールも踏まえると未カバー部分のテストを一気に書くというのは中々難しいところです。
そして、同時にテスト実行にかかる時間の増加と、比例して伸びる CI/CD 時間の課題もあるため頑張りが必要です。

Infra/DevOps - 持続可能な開発と運用を目指して

リリースマネジメント

基本的な GitOps によるデプロイフローや CD 環境、e2e のスモークテストはあります。
Production リリース時はスムーズにいきますが、実際には以下の流れがその前にあり

  1. PR 毎に検証環境へリリース
  2. Issuer と開発者が確認
  3. チェック完了したら Production リリースフローへ

各 Step が JIRA や Github に散らばっていてイマイチ統一感がありません。
ワークフローをもっと視覚化したいと考えています。

イメージ
Amplifyでのステータス表示に関連Step追加されるといいなのイメージ

プロビジョニング/IaC

検証環境や新規プロジェクトでは IaC(Terraform)管理で、インフラのコード化と再現性を担保しています。
再現性という点だと、モニタリングや監視(by Datadog)、Github などの構成も含めて管理しておきたいところです。
完全に IaC 管理するのは無理があるので、再利用頻度や構築難易度、レビューしたいかどうかを判断しコスパを踏まえて進めています。

デリバリーリスク低減と信頼性の担保

SRE 課題とも言えますが、DevOps にも包含されるものとして下記のような課題を抱えています。

  • ソフトウェアテストが整備し切れてない
    • スモークテスト (by Datadog Synthetic Monitoring) もすべては網羅できていない
  • Canary Release を可能にしたい
    • Dark Canary Release はできるが、限定されたチェックだと保証としては弱い
  • Feature Toggle 運用を始めたい
    • ConfigCat 等の SaaS を利用する?
  • スケーリングおよびパフォーマンス要件のテスト

インシデント管理と MTTR 削減

  • ワークロード自体の設計
    • バルクヘッドアーキテクチャとか
      • リクエスト、アカウント単位のサブセットで区画管理
      • 伸縮性、弾⼒性をもうちょいどうにかしたい
  • 障害時の連絡および対応体制などが整備不足
    • 意思決定フローなども
    • ポストモーテム運用

継続的フィードバック

システム運用のメトリクスだけでなく、以下のようなサービス運用に関わるフィードバックをメトリクスとして収集&測定して改善のためのリリース計画や、テスト計画を作成する流れを取りたいと考えています。

  • NPS, アンケート
  • バグレポート, サポートチケット
  • ツイート数

DX(Developer eXperience)/開発環境整備

  • ローカル環境が遅い、メモリ食い過ぎ
    • VirtioFS 有効にしたら劇的に早くなったがまだまだ (thanks Redhat の方)
    • メモリも食いすぎている
  • DockerCompose ファイルのバージョンが 2.x と古い
    • v3 にて廃止されている記述もある
    • 非推奨となる前にアップデートする必要がある
  • 軽量な Frontend 開発環境
    • webpack をはじめとしたビルド 〜 CI/CD 周辺

あとがき

きれいなこともあれば、負債もあるのが現状です。
見栄を張ってピカピカな様子を見せるよりも、汗かきながらサービスという大事な資産の維持(と、われらのかんがえたさいきょうのかいはつ)のために地道に改善を繰り返している様子が伝われば本望です。そしてそれは非常にチャレンジングな取り組みです。

書いていたら異常に膨れ上がってしまい、このあと

  • Frontend 編
  • SRE & DevSecOps/Security 編
  • DataEngineering & 社内 IT 戦略編

と続きます。

関連情報

もっと詳しく聞いてみたい!と思った方はぜひ カジュアル面談 しましょう。Podcast では弊社の技術チャレンジである「HR のデジタル化」についても語っています。

https://open.spotify.com/episode/4SxOcLXuxSUPVODeb2Axro
https://zenn.dev/offers/articles/20220714-develop-issues-part3
https://zenn.dev/offers/articles/20220711-develop-issues-part2

脚注
  1. 個人で使うには Rust 推しで、0.1 時代から 使っている くらい好きなのですが、チーム開発および体制づくりとかツールチェーン状況とかを踏まえるとなかなかに選択するの二の足を踏むよねっていう思い ↩︎

Offers Tech Blog

Discussion