G-gen の武井です。
Config Controller (Config Sync) で Google Cloud (旧称 GCP) のブループリントを利用して GitOps なリソース管理を実現するための検証を行いました。当記事ではその方法をご紹介します。

はじめに
当記事の概要
Config Controller で Google Cloud のブループリントを利用すると以下を実現することができます。
- GitOps パイプライン のデプロイ
- GitOps パイプライン を用い、ランディングゾーン を始めとする各種 Google Cloud リソース構成のデプロイ・管理
当記事では実際の検証結果をふまえ分かりやすく解説します。
アーキテクチャ
構成
前述の概要を図示すると以下のとおりです。

構成要素
各構成要素とそれらが担う役割 (処理) の概要を説明します。なお、GitOps パイプライン とは以下表の #3 ~ #5
から構成される CI/CD パイプラインのことを指します。
# | 構成要素 | 役割 |
---|---|---|
1 | GitHub | Google Cloud ブループリント (テンプレート) を管理する Git リポジトリ |
2 | setters | ブループリント上の設定値を一元管理する機能 |
3 | source-repo | setters を定義したブループリントが格納される Git リポジトリ |
4 | Cloud Build | setters から環境固有のマニフェストをレンダリングする kpt 関数 |
5 | deployment-repo | レンダリングされたマニフェストが格納される Git リポジトリ |
6 | Config Sync | Config Controller に GitOps サービスを提供するコンポーネント |
7 | Config Controller | マニフェストにもとづきリソースをデプロイ管理するコンポーネント |
一連の処理
setters
を定義したブループリントを GitOps パイプラインに push
すると、Cloud Build による kpt
関数 (レンダリング) が実行され、各環境固有のマニフェストが自動的に生成されます。
Config Sync はレンダリングされたマニフェストが格納されたリポジトリを定期的に参照します。参照結果は Config Controller に連携され、結果に基づくリソースの管理やデプロイを自動実行します。
前提知識 (用語解説)
Google Cloud ブループリント
Google Cloud には ブループリント と呼ばれる、Google Cloud 上のリソースやサービスの構成を宣言的に管理するためのフレームワークが存在します。
ブループリントには ランディングゾーン (後述) を始め、様々な構成に関するベストプラクティスが提供されており、それらを利用することで、企業や組織は Google Cloud の構成を一貫性のある方法でデプロイ・管理することができます。
ランディングゾーン
ランディングゾーン とは、「クラウド上に新しい環境やワークロードを迅速かつ安全にデプロイするための事前定義された設計パターン」を表す概念 (用語) です。
セキュリティ、運用、ネットワーク設計、アクセス管理など、クラウド基盤を構築する上でのベストプラクティスが考慮された形で設計されており、上記ブループリントの landing-zone
ディレクトリ配下にはマニフェストファイル一式が用意されています。
Anthos Config Management
Anthos Config Management は、Google Cloud リソースのプロビジョニングとオーケストレーションを行うサービスです。
Config Controller、Config Sync、Policy Controller という 3つ のコンポーネントから構成されます。
詳細についてはこちらの記事をご確認ください。
blog.g-gen.co.jp
kpt
kpt とは マニフェストファイルを操作(パッケージ化、pull、更新、変更)するための Google が開発したオープンソースツールです。
今回のケースでは、当ツールを使って Google Cloud のブループリントを取得したり、取得したブループリント (テンプレート) から、適用先環境に合わせたマニフェストファイルを レンダリング (後述) したりします。
レンダリング
前述の通り、Config Controller や kpt の文脈におけるレンダリングとは「雛形となるブループリントから各環境固有のマニフェストファイルを生成する処理のこと」を指しており、その処理の中で kpt の setters (後述) という機能が用いられています。
setters
setters とは、「マニフェストファイル内の特定の値を一元的に管理・更新するための機能」のことで、Linux でいう環境変数の概念と同じです。
Google Cloud のブループリントは様々なプロジェクトや環境で再利用することが想定されます。当機能を利用すれば、ブループリント上の初期値をそれぞれの環境やプロジェクト固有の値 (例: プロジェクト ID やリージョン名) に簡単に更新でき、ブループリントを効率的に利用できます。
関連記事
以下の記事でも Config Controller について解説しています。こちらもあわせてご参照ください。
blog.g-gen.co.jp
blog.g-gen.co.jp
事前準備
参考ドキュメント
今回の検証は以下の公式ガイドを参考にして実施しています。
実行環境
本設定では gcloud
コマンドの他に、kubectl
、nomos
、kpt
といったコマンドを利用するため、これらがプリインストールされた Cloud Shell を利用します。
# コマンド which kubectl nomos kpt # 戻り値 /usr/bin/kubectl /usr/bin/nomos /usr/bin/kpt
Project / VPC / Subnet の準備
Config Controller (実体は GKE クラスタ) を作成する Project / VPC / Subent
を準備します。
※ 作成方法の解説は割愛します。
# | リソース | リソース名 |
---|---|---|
1 | Project (Project ID) | sandbox-cc-test-prj |
2 | VPC | sandbox-cc-test-vpc |
3 | Subnet | sandbox-cc-test-subnet |
環境変数と gcloud の設定
Cloud Shell で環境変数と gcloud
コマンドのプロジェクト設定を行います。
※ 設定途中で Cloud Shell の接続が切れた場合は再度環境変数を設定してください。
# CONFIG_CONTROLLER_NAME は 25 文字以内 export PROJECT_ID=sandbox-cc-test-prj export CONFIG_CONTROLLER_NAME=config-controller-1 export BILLING_ACCOUNT=$(gcloud alpha billing projects describe $PROJECT_ID \ '--format=value(billingAccountName)' | sed 's/.*\///') export ORG_ID=$(gcloud projects get-ancestors ${PROJECT_ID} --format='get(id)' | tail -1) # gcloud の設定 (向き先となるプロジェクトの指定) gcloud config set project ${PROJECT_ID} # 戻り値 Updated property [core/project].
Config Controller の設定
API 有効化
Config Controller API
と GKE API
を有効にします。
# コマンド gcloud services enable krmapihosting.googleapis.com container.googleapis.com # 戻り値 Operation "operations/acf.p2-566560710327-a294ce1f-f676-4214-9e8e-1340fe0bee36" finished successfully.
Config Controller クラスタの作成
クラスタを以下の条件で作成します。(この操作には時間がかかる場合があります)
Autopilot
asia-northeast1 (東京リージョン)
- 事前準備で作成した
VPC / Subnet
# コマンド gcloud anthos config controller create ${CONFIG_CONTROLLER_NAME} \ --location=asia-northeast1 \ --network=sandbox-cc-test-vpc \ --subnet=sandbox-cc-test-subnet \ --full-management # 戻り値 Create request issued for: [config-controller-1] Waiting for operation [projects/sandbox-cc-test-prj/locations/asia-northeast1/operations/operation-1692153896333-6030147e571e0-03bfd650-4d82d756] to comple te...done. Created instance [config-controller-1]. Fetching cluster endpoint and auth data. kubeconfig entry generated for krmapihost-config-controller-1.
クラスタの作成が正常に完了したことを確認します。
# コマンド gcloud anthos config controller list --location=asia-northeast1 # 戻り値 NAME: config-controller-1 LOCATION: asia-northeast1 STATE: RUNNING
Config Controller クラスタの認証
クラスタの認証情報を取得します。
# コマンド gcloud anthos config controller get-credentials ${CONFIG_CONTROLLER_NAME} \ --location=asia-northeast1 # 戻り値 Fetching cluster endpoint and auth data. kubeconfig entry generated for krmapihost-config-controller-1.
Config Controller クラスタへの権限付与
クラスタのサービスアカウント (service-PROJECT_NUMBER@gcp-sa-yakima.iam.gserviceaccount.com
) に、プロジェクトおよび組織レベルで管理権限を付与します。
# 環境変数設定 export SA_EMAIL="$(kubectl get ConfigConnectorContext -n config-control \ -o jsonpath='{.items[0].spec.googleServiceAccount}' 2> /dev/null)" # IAM Policy 設定 (プロジェクトレベル) gcloud projects add-iam-policy-binding "${PROJECT_ID}" \ --member "serviceAccount:${SA_EMAIL}" \ --role "roles/owner" \ --project "${PROJECT_ID}" # 戻り値 (一部のみ抜粋) Updated IAM policy for project [sandbox-cc-test-prj]. bindings: - members: - serviceAccount:service-566560710327@gcp-sa-yakima.iam.gserviceaccount.com - user:user@example.co.jp role: roles/owner etag: BwYDAjdY4F0= version: 1 # IAM Policy 設定 (組織レベル) gcloud organizations add-iam-policy-binding $ORG_ID \ --role=roles/resourcemanager.organizationAdmin \ --condition=None \ --member="serviceAccount:${SA_EMAIL}" # 戻り値 (一部のみ抜粋) Updated IAM policy for organization [999999999999]. bindings: - members: - serviceAccount:service-566560710327@gcp-sa-yakima.iam.gserviceaccount.com role: roles/resourcemanager.organizationAdmin etag: BwYDAoGjp8Q= version: 1
GitOps パイプラインの設定
成果物の確認
このプロセスでは以下のリソースで構成される GitOps パイプラインを作成します。
# | リソース | 役割 |
---|---|---|
1 | source-repo | ローカルから push されるファイル一式を格納するリポジトリ |
2 | Build トリガー | 上記からレンダリングされたファイルを deployment-repo に push |
3 | deployment-repo | レンダリングされたファイル一式を格納するリポジトリ |
4 | Config Sync | deployment-repo に接続する GitOps サービス |
API 有効化
Cloud Source Repositories API
と Resource Manager API
を有効にします。
# コマンド gcloud services enable sourcerepo.googleapis.com cloudresourcemanager.googleapis.com # 戻り値 Operation "operations/acat.p2-566560710327-99c27c46-29ce-4747-a867-eea8ff811998" finished successfully.
GitOps ブループリントのダウンロード
kpt
を使用して GitHub から Cloud Shell に GitOps ブループリント をダウンロードして GitOps パイプラインをデプロイします。
バージョンは GitOps ブループリントの GHANGELOG.md
から確認できます。

