Upgrade to Pro — share decks privately, control downloads, hide ads and more …

spanner-autoscalerに学ぶ
CRD設計パターン
〜自動化と緊急時対応を両立する...

Avatar for tkuchiki tkuchiki
September 26, 2026

 spanner-autoscalerに学ぶ
CRD設計パターン
〜自動化と緊急時対応を両立する
Kubernetesコントローラーの作り方〜

Avatar for tkuchiki

tkuchiki

September 26, 2026

More Decks by tkuchiki

Other Decks in Technology

Transcript

  1. Cloud Spannerについて • Cloud SpannerはProcessing Units(PU)を無停止で増減できる • 公式のオートスケーラー • cloudspannerecosystem/autoscaler(OSS)

    • Google Cloudのマネージドオートスケーラー • 我々が開発しているオートスケーラー • https://github.com/mercari/spanner-autoscaler spanner-autoscaler
  2. なぜKubernetesコントローラーとして実装したか • Kubernetes上でアプリを運用している • Microservice 200+、Spanner Instance 50+ • SpannerAutoscaler導入率:

    90+% • Deployment などと同じような運用体験を提供 • YAML/CUE で管理できる • 既存のKubernetes用の仕組みを活用できる • Terraform module・CUEによる抽象化で、導入しやすい仕組みを提供 [1][2]
  3. CRDとCR • CustomResourceDefinition(CRD) • Kubernetesに新しい種類のリソース(Kind)を追加する型定義 • 例: 「SpannerAutoscalerという種類のリソース」をapiserverに登録する • CustomResource(CR)

    • CRDで定義された型の実際のインスタンス • kubectl applyで作る対象そのもの • 標準のPod/Deploymentなどと同様、etcdに保存される
  4. 2つのCRD/CRと役割分担 SpannerAutoscaleSchedule • schedule • PUをどのくらい増やすか • statusを持たない • spec.targetResourceで

    SpannerAutoscalerを指定 watch/reconcile SpannerAutoscaler • scaleConfig • minPU, maxPU, ... • scale up/downの間隔 • scale up/downで増減するPU数 ... targetResourceに自分を指定している watch/reconcile SpannerAutoscaleScheduleをwatch Controller • SpannerAutoscaleScheduleの 管理のみ • PUの計算をしない • 外部リソースにアクセスしない Controller • DesiredPUの計算 • 外部リソースへのアクセス • オートスケーリング • 根本的な機能を集約 CPU使用率 UpdateInstance
  5. 各CRDの役割 • SpannerAutoscaler • CPU使用率ベースの自動スケーリング本体 • Spannerの操作が責務 • SpannerAutoscaleSchedule •

    cronによるスケジュールドスケーリング • Spannerの状態は持たない • 役割ごとに分割し、リソース間参照(targetResource)で協調させる • SpannerAutoscaler -(watch)-> SpannerAutoscaleSchedule
  6. OwnerReference方式とscaleTargetRef(targetResource)方式 • OwnerReference方式 • 親が消えたら子も自動でcascade deleteされる • 作成に親のUIDが必要となり、作成順序に制約 • scaleTargetRef(targetResource)方式

    • 正式名称は不明だが HPAでは CrossVersionObjectReference と定義 • 独立して作成・削除することを許容 • 参照先が存在しない時はエラーを返す • 存在チェック・watch・参照先消失時のハンドリングを自分で実装する必要がある
  7. 権限管理: 独自RBAC vs 標準RBAC • ArgoCDのような独自RBAC方式 • 細かい粒度で権限を制御できる • kubectl

    rollout restart deployment の実行だけ許可、といった制御も可能 • 独自の権限モデルを実装・運用する必要があり複雑 • spanner-autoscalerの方式(役割ごとにCRDを分割) • 標準のKubernetes RBAC・Audit Loggingがそのまま使える • 独自の権限モデルの実装・保守が不要 • 細かい粒度で権限を制御できない
  8. Manual Scalingの動作例 PU: 1000 Manual Scaling Controller PU: 4000 Manual

    Scaling Controller Create CR1(minPU:2000) Create CR3 minPU:3000 OK Reject Delete CR2 PU: 2000 OK Create CR2(minPU:4000) PU: 2000 OK PU: 4000 Create CR3(minPU:3000) OK Manual Scaling Controller PU: 3000 Manual Scaling Controller
  9. AIによるオペレーションの可能性 • AIにはcreateのみ許可という制御が、標準のRBACだけで実現可能 • 例: 夜間にスケールアウトイベントが複数回発生、かつ、CPU使用率90% がN分継続している、を条件にアラートをトリガー • アラートのトリガーを条件にAIにスケールアウトさせる •

    オートスケーラーのスケールアウトが間に合っていないと判断 • 実行内容は標準の監査ログに記録されるため追跡が容易 • より堅牢にしたい場合は専用CRDの実装+独自RBACが必要になるかも
  10. 上書き処理の実装Tips • ManualScalingのような「手動上書き」を実装するときの一般化できる 手法 • 2つの望ましい値を比較して大きい方を採用するロジックにしない • 計算が複雑になりがち & テストも増えがち

    • Reconcileの中で有効な上書きがあるかを先に判定し、あればその場で 処理を終了(早期リターン) • 上書きが無い場合だけ、通常のロジックに進む
  11. APIバージョニング(v1alpha1 -> v1beta1) • 既存フィールドの型・意味を変えるなど、後方互換性を保てない変更を行 うときにバージョンを変更する • Hub-and-Spokeモデル • v1beta1をHubに、v1alpha1はHubとの変換だけ持つ(組合せ爆発しない)

    • 新しいバージョンから古いバージョンに戻す変換では、一部の情報が失わ れることを意図的に許容している • 例: パーセント指定のスケールダウンは、旧バージョンでは固定のノード 数に置き換わる
  12. カスタムコントローラーを作る際のテストの選択肢 • client/fakeという「インメモリの疑似クライアント」がある • OpenAPI validationは実行されず、webhookも呼ばれない • Generation/ResourceVersionも正しく振る舞わない • 「When

    in doubt, it's almost always better not to use this package and instead use envtest.」 [4] • もう少し本物に近い検証がしたい場合、kindなどの実クラスタでのe2e testと、envtestがある [4]
  13. 外部システム依存コントローラーのテスト • Spanner/Cloud MonitoringなどのKubernetes外のリソースのテストは自 分で用意する必要がある • 実リソース、エミュレータ、モック • 厳密さ:実リソース >

    エミュレータ > モック • コスト(利用料金・実行速度・計算リソースも含む):実リソース > エミュ レータ > モック • spanner-autoscalerはエミュレータ+モック
  14. 自作エミュレータの機能 現在のPUを保持 固定のCPU使用率を返す UpdateInstance Spanner Controller エミュレータ CPU使用率を5,10,40,... のように PUを取得

    PUを考慮した 返す値を問い合わせごとに変える CPU使用率を返す ↓ Spannerに負荷をかけている状況を再現 Workloadモード シナリオモード Monitoringエミュレータ Staticモード
  15. ValidatingAdmissionPolicy(VAP) • Kubernetes組み込みの検証機構(1.30 GA) • Admission Webhookに対する宣言的・in-processな代替として位置づけられて いる • CELで条件式を書くだけでバリデーションのルールを宣言的に定義できる

    • apiserver内で直接評価されるため、Webhookのような外部プロセス呼び出し が不要で、apiserverが動いていれば実行し続けられる • CELはhost application(apiserver)が渡したデータにしかアクセスできない設計 (non-Turing complete)なので、できることに制約がある
  16. VAPとWebhookの使い分け • VAP • object/oldObjectの比較(Update前後の自分自身、immutable化など) • params/namespaceObject(paramRefで事前に固定したリソース)を使った 形式チェック • Webhook

    • フィールド値に応じて動的に別リソースを参照する(paramRefは静的固定 のため不可) • 現在時刻を参照する(CELの変数に時刻を返すものがない)
  17. spanner-autoscalerを提供することで得られている恩恵 • Platform Engineering/SREチームが介在せず運用できている • コントローラー、Terraform module、CUE の開発・運用に集中すれば 良い •

    プロダクトチームへのセルフサービス化が容易 • 導入・設定がプロダクトチーム内で完結するのでオーナーシップ を損なわない • YAML/CUE を書くだけで良い
  18. kubebuilderとは • CRD・コントローラー・Admission Webhookのひな形を生成するフレームワーク • controller-runtime/controller-toolsの上に構築されている • kubebuilder init でプロジェクト、kubebuilder

    create api でAPIを生成 •api/v1/<Kind>_types.go(Spec/Status)とinternal/controller/ <kind>_controller.goが生成される • コード中の+kubebuilderマーカーをcontroller-genが処理し、CRD manifestや RBACを自動生成 [7]
  19. controller-runtimeとは • コントローラーを実装するためのGoライブラリ群(kubebuilder/Operator SDKが利用) • Manager: Client・Cache・Schemeなど、コントローラーが共有する依存関 係を提供 • Reconciler:

    実際の同期ロジック本体。対象オブジェクトの名前を受け取 り、都度最新状態を取りに行く • Client/Cache: apiserverへの読み書き(Client)とローカルキャッシュからの読 み取り(Cache) [8]
  20. kubebuilderとcontroller-runtimeの関係 Controller (*_controller.go) 依存 controller-runtime • Manager • Reconciler •

    Client Watch/Reconcile プロジェクト生成 kubebuilder CRD (*_types.go) リソース定義を登録 kube-apiserver
  21. 参考文献 (1/3) • [1] Terraformモジュールを使ったCloud Spannerの設定標準化の取り組み • https://engineering.mercari.com/blog/entry/20230615-cloudspanner-configurationstandardization/ • [2]

    CUEを使用したKubernetesマニフェスト管理 • https://engineering.mercari.com/blog/entry/20220127-kubernetes-configurationmanagement-with-cue/ • [3] Kubebuilder Book: Hubs, spokes, and other wheel metaphors • https://book.kubebuilder.io/multiversion-tutorial/conversion-concepts.html • [4] controller-runtime: fake client package docs • https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/client/fake
  22. 参考文献 (2/3) • [5] Kubebuilder Book: Configuring envtest for integration

    tests • https://book.kubebuilder.io/reference/envtest.html • [6] sample-controller: client-go controller interaction diagram • https://github.com/kubernetes/sample-controller/blob/master/docs/ controller-client-go.md • [7] Kubebuilder Book: Quick Start • https://book.kubebuilder.io/quick-start.html • [8] Kubebuilder Book: Controller Overview • https://book.kubebuilder.io/cronjob-tutorial/controller-overview.html
  23. 参考文献 (3/3) • [9] kubebuilder: GitHub README •https://github.com/kubernetes-sigs/kubebuilder • [10]

    controller-runtime: GitHub README •https://github.com/kubernetes-sigs/controller-runtime