GitHubで実現するConfig Controllerによるリソース管理の自動化

記事タイトルとURLをコピーする

G-gen の武井です。

当記事では GitHub と Config Controller (Config Sync) を連携して Google Cloud (旧称 GCP) のリソース管理を自動化する方法について解説します。

当記事について

位置付け

以前 Google Cloud のブループリントを利用してリソース管理を自動化する方法を紹介しました。

blog.g-gen.co.jp

ブループリントを使用する場合、GitOps パイプライン (自動化の仕組み) におけるソースコード管理には Cloud Source Repositories が用いられます。

Cloud Source Repositories には2024年3月時点では Pull request 機能がないため、GitHub を導入して Pull request をはじめとした コラボレーション機能を補完して利便性を向上 させる意図があります。

前提知識

内容の重複を避けるため、前述の過去記事で解説済みの事項は割愛しています。そのため、過去記事をお読みいただくことで当記事の理解が深まるものと考えます。

関連記事

前述の過去記事以外にも Config Controller に関する記事がございます。こちらも合わせてお読みいただけると幸いです。

blog.g-gen.co.jp

変更点

概要

今回紹介するアーキテクチャは、前述のブループリントを最大限活用しつつも、GitOps パイプラインに GitHub に導入します。

GitOps パイプラインの構成

定義ファイルの Push 先が GitHub に変わるため、Pull request や Merge といったコラボレーション機能の活用、Mergeトリガーの CI/CD (リソース管理の自動化) が実現できます。

アーキテクチャ

今回の変更を図示すると以下のとおりです。

ポイントは、Cloud Source Repositories の source-repo を GitHub のミラーリングリポジトリに変更する点 にあります。

これにより、ブループリントを大幅に改修することなく、GitOps パイプラインの根幹にあたる Kpt によるレンダリング機能もそのまま活用できます。

変更前の構成

変更前

# コンポーネント 役割
1 source-repo ローカルから push されるファイル一式を格納するリポジトリ
2 Build トリガー 上記からレンダリングされたファイルを deployment-repopush
3 deployment-repo レンダリングされたファイル一式を格納するリポジトリ
4 Config Sync deployment-repo に接続する GitOps サービス

変更後の構成

変更後

# コンポーネント 役割
1 source-repo (GitHub) ローカルから push されるファイル一式を格納するリポジトリ
2 source-repo (CSR) GitHub をミラーリングするリポジトリ
3 Build トリガー 上記からレンダリングされたファイルを deployment-repopush
4 deployment-repo レンダリングされたファイル一式を格納するリポジトリ
5 Config Sync deployment-repo に接続する GitOps サービス

実装手順

概要

ここからは実装手順を解説しますが、詳細は前述の過去記事にて解説済みのため変更点を中心に解説します。

事前準備

こちらの手順は変更ありませんので詳細については過去記事をご確認ください。

Config Controller の設定

こちらの手順は変更ありませんので詳細については過去記事をご確認ください。

GitOps パイプラインの設定

変更点のみ以降で解説します。

source-repositories.yaml の編集

過去記事には存在しない手順となります。

Cloud Source Repositories の source-repo は GitHub ミラーのリポジトリとして手動で作成するため、定義ファイルから削除します。

# 変更前
  
apiVersion: sourcerepo.cnrm.cloud.google.com/v1beta1
kind: SourceRepoRepository
metadata:
  name: source-repo # kpt-set: ${source-repo}
  namespace: config-control # kpt-set: ${namespace}
  annotations:
    cnrm.cloud.google.com/blueprint: cnrm/gitops/v0.6.1
    cnrm.cloud.google.com/project-id: project-id # kpt-set: ${project-id}
---
apiVersion: sourcerepo.cnrm.cloud.google.com/v1beta1
kind: SourceRepoRepository
metadata:
  name: deployment-repo # kpt-set: ${deployment-repo}
  namespace: config-control # kpt-set: ${namespace}
  annotations:
    cnrm.cloud.google.com/blueprint: cnrm/gitops/v0.6.1
    cnrm.cloud.google.com/project-id: project-id # kpt-set: ${project-id}
