Flux v2によるKubernetes上のGitOps実践:Gitからのインフラおよびアプリケーション自動同期

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

手動デプロイの苦悩:なぜGitOpsが必要だったのか

半年前、木曜日のデプロイウィンドウはまさに混沌そのものでした。us-east-1とeu-central-1に分散配置された計4つのKubernetesクラスタ(ステージング2環境、本番2環境)では、GitLab CIのRunnerがkubectl applyを介して素のManifestを力任せにPushしていました。デプロイジョブが途中でタイムアウトしたり、深夜2時にエンジニアが稼働中のPodへ直接ホットフィックスを適用したりするたび、クラスタの状態はGitリポジトリから静かに乖離(ドリフト)していきました。実際にクラスタ上で何が動いているのか、本番環境を直接調査しない限り誰も把握できない状況に陥っていたのです。

セキュリティ面でも深刻な問題を抱えていました。14名もの開発者が各自のラップトップにcluster-admin権限のkubeconfigコンテキストを保持し、CI Runnerには長期間有効な管理者トークンが保管されていました。さらに、リリース失敗時のロールバックには手作業でのManifest調査に45分も費やすのが常態化していました。こうしたPush型のデリバリー方式から完全に脱却するため、私たちはGitOpsへの移行を決断しました。クラスタ自身がGitリポジトリから望ましい状態を自律的にPullし、リコンサイル(継続的同期)する仕組みへと舵を切ったのです。

コアコンセプト:Flux v2のアーキテクチャを理解する

Flux v2は、カスタムリソース定義(CRD)をベースに構築された専用Kubernetes Controller群として動作します。単一の重量級デーモンにすべてを詰め込むのではなく、責務ごとに特化したマイクロコントローラーへ同期処理を委譲しています。

  • Source Controller: Gitリポジトリ、Helmレジストリ、OCIアーティファクト、あるいはS3バケットからコンテンツをPullします。取得したコンテンツを変更不可能なtarballにパッケージングし、クラスタ内部で利用できるように公開します。
  • Kustomize Controller: Source Controllerが展開した素のKubernetes ManifestやKustomize Overlayを受け取り、稼働中のクラスタ状態と照らし合わせて同期・適用(リコンサイル)します。
  • Helm Controller: カスタムリソースを用いてHelm Chartのリリース、アップグレード、テストサイクルを宣言的に管理します。これにより、CIのビルドノードにHelm CLIをインストールする必要がなくなります。
  • Notification Controller: SlackやPagerDutyへリアルタイムのロールアウト通知を送信するほか、インバウンドWebhookを受信してコミット時に即時リコンサイルをトリガーし、ポーリング間隔の待ち時間を解消します。

これらのコントローラーはすべてクラスタ内部で動作するため、同期エンジンは内側から変更を引き込み(Pull)ます。外部のCIパイプラインに必要な権限は、GitへのコミットPushやコンテナイメージタグの発行のみであり、Kubernetes APIへ直接アクセスすることは一切ありません。

ハンズオン実践:Flux v2をゼロからデプロイする

まっさらなクラスタ上でFluxを稼働させるのに、10分もかかりません。以下は、私たちの複数クラスタ環境をブートストラップし、最初の自動化ワークロードを起動した現場検証済みのワークフローです。

ステップ 1: Flux CLIのインストールと前提条件の確認

ローカルの開発マシンにスタンドアロンのCLIをインストールします。主にブートストラップ作業や迅速なデバッグ用として使用します。

# Linux/macOS環境にてcurl経由でインストール
curl -s https://fluxcd.io/install.sh | sudo bash

# Kubernetesクラスタの互換性を検証(v1.28以上が必要)
flux check --pre

この事前チェックにより、現在アクティブなkubeconfigコンテキストがクラスタ管理者権限を持っているか、またKubernetes APIのバージョンがCRDの要件を満たしているかが確認されます。

ステップ 2: GitリポジトリへのFluxのブートストラップ

ブートストラップを実行すると、Fluxのコントローラー群がflux-system名前空間にインストールされます。また、アプリケーションコードと併せてFluxの設定Manifestを管理するための専用Gitリポジトリも自動構成されます。

export GITHUB_TOKEN="ghp_yourPersonalAccessTokenHere"
export GITHUB_USER="your-github-username"

flux bootstrap github \
  --owner=$GITHUB_USER \
  --repository=fleet-infra \
  --branch=main \
  --path=./clusters/production \
  --personal

Fluxは自身のコントローラー定義を./clusters/production/flux-systemに書き込み、GitHubへPushしてDeploy Keyを自動設定します。約90秒ほどで、すべてのコアコントローラーPodが正常に起動します。

ステップ 3: ワークロード向けのGitSourceとKustomizationの定義

次に、対象ワークロードのリポジトリ所在と適用方法をFluxへ指示します。fleet-infraリポジトリをローカルにクローンし、アプリケーションManifest用のディレクトリを作成します。

git clone https://github.com/$GITHUB_USER/fleet-infra.git
cd fleet-infra
mkdir -p ./clusters/production/apps

アプリケーションのリポジトリを./clusters/production/apps/webapp-source.yamlに定義します。

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: webapp-source
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/your-github-username/sample-webapp
  ref:
    branch: main

続いて、そのソースコードをどのようにデプロイするかを./clusters/production/apps/webapp-kustomization.yamlで定義します。

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: webapp-deploy
  namespace: flux-system
spec:
  interval: 5m
  targetNamespace: default
  sourceRef:
    kind: GitRepository
    name: webapp-source
  path: "./k8s/overlays/production"
  prune: true
  wait: true
  timeout: 2m

ここで特に重要なのがprune: trueの設定です。この設定を有効にすることで、Git側でManifestを削除した際にFluxがクラスタ上からも該当リソースを自動的に削除し、不要になったServiceやSecretの孤立・残留を防ぎます。

ステップ 4: コミットとリコンサイル状態の確認

作成したマニフェスト定義をリポジトリへPushします。

git add clusters/production/apps/
git commit -m "feat: register webapp kustomization"
git push origin main

Fluxはデフォルトで1分ごとにリポジトリをポーリングし、変更を検知してManifestを適用します。ポーリング間隔を待たずに、手動で即時同期を実行してステータスを確認することも可能です。

# 即時同期を強制実行
flux reconcile source git flux-system

# Gitソースの状態を確認
flux get sources git

# Kustomizationのリコンサイル状況とヘルスチェックを確認
flux get kustomizations

自己修復(セルフヒーリング)機能もテストしてみましょう。kubectl scale deployment webapp --replicas=0を実行して意図的な障害を発生させます。数分以内にKustomize Controllerが定義との差異を検知し、期待されるレプリカ数へと自動復旧します。

本番稼働から半年を経た振り返り

デリバリーパイプラインをFlux v2へ移行したことで、日々の運用体制は劇的に改善しました。デプロイ頻度は従来の週2回の定期ウィンドウから、1日平均18回へと大幅に増加。平均修復時間(MTTR)は45分から3分未満へと激減し、リリース失敗時の復旧作業もgit revertを実行するだけのシンプルな操作になりました。

何より大きな収穫は、14台の開発マシンからクラスタへの直接アクセス権を剥奪し、CIワーカーから管理者トークンを一掃できたことです。現在ではGitが信頼できる唯一の情報源(Single Source of Truth)となり、監査ログはコミット履歴に正確に刻まれ、構成ドリフトが生じてもクラスタが自律的に正常な状態を回復しています。

Share: