Skip to main content

そのdev/staging/prodブランチ、実は時限爆弾。KubernetesのGitOpsが壊れる本当の理由

GitOpsを導入する際、多くのチームが最初にぶつかる設計判断が「環境をどう分けるか」だ。dev/staging/productionをGitブランチで分ける構成は、Git Flowの延長として一見自然に見える。しかし、この設計はKubernetesのGitOps運用において典型的なアンチパターンであり、放置すると本番環境のクラスタ状態そのものを壊しかねない。

1. 「安全な分離」だと思っていたブランチ環境が、実は壊れていく

section01

ブランチによる環境分離は、アプリケーションコードのバージョン管理としては合理的だ。機能ブランチを切り、レビューを経てmainにマージするフローは多くの開発チームに馴染みがある。だからこそ、Kubernetesのマニフェストやインフラ構成も同じ発想で「dev用ブランチ」「staging用ブランチ」「production用ブランチ」に分けてしまうチームは少なくない。

しかし、GitOpsの文脈ではこれがそのままアンチパターンになる。Octopus Deployのブログは、環境をGitブランチでモデル化する手法を「過去の遺物」と明確に位置づけ、HelmやKustomizeがそもそも複数環境向けのプレーンなファイル構成を前提に設計されていることを指摘している。ブランチベースの運用はこの設計思想に逆行してしまうのだ。

Platform Engineering.orgの記事でも、ブランチを環境に割り当てる方式は「ほとんどのチームにとってアンチパターンだ」と明言されており、マージコンフリクトの発生、環境間の状態比較の困難さ、トランクベース開発の原則違反という3つの具体的な弊害が挙げられている。この設計の負債は、クラスタ数が増えるほど後から直すコストが跳ね上がる。GitOps基盤を標準搭載したマネージドKubernetesを選ぶという選択肢があることも、この時点で頭の片隅に置いておきたい。

2. マージコンフリクトだけじゃない。Gitの「意図」とクラスタの「実態」がズレる本当の問題

section02

ブランチ分離が引き起こす表面的な問題は、マージコンフリクトや環境間の設定ドリフトだ。緊急パッチをproduction用ブランチに直接当てた結果、それがstaging用ブランチにバックポートされず、気づかぬうちに環境間の設定が乖離していく——これはGitOps運用者なら一度は経験する典型的な事故パターンだろう。

だが本質的な問題はもう一段深いところにある。GitOpsの根幹には「Gitを唯一の信頼できる情報源(Source of Truth)とする」という原則がある。CNCFのOpenGitOpsプロジェクトは、宣言的(Declarative)・バージョン管理と不変性(Versioned and Immutable)・自動プル(Pulled Automatically)・継続的な調整(Continuously Reconciled)という4原則を提示しており、これらはすべて「Gitに書かれた意図」と「クラスタの実態」が常に一致していることを前提にしている。

一方でKubernetesクラスタの実際の状態は、Kubernetes公式ドキュメントが説明する通り、コントロールプレーンのコンポーネントであるetcdに一貫性を保った形で保持されている。ブランチが分岐・マージを繰り返す構成では、「今どのブランチの内容が、どのクラスタのetcdに反映されているか」の対応関係を人間が正確に追い続けることは事実上不可能になる。Gitの差分と本番の実態がズレていくのは、運用ミスというより設計そのものの限界なのだ。

3. ディレクトリ構成 + トランクベース運用への移行パターン

section03

解決の方向性は明快だ。環境の分離を「ブランチ」ではなく「ディレクトリ(フォルダ)」で表現し、すべての環境が同じmainブランチを追跡しながら異なるアーティファクトバージョンを参照する構成に移行することだ。