# 最新の GitOps ブループリントをダウンロード kpt pkg get https://github.com/GoogleCloudPlatform/blueprints.git/catalog/gitops@gitops-blueprint-v0.6.1 gitops # 戻り値 Package "gitops": Fetching https://github.com/GoogleCloudPlatform/blueprints@gitops-blueprint-v0.6.1 From https://github.com/GoogleCloudPlatform/blueprints * tag gitops-blueprint-v0.6.1 -> FETCH_HEAD Adding package "catalog/gitops". Fetched 1 package(s).
Cloud Shell にダウンロードできたことを確認します。
# コマンド tree gitops/ # 戻り値 gitops/ ├── CHANGELOG.md ├── cloudbuild-iam.yaml ├── configsync │ ├── config-management.yaml │ ├── configsync-iam.yaml │ ├── Kptfile │ ├── README.md │ ├── rootsync.yaml │ ├── setters.yaml │ └── validation.yaml ├── hydration-trigger.yaml ├── Kptfile ├── README.md ├── services.yaml ├── setters.yaml └── source-repositories.yaml 1 directory, 15 files
主要なマニフェストファイルの役割は以下の通りです。
# | gitops/ 以下 | 役割 |
---|---|---|
1 | Kptfile | kpt の設定ファイル |
2 | setters.yaml | gitops/ 以下の各マニフェストファイルの設定値を一元管理 |
3 | services.yaml | パイプラインが使用するサービス API を管理 |
4 | source-repositories.yaml | リポジトリ (Cloud Source Repositories, CSR) を管理 |
5 | cloudbuild-iam.yaml | Cloud Build サービスアカウントの IAM Policy を管理 |
6 | hydration-trigger.yaml | リポジトリ間で行われる処理 (Cloud Build トリガー) を管理 |
# | gitops/configsync 以下 | 役割 |
---|---|---|
1 | configsync-iam.yaml | Config Sync と CSR 間の認証 (Workload Identity 方式) を管理 |
2 | rootsync.yaml | Config Sync (CSR に対する GitOps サービス) を管理 |
setters の定義
ダウンロードしたブループリントを setters (セッター)
を使って自身の環境向けにカスタマイズします。
setters
とは kpt
の機能の一つで、マニフェスト内の特定の値を一元的に変更・設定するための役割を提供します。簡単に表すとマニフェスト内の変数を管理するイメージです。
これにより、マニフェスト内の初期値が setters
を介して一意の値に置き換えられます。setters
は gitops/setters.yaml
ファイル内で管理されていますので、そちらを編集します。
# 変更前 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 を環境固有の値に置換 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: source-repo
レンダリング
定義した setters
を使ってブループリントをレンダリングします。
レンダリングとは、setters.yaml
で定義した内容にもどづきマニフェストを完成 (カスタマイズ) させる という意味に近しいです。
# コマンド kpt fn render gitops/ # 戻り値 Package "gitops/configsync": [RUNNING] "gcr.io/kpt-fn/apply-setters:v0.1" [PASS] "gcr.io/kpt-fn/apply-setters:v0.1" in 4.1s Results: [info] spec.clusterName: set field value to "cluster-name" [info] metadata.name: set field value to "sync-cluster-name" [info] metadata.namespace: set field value to "config-control" [info] metadata.annotations.cnrm.cloud.google.com/project-id: set field value to "project-id" ...(14 line(s) truncated, use '--truncate-output=false' to disable) [RUNNING] "gcr.io/kpt-fn/starlark:v0.4" [PASS] "gcr.io/kpt-fn/starlark:v0.4" in 4.4s Package "gitops": [RUNNING] "gcr.io/kpt-fn/apply-setters:v0.1" [PASS] "gcr.io/kpt-fn/apply-setters:v0.1" in 300ms Results: [info] spec.clusterName: set field value to "config-controller-1" [info] metadata.name: set field value to "sync-config-controller-1" [info] metadata.namespace: set field value to "config-control" [info] metadata.annotations.cnrm.cloud.google.com/project-id: set field value to "sandbox-cc-test-prj" ...(38 line(s) truncated, use '--truncate-output=false' to disable) Successfully executed 3 function(s) in 2 package(s).
レンダリング実行後、例えば gitops/source-repositories.yaml
を確認すると project-id
が定義した値に置換されたことが分かります。
# 変更前 apiVersion: sourcerepo.cnrm.cloud.google.com/v1beta1 kind: SourceRepoRepository metadata: # kpt-merge: config-control/source-repo name: source-repo # kpt-set: ${source-repo} namespace: config-control # kpt-set: ${namespace} annotations: cnrm.cloud.google.com/blueprint: cnrm/gitops/v0.6.1,kpt-pkg cnrm.cloud.google.com/project-id: project-id # kpt-set: ${project-id} internal.kpt.dev/upstream-identifier: 'sourcerepo.cnrm.cloud.google.com|SourceRepoRepository|config-control|source-repo' --- apiVersion: sourcerepo.cnrm.cloud.google.com/v1beta1 kind: SourceRepoRepository metadata: # kpt-merge: config-control/deployment-repo name: deployment-repo # kpt-set: ${deployment-repo} namespace: config-control # kpt-set: ${namespace} annotations: cnrm.cloud.google.com/blueprint: cnrm/gitops/v0.6.1,kpt-pkg cnrm.cloud.google.com/project-id: project-id # kpt-set: ${project-id} internal.kpt.dev/upstream-identifier: 'sourcerepo.cnrm.cloud.google.com|SourceRepoRepository|config-control|deployment-repo'
# 変更後 apiVersion: sourcerepo.cnrm.cloud.google.com/v1beta1 kind: SourceRepoRepository metadata: # kpt-merge: config-control/source-repo name: source-repo # kpt-set: ${source-repo} namespace: config-control # kpt-set: ${namespace} annotations: cnrm.cloud.google.com/blueprint: cnrm/gitops/v0.6.1,kpt-pkg-fn cnrm.cloud.google.com/project-id: sandbox-cc-test-prj # kpt-set: ${project-id} internal.kpt.dev/upstream-identifier: 'sourcerepo.cnrm.cloud.google.com|SourceRepoRepository|config-control|source-repo' --- apiVersion: sourcerepo.cnrm.cloud.google.com/v1beta1 kind: SourceRepoRepository metadata: # kpt-merge: config-control/deployment-repo name: deployment-repo # kpt-set: ${deployment-repo} namespace: config-control # kpt-set: ${namespace} annotations: cnrm.cloud.google.com/blueprint: cnrm/gitops/v0.6.1,kpt-pkg-fn cnrm.cloud.google.com/project-id: sandbox-cc-test-prj # kpt-set: ${project-id} internal.kpt.dev/upstream-identifier: 'sourcerepo.cnrm.cloud.google.com|SourceRepoRepository|config-control|deployment-repo'
また、gitops/source-repositories.yaml
ファイル以外も setters
によってレンダリングされており、これらレンダリングされたファイル一式を使って GitOps パイプラインをデプロイします。
GitOps パイプラインのデプロイ
kubectl apply
でレンダリングしたファイル一式を適用し、GitOps パイプラインをデプロイします。
# コマンド kubectl apply --wait -f gitops/ --recursive # 戻り値 iampartialpolicy.iam.cnrm.cloud.google.com/deployment-repo-cloudbuild-write created iampartialpolicy.iam.cnrm.cloud.google.com/source-repo-cloudbuild-read created configmanagement.configmanagement.gke.io/config-management configured iamserviceaccount.iam.cnrm.cloud.google.com/sync-config-controller-1 created iampartialpolicy.iam.cnrm.cloud.google.com/sync-config-controller-1 created iampartialpolicy.iam.cnrm.cloud.google.com/source-reader-sync-config-controller-1-sandbox-cc-test-prj created rootsync.configsync.gke.io/root-sync created configmap/setters created cloudbuildtrigger.cloudbuild.cnrm.cloud.google.com/source-repo-cicd-trigger created service.serviceusage.cnrm.cloud.google.com/sourcerepo.googleapis.com created service.serviceusage.cnrm.cloud.google.com/cloudbuild.googleapis.com created configmap/setters configured sourcereporepository.sourcerepo.cnrm.cloud.google.com/source-repo created sourcereporepository.sourcerepo.cnrm.cloud.google.com/deployment-repo created error: resource mapping not found for name: "validate-cluster-name-length" namespace: "" from "gitops/configsync/validation.yaml": no matches for kind "StarlarkRun" in version "fn.kpt.dev/v1alpha1" ensure CRDs are installed first
リポジトリを作成します。
# コマンド kubectl wait --for=condition=READY -f gitops/source-repositories.yaml # 戻り値 sourcereporepository.sourcerepo.cnrm.cloud.google.com/source-repo condition met sourcereporepository.sourcerepo.cnrm.cloud.google.com/deployment-repo condition met
上記実行後、source-repo
と deployment-repo
の 2つのリポジトリが作成されました。
# コマンド gcloud source repos list # 戻り値 REPO_NAME: deployment-repo PROJECT_ID: sandbox-cc-test-prj URL: https://source.developers.google.com/p/sandbox-cc-test-prj/r/deployment-repo REPO_NAME: source-repo PROJECT_ID: sandbox-cc-test-prj URL: https://source.developers.google.com/p/sandbox-cc-test-prj/r/source-repo

