Slide 1

Slide 1 text

Platform Engineering Kaigi 2026 認知負荷を吸収し、 プロダクトをまたぐ PR Preview基盤の設計事例 Taiki Ono, Principal Software Engineer ―1

Slide 2

Slide 2 text

導⼊ -2

Slide 3

Slide 3 text

PRプレビューとは ● 解決したい問題 ○ Pull Requestのレビュー量増加問題 ○ フィードバックサイクルのシフトレフト ○ 開発者の多様化 ● ユーザージャーニー ○ PR作成と同時にプレビュー作成 ○ プレビュー毎の専⽤URLからアクセス ○ PRマージでプレビュー削除 ―3

Slide 4

Slide 4 text

enechainでの現況 ● あるプロダクトチームが先⾏して開発 ○ 社内での価値検証が済んでいてプラットフォーム機能としてニーズが⾼かった ● 全社で利⽤できるプラットフォーム機能として開発‧運⽤中 ○ 2⽉に設計開始、3⽉末から導⼊開始 ○ 社内の最も開発が活発なプロダクト‧最も複雑な構成のプロダクトでも導⼊済み ○ 実際に社内で積極的に使われている ○ 技術的な詳細はTech Blog記事へ ■ https://techblog.enechain.com/entry/intro-prothea ―4

Slide 5

Slide 5 text

enechainのテクノロジースタック GKE Cluster Manifest Repo ArgoCD Product Namespace Frontend Browser BFF Backend API ―5

Slide 6

Slide 6 text

グランドデザイン -6

Slide 7

Slide 7 text

解決策の⽅向性 ● マニフェスト⽣成⽅式 ○ プレビュー⽤のマニフェストファイルを⽣成してArgoCDなどでクラスタに適⽤ ● クラスタ内で複製する⽅式 ○ マニフェストファイルは変更せずクラスタ内で直接プレビューリソースを作成 どちらを選択するべきか?→ プラットフォームでなにを解決したいのか? ―7

Slide 8

Slide 8 text

認知負荷の分解 ● 本質的な負荷 ○ ドメインから由来する問題そのものの難しさ ● ⾮本質的な負荷 ○ やり⽅‧環境から来る負荷 ● 価値を⽣む負荷 ○ プロダクトを良くする思考 ―8

Slide 9

Slide 9 text

プラットフォームと複雑性 ● 認知負荷は消えない、プラットフォームが吸収する ● つまり、複雑性はプロダクト開発からプラットフォームへ移る ● ここにトレードオフが存在する ○ 認知負荷を吸収していくと、プラットフォームを複雑にする⼒が働く ―9

Slide 10

Slide 10 text

トレードオフを破る⼒学 ● 認知負荷のコストも認知負荷削減のリターンもどちらも積み上がって効く ○ プラットフォームの構築は⼤きな初期コストと⼩さな継続的コスト ○ ⽣まれた余剰リソースを改善に投資するサイクルが回ると指数的に状況が変わり得る ● ソフトウェアエンジニアリングのパワー ○ 複雑な問題をシンプルに解ける可能性がある ○ 認知負荷の低いプロダクト開発とシンプルなプラットフォーム これらを踏まえた上で⾃分たちの状況で意思決定することが⼤事 ― 10

Slide 11

Slide 11 text

今回の我々の意思決定 ● マニフェスト⽣成⽅式 ○ プレビュー⽤のマニフェストファイルを⽣成してArgoCDなどでクラスタに適⽤ ● ✅ クラスタ内で複製する⽅式 ○ マニフェストファイルは変更せずクラスタ内で直接プレビューリソースを作成 ― 11

Slide 12

Slide 12 text

設計 - 12

Slide 13

Slide 13 text

概要 Dev Cluster GitHub Clone Manifest Repo prothea webhookserver controller Webhook Product Repo PR Create Watch Read Product Namespace Push Product Developer Preview Request Reconcile Preview Configuration Preview Environment ― 13

Slide 14

Slide 14 text

プレビューリソースの作成 Dev Cluster GitHub Clone Manifest Repo prothea webhookserver controller Webhook Product Repo PR Create Watch Read Product Namespace Push Product Developer Preview Request Reconcile Preview Configuration Preview Environment ― 14

Slide 15

Slide 15 text

ベースマニフェストを変更しない ● Kubernetesのマニフェストは素の状態でも認知負荷が⾼め ○ プラットフォームによる抽象化の過渡期なので開発者が認知する必要がある ● さらにkustomizeなどでテンプレート化されていて複雑 ● ここからプレビューリソース層を追加するかどうか ○ プレビュー⽤の規約は業界標準ではなく社内独⾃ → 複数の概念を混ぜた状態は避ける 特に社内独⾃規約が混ざると複雑度が増しやすい ― 15

Slide 16

Slide 16 text

プレビュー環境の設定 Dev Cluster GitHub Clone Manifest Repo prothea webhookserver controller Webhook Product Repo PR Create Watch Read Product Namespace Push Product Developer Preview Request Reconcile Preview Configuration Preview Environment ― 16

Slide 17

Slide 17 text