Google Cloudの公式GitOpsベストプラクティスガイドでも、ブランチよりもフォルダのほうが変更を検出しやすく、複数クラスタへの同期が容易になるとして、フォルダベースのアプローチを明確に推奨している。同ガイドはさらに、パッケージ・プラットフォーム・アプリケーション構成・アプリケーションコードという4種類のリポジトリを役割ごとに分離することも提案しており、チームの責任範囲とリポジトリ構造を一致させる設計思想がうかがえる。

この構成であれば、プロモーションは「ブランチのマージ」ではなく「マニフェスト内のイメージタグを書き換えるコミット」になる。Argo CDの公式ドキュメントが定義するように、GitOpsはGitリポジトリを望ましい状態のソースとし、その変更を自動的・宣言的に反映する仕組みだ。ディレクトリ構成にすることで、この仕組みがそのまま素直に機能するようになる。より大規模な組織では、Akuityが公開しているGitOpsベストプラクティスのホワイトペーパーが指摘するように、単一リポジトリと複数リポジトリのどちらを選ぶかは組織構造そのものに影響される問題であり、環境間のプロモーションを一級市民として扱う専用ツールを組み合わせる動きも進んでいる。Kubo CloudはArgoCD/Fluxとの統合を標準搭載しているため、このディレクトリ構成への移行を自前でゼロから構築する必要がなく、Helmチャート対応も含めてすぐに実践に移せる。

4. マルチクラスタ運用で10クラスタが100クラスタになったとき、何が壊れるのか

section04

ディレクトリ構成への移行が済んでも、フリートの規模が拡大すると新しい壁に突き当たる。OneUptimeの検証記事によれば、単一のArgoCDインスタンスで100クラスタを超える運用を行うと、アプリケーションコントローラーが全クラスタの全リソースをメモリ内にキャッシュし続けるためメモリ使用量が肥大化し、リポジトリサーバーのマニフェスト生成も遅延し始める。クラスタ数×アプリケーション数のマトリクスが大きくなるほど、この負荷は指数的に増していく。

この壁を越えるための定石が、リージョンごとに20〜30クラスタを管理するArgoCDインスタンスを配置し、それらを束ねるメタインスタンスでまとめて管理する「フェデレーション型アーキテクチャ」だ。個々のクラスタへのApplication生成には、ArgoCDのApplicationSet Cluster Generatorを使い、ラベルセレクタで対象クラスタを絞り込みながら自動生成する運用が2026年時点の実践的なパターンとして定着している。ブランチ設計の問題を先に解決していなければ、この段階でスケール戦略を検討すること自体が難しくなる。

まとめ:ブランチ設計の負債は、クラスタが増える前に清算する

section05

GitOpsにおけるブランチ環境分離は、導入初期には気づきにくい負債だ。マージコンフリクトという表面的な不便さの奥には、「Gitの意図」と「クラスタの実態」がズレていくという構造的な問題が潜んでいる。ディレクトリ構成とトランクベース運用への移行は、クラスタ数が少ないうちに済ませておくほど低コストで、フリートが10から100クラスタへ拡大したときの選択肢を狭めない。

こうしたGitOpsの設計をゼロから自前で組むには相応の時間がかかる。KuboはK3sベースのマネージドKubernetesとして、ArgoCD/Fluxとの統合を標準搭載しており、ディレクトリベースのGitOps構成をすぐに実践できる状態から始められる。マルチクラスタの管理・可視化にはRancher管理基盤を採用しており、10クラスタから100クラスタへとマルチクラスタ運用が拡大していく過程で必要になる運用の土台もあらかじめ用意されている。

EKSやAKSでフルスクラッチにGitOps基盤を構築し、スケール時のアーキテクチャ変更にも自前で対応し続けるのか、それとも標準統合された基盤の上でブランチ設計の見直しに集中するのか。この記事の内容を自分たちの構成に当てはめて棚卸ししてみたい方は、まずKuboの料金プランでEKS/AKSとのコスト比較を確認するか、お問い合わせから現状のGitOps構成について相談してみてほしい。

Related articles

← Back to all posts