また、以下のコマンドで Build トリガーと Config Sync が作成されたことを確認できます。
# コマンド kubectl get gcp -n config-control -o yaml \ | grep "^ name: \\|message" # 戻り値 name: source-repo-cicd-trigger message: The resource is up to date name: deployment-repo-cloudbuild-write message: The resource is up to date name: source-reader-sync-config-controller-1-sandbox-cc-test-prj message: The resource is up to date name: source-repo-cloudbuild-read message: The resource is up to date name: sync-config-controller-1 message: The resource is up to date name: sync-config-controller-1 message: The resource is up to date name: projects/sandbox-cc-test-prj/serviceAccounts/sync-config-controller-1@sandbox-cc-test-prj.iam.gserviceaccount.com name: cloudbuild.googleapis.com message: The resource is up to date name: sourcerepo.googleapis.com message: The resource is up to date name: deployment-repo message: The resource is up to date name: source-repo message: The resource is up to date
source-repo リポジトリへの Push
source-repo
リポジトリに GitOps パイプラインのデプロイに使用したファイル一式を push
します。
まず、リポジトリのデフォルトブランチを main
に設定します。
# コマンド (戻り値なし) git config --global init.defaultBranch main
次に、gcloud source repos clone
コマンドで source-repo
リポジトリを Cloud Shell にクローンします。
# コマンド gcloud source repos clone source-repo # 戻り値 Cloning into '/home/user/gitops_test_20230816/source-repo'... warning: You appear to have cloned an empty repository. Project [sandbox-cc-test-prj] repository [source-repo] was cloned to [/home/user/gitops_test_20230816/source-repo].
クローンしたリポジトリに gitops/
ディレクトリを移動します。
# 移動前の状態確認 ls -l total 8 drwx------ 3 user user 4096 Aug 16 12:52 gitops drwxr-xr-x 3 user user 4096 Aug 16 14:46 source-repo # 移動とその後の状態確認 mv gitops/ source-repo/ && ls -l total 4 drwxr-xr-x 4 user user 4096 Aug 16 14:51 source-repo
最後にファイル一式を commit / push
します。
# コマンド (git commit まで) cd source-repo/ git add gitops/ git commit -m "Add GitOps blueprint" [main (root-commit) f989115] Add GitOps blueprint 15 files changed, 726 insertions(+) create mode 100644 gitops/CHANGELOG.md create mode 100644 gitops/Kptfile create mode 100644 gitops/README.md create mode 100644 gitops/cloudbuild-iam.yaml create mode 100644 gitops/configsync/Kptfile create mode 100644 gitops/configsync/README.md create mode 100644 gitops/configsync/config-management.yaml create mode 100644 gitops/configsync/configsync-iam.yaml create mode 100644 gitops/configsync/rootsync.yaml create mode 100644 gitops/configsync/setters.yaml create mode 100644 gitops/configsync/validation.yaml create mode 100644 gitops/hydration-trigger.yaml create mode 100644 gitops/services.yaml create mode 100644 gitops/setters.yaml create mode 100644 gitops/source-repositories.yaml # コマンド (git push) git push [main (root-commit) f989115] Add GitOps blueprint 15 files changed, 726 insertions(+) create mode 100644 gitops/CHANGELOG.md create mode 100644 gitops/Kptfile create mode 100644 gitops/README.md create mode 100644 gitops/cloudbuild-iam.yaml create mode 100644 gitops/configsync/Kptfile create mode 100644 gitops/configsync/README.md create mode 100644 gitops/configsync/config-management.yaml create mode 100644 gitops/configsync/configsync-iam.yaml create mode 100644 gitops/configsync/rootsync.yaml create mode 100644 gitops/configsync/setters.yaml create mode 100644 gitops/configsync/validation.yaml create mode 100644 gitops/hydration-trigger.yaml create mode 100644 gitops/services.yaml create mode 100644 gitops/setters.yaml create mode 100644 gitops/source-repositories.yaml
source-repo
リポジトリの main
ブランチにファイル一式が格納されました。