# 変更後、deployment-repo の定義だけ残す
  
apiVersion: sourcerepo.cnrm.cloud.google.com/v1beta1
kind: SourceRepoRepository
metadata:
  name: deployment-repo # kpt-set: ${deployment-repo}
  namespace: config-control # kpt-set: ${namespace}
  annotations:
    cnrm.cloud.google.com/blueprint: cnrm/gitops/v0.6.1
    cnrm.cloud.google.com/project-id: project-id # kpt-set: ${project-id}

setters の定義

project-id 等の値を自身の環境に合わせて修正する点については変更ありませんが、source-repo は以下のように定義します。

# 変更前
  
apiVersion: v1
kind: ConfigMap
metadata: # kpt-merge: /setters
  name: setters
  annotations:
    config.kubernetes.io/local-config: "true"
    internal.kpt.dev/upstream-identifier: '|ConfigMap|default|setters'
data:
  # This should be the project where you deployed Config Controller
  project-id: project-id
  project-number: "1234567890123"
  # This should be the name of your Config Controller instance
  cluster-name: cluster-name
  # You can leave these defaults
  namespace: config-control
  deployment-repo: deployment-repo
  source-repo: source-repo
# 変更後  
# cluster-name / project-id / project-number を環境固有の値に置換  
# source-repo では GitHub リポジトリ `repo-owner/repo-name` の形式で定義する (GitHub リポジトリの URL から確認可能)
# source-repo-meta という Key を用意し、値は `source-repo` と定義する
  
apiVersion: v1
kind: ConfigMap
metadata: # kpt-merge: /setters
  name: setters
  annotations:
    config.kubernetes.io/local-config: "true"
    internal.kpt.dev/upstream-identifier: '|ConfigMap|default|setters'
data:
  # This should be the project where you deployed Config Controller
  project-id: sandbox-cc-test-prj
  project-number: "566560710327"
  # This should be the name of your Config Controller instance
  cluster-name: config-controller-1
  # You can leave these defaults
  namespace: config-control
  deployment-repo: deployment-repo
  source-repo-meta: source-repo
  source-repo: ggenyutakei/source-repo

gitops/configsync/setters.yaml の定義

GitOps パイプラインのデプロイの前に、以下に従い configsync-dir の値を config/landing-zone に変更してください。

source-repo (GitHub ミラー) の手動作成

過去記事には存在しない手順となります。

以下の公式ガイドを参考に、上記 setters.yaml で指定した GitHub リポジトリとミラーリングする Cloud Source リポジトリを作成してください。

Cloud Build トリガーの手動作成

過去記事には存在しない手順となります。

GitHub リポジトリへの Merge をトリガーにして Kpt によるレンダリング処理が実行されるよう、Cloud Build トリガーを手動で作成します。

手順は以下の公式ガイドを参照いただきつつ、パラメータについては以下に記します。

# パラメーター 設定値
1 イベント ブランチに push する
2 ソース 第1世代
3 リポジトリ ggenyutakei/source-repo
4 ブランチ .*
5 構成 Cloud Build 構成ファイル
6 ロケーション インライン ※詳細は以下
7 変数1 / 値1 _ADMIN_CLUSTER_NAME / config-controller-1
8 変数2 / 値2 _DEPLOYMENT_REPO / deployment-repo
9 変数3 / 値3 _SOURCE_REPO / ggenyutakei/source-repo
# インラインYAML
  