設定⽤カスタムリソース 設定は基本的な紐付け情報のみ プロダクトによる構成の違いを どう吸収しているか? ― 17

Slide 18

Slide 18 text

プレビュー構成の導出 Dev Cluster GitHub Clone Manifest Repo prothea webhookserver controller Create / Read Webhook Product Repo PR Create Watch Read Derived Preview Configuration Product Namespace Push Product Developer Preview Request Reconcile Preview Configuration Preview Environment ― 18

Slide 19

Slide 19 text

導出した結果を⾒せるリソース ● 複製するアプリケーションの⼀覧 ○ Deployment、Service、アプリのコンテナ名、取り除くPodラベルなど ● プレビューへのアクセス経路 ○ ドメイン名、Gateway / IngressとそのHTTPRoute ○ プレビューURLの元 ○ プレビュー⽤の共有インフラの設定 ○ 詳細は後述 ● 共有インフラのセットアップ結果 プロダクト開発者‧プラットフォーム運⽤者⽤の中間情報 ― 19

Slide 20

Slide 20 text

プラットフォームのインタフェース ● なるべくプラットフォームでカバーする ○ 🙅 ドキュメントやCLI⽣成を利⽤して細かい設定を開発者が書く‧確認する ○ 🙅 プラットフォームがなにをする‧したのかがわからない ○ 🙅 異常ケースではプラットフォームのログを読ませる ● シンプルな規約に収める ● 設定変更でなにが変わるのか‧なにが起きるのかを予⾒させる ○ CIでのシフトレフト ● ⽇常的に使わない部分は隠して段階的インタフェースを⽤意する ○ 今回だとカスタムリソースとして⾒せる ― 20

Slide 21

Slide 21 text

透過的ネットワーク - 21

Slide 22

Slide 22 text

プレビュー環境への⼊⼝ Dev Cluster GitHub Clone Manifest Repo prothea webhookserver controller Webhook Create Product Repo PR Watch Read Product Namespace Preview Request Push Product Developer Open URL Reconcile Preview Configuration Preview Environment ― 22

Slide 23

Slide 23 text

ベース環境とは独⽴したルーティング経路 Product Namespace Base Environment example.com Browser GKE Gateway / Ingress pr-123.example.com preview-gateway PR-123 Preview *.example.com PR-456 Preview pr-456.example.com ― 23

Slide 24

Slide 24 text

特殊な構成もプラットフォームが吸収 Parent Product Namespace / GKE Gateway preview-gateway Preview Environment /sub Browser Sub Product Namespace preview-gateway Preview Environment ― 24

Slide 25

Slide 25 text

サービス間の通信 Default HTTPRoute Default HTTPRoute Base Backend API Base Core API Per-Preview HTTPRoute Per-Preview HTTPRoute Preview Backend API Preview Core API Inject preview-id header Gateway HTTP Request with preview-id header pr-123.example.com BFF Browser With GAMMA (Gateway API for Service Mesh) HTTP Request with preview-id header ― 25

Slide 26

Slide 26 text

境界設計 - 26

Slide 27

Slide 27 text

アプリケーションとの境界設計 ● プレビュー⽤のコンテナイメージのビルド ○ 社内共通ビルドワークフロー向けのビルド後のフックを⽤意 ● フロントエンドの向き先解決 ○ セットアップ⼿順に含める (いい解決策が思いつかなかった) ● Cross-Origin Resource Sharing対応 ○ 後述 ― 27

Slide 28

Slide 28 text

Cross-Origin Resource Sharing ● プレビュー環境ではドメイン名が変わることは本来プラットフォームの関⼼事 ○ preview-gatewayでpreflightに応答したい ○ アプリケーションには変更を⼊れないようにしたい ● 合理的に引き受けられない場合はアプリケーション側に戻す選択もある ○ credentialなリクエストでの任意ヘッダー許可がIstioでできない問題 ○ アプリケーション側では1⾏の変更で済む ― 28

Slide 29

Slide 29 text

開発者体験 - 29

Slide 30

Slide 30 text

より良い開発者体験 ● ノイズにならないUIを作る ○ 今回だとGitHub Deployments API ● 開発者のミスをケアする ○ 起動しないコンテナなど ○ 異常系で丁寧にフィードバックを返す ● ⼀段奥に調査⽤の情報を整理して置く ○ 今回だとCRDとそのStatus ― 30

Slide 31

Slide 31 text

より良い開発者体験のために ● 複雑性を引き受けられるプラットフォームの技術選定 ○ 複雑なことをシンプルに実現する必要がある ● Platform as Productの実践 ○ 開発者の⾏動を観察‧計測‧分析する ■ ○ 「顧客はほしいものがわからない」原則 ドッグフーディング ― 31

Slide 32

Slide 32 text

終わりに - 32

Slide 33

Slide 33 text

まとめ ● 複雑性をどこに置くか? ○ トレードオフを考えた上で意思決定 ● 認知負荷を吸収するプラットフォーム ○ 必要な複雑性を引き受けられる技術選定 ■ 時には境界を引き直す ○ 既存の概念を混ぜない ○ インタフェースに注⼒する ■ Platform as Product ― 33