ランディングゾーンのデプロイ
概要
以下の手順でランディングゾーンをデプロイします。
- ランディングゾーンのブループリントをダウンロードする
setters
を定義してsource-repo
にpush
する
kpt
によるレンダリング、deployment-repo
への push
はパイプラインが行いますので、上記手順を実行するだけでランディングゾーンがデプロイされます。
ランディングゾーンブループリントのダウンロード
kpt
を使って ランディングゾーンのブループリント を Cloud Shell にダウンロードします。
# コマンド、@main でリポジトリの main ブランチから取得する kpt pkg get https://github.com/GoogleCloudPlatform/blueprints.git/catalog/landing-zone@main ./landing-zone # kpt pkg の戻り値は先程と同様のため割愛
Cloud Shell にダウンロードできたことを確認します。
# コマンド tree -a landing-zone/ # 戻り値 landing-zone/ ├── CHANGELOG.md ├── iam.yaml ├── Kptfile ├── logging │ └── .gitkeep # 空ディレクトリを維持するためのファイル ├── namespaces │ ├── hierarchy.yaml │ ├── logging.yaml │ ├── networking.yaml │ ├── policies.yaml │ └── projects.yaml ├── network │ └── .gitkeep # 空ディレクトリを維持するためのファイル ├── policies │ ├── deletion-policy-required-template.yaml │ ├── disable-guest-attributes.yaml │ ├── disable-iam-grants-default-sa.yaml │ ├── disable-nested-virtualization.yaml │ ├── disable-sa-key-creation.yaml │ ├── disable-serial-port.yaml │ ├── disable-vm-external-ip.yaml │ ├── enforce-uniform-bucket-lvl-access.yaml │ ├── folder-naming-constraint-template.yaml │ ├── restrict-cloud-sql-public-ip.yaml │ ├── restrict-lien-removal.yaml │ └── skip-default-network.yaml ├── projects │ └── .gitkeep # 空ディレクトリを維持するためのファイル ├── README.md ├── services.yaml └── setters.yaml 5 directories, 26 files
主要なマニフェストファイルの役割は以下の通りです。
# | landing-zone/ 以下 | 役割 |
---|---|---|
1 | Kptfile | kpt の設定ファイル |
2 | setters.yaml | landing-zone/ 以下の各マニフェストファイルの設定値を一元管理 |
3 | services.yaml | ランディングゾーンが使用するサービス API を管理 |
4 | iam.yaml | グループアカウントの IAM Policy (組織レベル) を管理 |
namespaces
ディレクトリには Config Controller が使用するネームスペース、policies
ディレクトリは組織ポリシーに関するマニフェストファイルが格納されています。
logging
、network
、projects
ディレクトリは現時点で空ディレクトリを維持するためのファイルしかないためデプロイされるリソースはありませんが、別途拡張・カスムすることができます。
setters の定義
landing-zone/setters.yaml
ファイルを編集して setters
を定義します。
その前に上記ファイルの編集差分を後ほど確認できるよう、git commit
まで実行します。
# コマンド ls -l # 戻り値 total 8 drwx------ 3 user user 4096 Aug 16 12:52 gitops drwx------ 7 user user 4096 Aug 17 05:56 landing-zone # git commit まで実行 (レンダリング後の差分を diff するため push はしない) git add landing-zone/ git commit -m "Add landing zone" # git の戻り値は先程と同様のため割愛
あらためて landing-zone/setters.yaml
ファイルを編集します。
# 変更前 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: # Organization ID and billing account org-id: "123456789012" billing-account-id: AAAAAA-BBBBBB-CCCCCC # Groups to use for org-level roles group-org-admins: gcp-organization-admins@example.com group-billing-admins: gcp-billing-admins@example.com # The project where Config Controller is deployed management-project-id: management-project-id # This default is safe to keep management-namespace: config-control
# 変更後、org-id / billing-account-id / management-project-id / group-org-admins / group-billing-admins を変更 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: # Organization ID and billing account org-id: "999999999999" # billing-account-id: 00000B-66666E-DDDD77 # Groups to use for org-level roles group-org-admins: ggen@sandbox.co.jp group-billing-admins: ggen@sandbox.co.jp # The project where Config Controller is deployed management-project-id: sandbox-cc-test-prj # This default is safe to keep management-namespace: config-control
landing-zone/setters.yaml
ファイル編集後の差分は git diff
コマンドでも確認できます。
# コマンド git diff # 戻り値 diff --git a/landing-zone/setters.yaml b/landing-zone/setters.yaml index 398cbcb..0905af7 100644 --- a/landing-zone/setters.yaml +++ b/landing-zone/setters.yaml @@ -20,12 +20,12 @@ metadata: # kpt-merge: /setters internal.kpt.dev/upstream-identifier: '|ConfigMap|default|setters' data: # Organization ID and billing account - org-id: "123456789012" - billing-account-id: AAAAAA-BBBBBB-CCCCCC + org-id: "999999999999" + billing-account-id: 00000B-66666E-DDDD77 # Groups to use for org-level roles - group-org-admins: gcp-organization-admins@example.com - group-billing-admins: gcp-billing-admins@example.com + group-org-admins: ggen@sandbox.co.jp + group-billing-admins: ggen@sandbox.co.jp # The project where Config Controller is deployed - management-project-id: management-project-id + management-project-id: sandbox-cc-test-prj # This default is safe to keep management-namespace: config-control
source-repo リポジトリへの Push
変更内容を確認したら source-repo
リポジトリに push
します。
# コマンド git commit -a -m "Customize landing zone blueprint" git push # git の戻り値は先程と同様のため割愛
その後、上記をトリガーとして GitOps パイプラインが以下のように動作し、最終的にランディングゾーンがデプロイされます。
landing-zone/setters.yaml
ファイルにもとづきレンダリングが行われる- レンダリングされたファイル一式が
deployment-repo
にpush
される - Config Sync が
deployment-repo
を参照する - Config Controller が 参照結果にもとづきランディングゾーンをデプロイする
トラブルシューティング
想定エラー
参考ドキュメントをベースに進めてきましたが、nomos status
(Config Sync が管理するリソースの状態確認) コマンドを実行すると KNV1069: SelfManageError
が発生するものと思われます。
# コマンド nomos status # 戻り値 (エラーのみ抜粋) KNV1069: RootSync config-management-system/root-sync must not manage itself in its repo
エラー原因
原因は Config Sync が、自身のマニフェストファイル (rootsync.yaml
) を含め、リポジトリ全体を参照するように設定されている からです。
Config Sync は 管理対象リソースのマニフェストファイル だけを参照すべきで、自身の状態を定義したマニフェストファイルを参照させてはいけません。
ファイル確認
パイプラインをデプロイした際のファイル (gitops/configsync/rootsync.yaml
) を確認します。
dir
が config
になっています。config
とは source-repo
リポジトリ上のルートディレクトリ名を指しており、すなわち Config Sync の設定を含むリポジトリ全体 を参照するようになっています。
apiVersion: configsync.gke.io/v1beta1 kind: RootSync metadata: # kpt-merge: config-management-system/root-sync name: root-sync namespace: config-management-system annotations: internal.kpt.dev/upstream-identifier: 'configsync.gke.io|RootSync|config-management-system|root-sync' spec: sourceFormat: unstructured git: repo: https://source.developers.google.com/p/sandbox-cc-test-prj/r/deployment-repo # kpt-set: https://source.developers.google.com/p/${project-id}/r/${deployment-repo} revision: HEAD branch: main dir: config # kpt-set: ${configsync-dir} auth: gcpserviceaccount gcpServiceAccountEmail: sync-config-controller-1@sandbox-cc-test-prj.iam.gserviceaccount.com # kpt-set: sync-${cluster-name}@${project-id}.iam.gserviceaccount.com
対処方法
ランディングゾーンに関するマニフェストだけを参照するよう設定を修正します。
- Cloud Shell 上にある
gitops/configsync/setters.yaml
を開き、configsync-dir
の値をconfig/landing-zone
に変更します。
# 変更後 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: namespace: config-control # cluster-name must not exceed 25 characters in length cluster-name: cluster-name configsync-dir: config/landing-zone deployment-repo: deployment-repo project-id: project-id
- レンダリングを実行して
gitops/configsync/rootsync.yaml
のdir
に反映させます。
# レンダリング実行場所の確認 (gitops ディレクトリが表示されること) ls -l # レンダリング (戻り値は割愛) kpt fn render gitops/
# レンダリング後 apiVersion: configsync.gke.io/v1beta1 kind: RootSync metadata: # kpt-merge: config-management-system/root-sync name: root-sync namespace: config-management-system annotations: internal.kpt.dev/upstream-identifier: 'configsync.gke.io|RootSync|config-management-system|root-sync' spec: sourceFormat: unstructured git: repo: https://source.developers.google.com/p/sandbox-cc-test-prj/r/deployment-repo # kpt-set: https://source.developers.google.com/p/${project-id}/r/${deployment-repo} revision: HEAD branch: main dir: config/landing-zone # kpt-set: ${configsync-dir} auth: gcpserviceaccount gcpServiceAccountEmail: sync-config-controller-1@sandbox-cc-test-prj.iam.gserviceaccount.com # kpt-set: sync-${cluster-name}@${project-id}.iam.gserviceaccount.com
kubectl apply
で Config Sync の設定を適用 (変更) します。
# 適用 (戻り値は割愛) kubectl apply --wait -f gitops/ --recursive
- レンダリングしたファイルを
source-repo
リポジトリにpush
します。
# コマンド (戻り値は割愛) git add . git commit -m "update rootsync" git push
nomos status の再確認
再度 nomos status
を実行しエラーが解消されたことを確認します。
各リソースのステータスが Current
になっていればデプロイが完了しています。
# コマンド nomos status # 戻り値 *gke_sandbox-cc-test-prj_asia-northeast1_krmapihost-config-controller-1 -------------------- <root>:root-sync https://source.developers.google.com/p/sandbox-cc-test-prj/r/deployment-repo/config/landing-zone@main SYNCED @ 2023-08-18 10:47:07 +0000 UTC 2f1935299502189667f71e2c4d03de46728447e2 Managed resources: NAMESPACE NAME STATUS SOURCEHASH constrainttemplate.templates.gatekeeper.sh/gcpenforcenamingv2 Current 2f19352 constrainttemplate.templates.gatekeeper.sh/gcprequiredeletionpolicy Current 2f19352 namespace/hierarchy Current 2f19352 namespace/logging Current 2f19352 namespace/networking Current 2f19352 namespace/policies Current 2f19352 namespace/projects Current 2f19352 config-control iampartialpolicy.iam.cnrm.cloud.google.com/hierarchy-sa-workload-identity-binding Current 2f19352 config-control iampartialpolicy.iam.cnrm.cloud.google.com/logging-sa-workload-identity-binding Current 2f19352 config-control iampartialpolicy.iam.cnrm.cloud.google.com/networking-sa-workload-identity-binding Current 2f19352 config-control iampartialpolicy.iam.cnrm.cloud.google.com/policies-sa-workload-identity-binding Current 2f19352 config-control iampartialpolicy.iam.cnrm.cloud.google.com/projects-sa-workload-identity-binding Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/billing-admins-iam Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/hierarchy-sa-folderadmin-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/logging-sa-bigqueryadmin-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/logging-sa-logadmin-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/networking-sa-dns-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/networking-sa-networkadmin-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/networking-sa-security-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/networking-sa-service-control-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/networking-sa-xpnadmin-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/org-admins-iam Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/policies-sa-orgpolicyadmin-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/projects-sa-billinguser-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/projects-sa-projectcreator-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/projects-sa-projectdeleter-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/projects-sa-projectiamadmin-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/projects-sa-projectmover-permissions Current 2f19352 config-control iampolicymember.iam.cnrm.cloud.google.com/projects-sa-serviceusageadmin-permissions Current 2f19352 config-control iamserviceaccount.iam.cnrm.cloud.google.com/hierarchy-sa Current 2f19352 config-control iamserviceaccount.iam.cnrm.cloud.google.com/logging-sa Current 2f19352 config-control iamserviceaccount.iam.cnrm.cloud.google.com/networking-sa Current 2f19352 config-control iamserviceaccount.iam.cnrm.cloud.google.com/policies-sa Current 2f19352 config-control iamserviceaccount.iam.cnrm.cloud.google.com/projects-sa Current 2f19352 config-control service.serviceusage.cnrm.cloud.google.com/sandbox-cc-test-prj-cloudbilling Current 2f19352 config-control service.serviceusage.cnrm.cloud.google.com/sandbox-cc-test-prj-cloudresourcemanager Current 2f19352 config-control service.serviceusage.cnrm.cloud.google.com/sandbox-cc-test-prj-serviceusage Current 2f19352 hierarchy configconnectorcontext.core.cnrm.cloud.google.com/configconnectorcontext.core.cnrm.cloud.google.com Current 2f19352 hierarchy rolebinding.rbac.authorization.k8s.io/allow-resource-reference-from-hierarchy Current 2f19352 logging configconnectorcontext.core.cnrm.cloud.google.com/configconnectorcontext.core.cnrm.cloud.google.com Current 2f19352 networking configconnectorcontext.core.cnrm.cloud.google.com/configconnectorcontext.core.cnrm.cloud.google.com Current 2f19352 policies configconnectorcontext.core.cnrm.cloud.google.com/configconnectorcontext.core.cnrm.cloud.google.com Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/disable-guest-attributes Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/disable-iam-grants-default-sa Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/disable-nested-virtualization Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/disable-sa-key-creation Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/disable-serial-port Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/disable-vm-external-ip Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/enforce-uniform-bucket-lvl-access Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/restrict-cloud-sql-public-ip Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/restrict-lien-removal Current 2f19352 policies resourcemanagerpolicy.resourcemanager.cnrm.cloud.google.com/skip-default-network Current 2f19352 projects configconnectorcontext.core.cnrm.cloud.google.com/configconnectorcontext.core.cnrm.cloud.google.com Current 2f19352 projects rolebinding.rbac.authorization.k8s.io/allow-resource-reference-from-logging Current 2f19352 projects rolebinding.rbac.authorization.k8s.io/allow-resource-reference-from-networking Current 2f19352
動作確認
リソース
nomos status
でリソース状況を確認しましたが、実際に組織ポリシーがデプロイされたことを確認してみます。
Cloud コンソール > IAM と管理 > 組織のポリシー
と遷移したら、スコープを 組織
に切り替え、フィルタに constraints/sql.restrictPublicIp
と入力します。