steps:
  - name: 'gcr.io/cloud-builders/gcloud:latest'
    args:
      - '-c'
      - >
        set -e

        gcloud source repos clone $_DEPLOYMENT_REPO .

        (git show-branch $BRANCH_NAME &>/dev/null) && (git checkout
        $BRANCH_NAME) || (git checkout -b $BRANCH_NAME)

        git config user.email $(gcloud auth list --filter=status:ACTIVE
        --format='value(account)')

        mkdir -p /deployment-workspace/config
    dir: /deployment-workspace
    id: Clone Deployment Repo
    entrypoint: /bin/sh
    volumes:
      - name: deployment-workspace
        path: /deployment-workspace
    timeout: 300s
  - name: 'gcr.io/kpt-dev/kpt:v1.0.0-beta.9'
    args:
      - '-c'
      - >
        set -eo pipefail

        SRC_DIR="."

        DEST_DIR="/hydrated-workspace/config"


        echo "Initializing kpt"

        kpt pkg init "$${SRC_DIR}"


        echo "Executing Kpt Functions..."

        kpt fn render "$${SRC_DIR}" --output="$${DEST_DIR}"
        --truncate-output=false


        echo "Removing local config"

        kpt fn eval "$${DEST_DIR}" -i
        gcr.io/kpt-fn/remove-local-config-resources:v0.1
    id: Apply Hydration and Validation
    entrypoint: /bin/bash
    volumes:
      - name: hydrated-workspace
        path: /hydrated-workspace
  - name: 'gcr.io/cloud-builders/gcloud:latest'
    args:
      - '-c'
      - >
        set -e

        git pull origin $BRANCH_NAME || true # Ignore errors in case branch
        doesn't exist

        git rm -rf /deployment-workspace/config/* --ignore-unmatch

        cp -r /hydrated-workspace/config /deployment-workspace/

        touch /deployment-workspace/config/.gitkeep

        # Configure Git to create commits with Cloud Build's service account

        git config user.email $(gcloud auth list --filter=status:ACTIVE
        --format='value(account)')

        git add -A

        git status

        if git diff --cached --exit-code; then echo "No changes"; true;

        else git commit -m "Resources from ${COMMIT_SHA}" && git push origin
        $BRANCH_NAME; fi

        printf "\n\nLatest deployment repo commit SHA: $(git rev-parse HEAD)\n"
    dir: /deployment-workspace
    id: Push Changes To Deployment Repo
    waitFor:
      - Apply Hydration and Validation
    entrypoint: /bin/sh
    volumes:
      - name: hydrated-workspace
        path: /hydrated-workspace
      - name: deployment-workspace
        path: /deployment-workspace
timeout: 600s

source-repo リポジトリへの Push

GitOps パイプラインのデプロイに使用したファイル一式は、setters の中で指定した GitHub リポジトリ に Push してマージしてください。

CSR ではなく GitHub の source-repo に Push すること

ランディングゾーンのデプロイ

以下の手順でランディングゾーンをデプロイします。これ以外は過去記事から大きな変更はありません。

  1. GitHub リポジトリでブランチを切る
  2. ランディングゾーンのブループリントをダウンロードして上記ブランチに配置する
  3. setters を定義して GitHub リポジトリ に push、Pull request をへて Merge する

kpt によるレンダリング、deployment-repo への push はパイプラインが行いますので、上記手順を実行するだけでランディングゾーンがデプロイされます。

最後に

Config Controller は Kubernetes の仕組みを用いているため、Reconciliation Loop に基づきリソースをあるべき状態を維持しようと作用します。

この機能は組織ポリシーや VPC Service Controls など、クラウド環境におけるセキュリティの根幹をなす 予防的統制 (ガードレール) と相性がよく、予期せぬ変更が発生した場合でも Config Controller が検知・是正してくれ、セキュリティ強化・維持、運用効率化の両方を実現します。

予防的統制機能を Config Controller で管理する方法については今後執筆予定です。

武井 祐介 (記事一覧)

2022年4月にジョイン。クラウドソリューション部所属。G-gen唯一の山梨県在住エンジニア

Google Cloud Partner Top Engineer 2024 に選出。IaC や CI/CD 周りのサービスやプロダクトが興味分野です。

趣味はロードバイク、ロードレースやサッカー観戦です。