ポリシー名をクリックすると、Cloud SQL にパブリック IP アドレスの付与を禁止するポリシーが有効化されていました。

Reconciliation Loop が働くことを確認するため、このポリシーを手動で削除します。
ポリシーを管理 > 親のポリシーを継承する
を選択し、ポリシーを設定
をクリックします。これにより、組織ポリシーの設定が初期化されます。


しばらく時間をおいて再確認すると、組織ポリシーが再適用されています。Reconciliation Loop が働きリソースがあるべき状態に戻りました。

GitOps パイプライン
リポジトリ
リポジトリは Cloud コンソール > Source Repositories
から確認できます。
source-repo
にはローカルリポジトリから push
したブループリント一式が格納されています。

対する deployment-repo
は、Cloud Build トリガーによるレンダリングで生成されたマニフェストファイルのみが格納されます。
Config Sync はこれら deployment-repo
に格納されたマニフェストファイルを参照しリソースをデプロイ・管理します。

Cloud Build トリガー
Cloud Build トリガーはグローバルリージョンにデプロイされています。
内容としては、source-repo
の push
をトリガーに、レンダリングされたファイルを deployment-repo
に push
する処理を実行します。

詳細は Build 履歴
から確認できます。

Config Sync
nomos status
だけでなく、Cloud コンソールからも Config Sync のステータスを確認できます。
Cloud コンソール > Anthos > Config
と遷移すると、Config Sync のダッシュボードが確認可能です。

パッケージ
タブに切り替えると、nomos status
同様 Config Sync によってデプロイされたリソースの状態が確認できます。

さいごに
公式ガイドではこの後フォルダやプロジェクトといったランディングゾーンリソースのデプロイへと続いていきますが、当記事では一旦ここで終了とします。
所感として、GitOps パイプラインでは Cloud Source Repositories を使用していますが、2023年8月時点ではプルリクエスト機能が搭載されていないため、GitHub をミラーしたリポジトリにカスタムすることでより利便性が向上すると思います。
今回の続きやリポジトリのカスタマイズについては今後記事にできればと思っています。
武井 祐介 (記事一覧)
2022年4月入社 / クラウドソリューション部 / 技術2課所属
趣味はゴルフにロードバイク。IaC や CI/CD 周りのサービスやプロダクトが興味分野です。
Google Cloud 認定全冠達成!(2023年6月)