フリート全体のチームリソースを管理

このページでは、Config Sync と Terraform を使用してクラスタのフリート全体にチームスコープのリソースを動的に作成する方法について説明します。Config Sync は、フリートチーム管理の機能を拡張して、フリート全体でインフラストラクチャとクラスタ構成を作成および管理します。

このガイドは、チームスコープやフリートの名前空間などのフリートチーム管理のコンセプトにすでに精通していることを前提としています。詳細については、フリートチーム管理の概要をご覧ください。

サンプル構成を使用したエンドツーエンドのチュートリアルについては、サンプル リポジトリのフリート テナンシーのチュートリアルをご覧ください。

Terraform の Config Sync でサポートされているフィールドのリストについては、GKE フリート機能の Terraform リファレンス ドキュメントをご覧ください。

ワークフローの例

あなたは、プラットフォーム管理者で、チームごとに異なるニーズがあるクラスタのフリート全体にリソースを動的に作成しようとしている。たとえば、NetworkPolicy をバックエンド チームの名前空間に適用し、フロントエンド チームの名前空間には適用しないことができます。このシナリオでは、名前空間全体にチームスコープのリソースを作成する手順は次のとおりです。

  1. チームのリソースを管理するフリートを選択または作成します。
  2. 信頼できる情報源を設定する信頼できる情報源には、チームスコープでフリートレベルの名前空間を選択するために使用する NamespaceSelector オブジェクトと、それらの Namespace 間で同期するリソース(NetworkPolicy など)が含まれます。
  3. Config Sync のフリートレベルのデフォルト構成を作成します。Config Sync は、前の手順で作成した信頼できる情報源から同期するときに、これらのデフォルト設定を使用します。これらの Config Sync の設定は、フリートで作成された新しいクラスタに適用されます。

  4. フリートにクラスタを作成します。

  5. Config Sync が名前空間内のリソースを検出して調整できるように、フロントエンドおよびバックエンド チームのスコープと名前空間を作成します。

これらの手順を完了すると、Config Sync は NamespaceSelector に基づいて NetworkPolicy を作成し、バックエンド チームの Namespace に適用します。リソースを変更または追加すると、Config Sync が構成ファイル、チームスコープ、フリートの名前空間、フリート メンバーの変更を継続的に検出して適用します。

料金

Config Sync とフリートチームの管理機能は、GKE Enterprise を有効にしたユーザーのみが使用できます。GKE Enterprise の料金の詳細については、GKE の料金ページをご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Google Cloud CLI をインストールします。
  3. gcloud CLI を初期化するには:

    gcloud init
  4. Google Cloud プロジェクトを作成または選択します

    • Google Cloud プロジェクトを作成します。

      gcloud projects create PROJECT_ID

      PROJECT_ID は、作成する Google Cloud プロジェクトの名前に置き換えます。

    • 作成した Google Cloud プロジェクトを選択します。

      gcloud config set project PROJECT_ID

      PROJECT_ID は、実際の Google Cloud プロジェクト名に置き換えます。

  5. Google Cloud CLI をインストールします。
  6. gcloud CLI を初期化するには:

    gcloud init
  7. Google Cloud プロジェクトを作成または選択します

    • Google Cloud プロジェクトを作成します。

      gcloud projects create PROJECT_ID

      PROJECT_ID は、作成する Google Cloud プロジェクトの名前に置き換えます。

    • 作成した Google Cloud プロジェクトを選択します。

      gcloud config set project PROJECT_ID

      PROJECT_ID は、実際の Google Cloud プロジェクト名に置き換えます。

  8. 構成ファイルを保存できる信頼できる情報源(Git リポジトリまたは OCI イメージ)を作成するか、信頼できる情報源にアクセスする。このガイドの例では、Git リポジトリを使用します。

必要なロール

フリートのチームリソースを作成するために必要な権限を取得するには、プロジェクトに対して次の IAM ロールを付与するよう管理者に依頼してください。

ロールの付与の詳細については、アクセスの管理をご覧ください。

必要な権限は、カスタムロールや他の事前定義ロールから取得することもできます。

ユーザー認証情報を取得する

このガイドの Terraform コマンドをローカル環境で実行するには、次のコマンドを実行して新しいユーザー認証情報を取得します。

gcloud auth application-default login

フリートを設定する

このセクションでは、フリートを作成し、必要なサービスを有効にします。

フリートを設定するには、次の手順を行います。

  1. フリート構成の Terraform ファイルのディレクトリを作成します。そのディレクトリに、main.tf ファイルと variables.tf ファイルを追加します。

  2. variables.tf ファイルに次の行を追加します。

    variable "project" {
      type = string
      description = "GCP project ID"
    }

  3. main.tf ファイルに次の行を追加します。

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = ">= 5.16.0"
        }
      }
    }
    
    provider "google" {
      # project variable must be provided at runtime
      project = var.project
    }
    
    # Enable API services
    resource "google_project_service" "services" {
      for_each = toset([
        "gkehub.googleapis.com",
        "container.googleapis.com",
        "connectgateway.googleapis.com",
        "cloudresourcemanager.googleapis.com",
        "iam.googleapis.com",
        "anthos.googleapis.com",
        "anthosconfigmanagement.googleapis.com",
      ])
      service = each.value
      disable_on_destroy = false
    }
    
    # Declare a fleet in the project
    resource "google_gke_hub_fleet" "default" {
      display_name = "demo"
    
      depends_on = [google_project_service.services]
    }
  4. PROJECT_ID 変数をエクスポートします。

    export TF_VAR_project=PROJECT_ID
    

    PROJECT_ID は、フリートを作成するプロジェクト ID に置き換えます。

  5. 作成したディレクトリで Terraform を初期化します。

    terraform init
    
  6. Terraform で示した変更が、想定されているプランと一致していることを確認します。

    terraform plan
    
  7. フリートを作成し、API を有効にして、サービス アカウントを作成します。

    terraform apply
    

    すべてのサービスが有効になるまでに数分かかることがあります。

信頼できる情報源を設定する

このセクションでは、信頼できる情報源に構成ファイルを追加します。使用するチームスコープごとに NamespaceSelector オブジェクトが必要です。たとえば、フロントエンド チームとバックエンド チームがある場合は、チームごとに NamespaceSelector オブジェクトを作成する必要があります。NamespaceSelector オブジェクトは、チームスコープ内の名前空間のすべてまたは一部を選択します。信頼できる情報源に、NetworkPolicy などのチームリソースを追加できます。これらのリソースを作成する際、NamespaceSelector を参照し、Config Sync がこれらのリソースを名前空間間で動的にデプロイして同期できるようにします。

信頼できる情報源を設定するには、次の手順を行います。

  1. 信頼できる情報源で、Config Sync の同期元となる構成ファイルのディレクトリを作成します。

  2. チームごとに、構成ディレクトリに NamespaceSelector オブジェクトを作成します。

    apiVersion: configmanagement.gke.io/v1
    kind: NamespaceSelector
    metadata:
       name: NAMESPACE_SELECTOR_NAME
    spec:
      mode: dynamic
      selector:
        matchLabels:
          fleet.gke.io/fleet-scope: SCOPE_NAME
    

    次のように置き換えます。

    • NAMESPACE_SELECTOR_NAME: NamespaceSelector オブジェクトの名前(例: backend-scope)。
    • SCOPE_NAME: チームスコープの名前(例: backend)。

    フリートの名前空間の一部である名前空間には、自動的に fleet.gke.io/fleet-scope: SCOPE_NAME というラベルが付きます。NamespaceSelector は、そのラベルを使用するチームスコープのすべてのフリート名前空間を選択します。名前空間を含めるまたは除外する方法のその他の例については、NamespaceSelector の例をご覧ください。

  3. Namespace 間で同期するオブジェクトを作成します。

    オブジェクトを特定のチームのみと同期するには、そのオブジェクトのメタデータに次のアノテーションを設定します。

    annotations:
      configmanagement.gke.io/namespace-selector: NAMESPACE_SELECTOR_NAME
    

    たとえば、バックエンド チームの NetworkPolicy は次のようになります。

    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: be-deny-all
      annotations:
        configmanagement.gke.io/namespace-selector: backend-scope # Actuate this resource in the namespaces with labels matched by the namespace selector
    spec:
      ingress:
      - from:
        - podSelector: {}
      podSelector:
        matchLabels: null

Config Sync のフリートレベルのデフォルトを作成する

このセクションでは、Config Sync のフリートレベルのデフォルトを作成して、フリートで作成されたすべてのクラスタに同じ Config Sync 構成を適用します。

Config Sync のフリートレベルのデフォルト構成を作成するには、次の手順を行います。

  1. フリートのデフォルト構成の Terraform ファイルのディレクトリを作成します。そのディレクトリに、main.tf ファイルと variables.tf ファイルを追加します。

  2. variables.tf ファイルに次の行を追加します。

    variable "project" {
      type = string
      description = "GCP project ID"
    }

  3. main.tf ファイルに次のリソースを追加して、Config Sync の設定を構成します。

    git

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = ">=5.16.0"
         }
       }
     }
    
    provider "google" {
      project = var.project
    }
    
    resource "google_gke_hub_feature" "feature" {
      name = "configmanagement"
      location = "global"
      provider = google
      fleet_default_member_config {
        configmanagement {
        version = "VERSION"
     config_sync {
       source_format = "unstructured"
       git {
         sync_repo = "REPO"
         sync_branch = "BRANCH"
         policy_dir = "DIRECTORY"
         secret_type = "SECRET"
            }
          }
        }
      }
    }
    

    次のように置き換えます。

    • VERSION:(省略可)Config Sync のバージョン番号。バージョン 1.17.0 以降に設定する必要があります。空白のままにすると、デフォルトは最新バージョンです。
    • REPO: 構成ファイルを含むリポジトリの URL。
    • BRANCH: リポジトリ ブランチ(例: main)。
    • DIRECTORY: 同期するリポジトリの最上位レベルを表す Git リポジトリ内のパス。
    • SECRET: シークレット認証タイプ。

    Config Sync git ブロックでサポートされている設定の完全なリストについては、GKE Hub 機能の Terraform リファレンス ドキュメントをご覧ください。

    OCI

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = ">=5.16.0"
         }
       }
     }
    
    provider "google" {
      project = var.project
    }
    
    resource "google_gke_hub_feature" "feature" {
      name = "configmanagement"
      location = "global"
      provider = google
      fleet_default_member_config {
        configmanagement {
        version = "VERSION"
        config_sync {
        source_format = "unstructured"
        oci {
         sync_repo = "REPO"
         policy_dir = "DIRECTORY"
         secret_type = "SECRET"
         }
        }
        }
      }
    }
    

    次のように置き換えます。

    • VERSION: Config Sync のバージョン番号。バージョン 1.17.0 以降に設定する必要があります。空白のままにすると、デフォルトは最新バージョンです。
    • REPO: 構成ファイルを含む OCI イメージ リポジトリの URL。
    • DIRECTORY: 同期先のリソースを含むディレクトリの絶対パス。ルート ディレクトリを使用する場合は空白のままにします。
    • SECRET: シークレット認証タイプ。

    Config Sync oci ブロックでサポートされている設定の完全なリストについては、GKE Hub 機能の Terraform リファレンス ドキュメントをご覧ください。

    たとえば、次の main.tf ファイルは、Git リポジトリから同期し、config ディレクトリにあるすべてのオブジェクトを同期するように Config Sync を構成します。

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = ">= 5.16.0"
        }
      }
    }
    
    provider "google" {
      project = var.project
    }
    
    resource "google_gke_hub_feature" "feature" {
      name = "configmanagement"
      location = "global"
      provider = google
      fleet_default_member_config {
        configmanagement {
          # version = "1.17.0" # Use the default latest version; if specifying a version, it must be at or after 1.17.0
          config_sync {
            source_format = "unstructured"
            git {
              sync_repo = "https://github.com/GoogleCloudPlatform/anthos-config-management-samples"
              sync_branch = "main"
              policy_dir = "fleet-tenancy/config"
              secret_type = "none"
            }
          }
        }
      }
    }
  4. 作成したディレクトリで Terraform を初期化します。

    terraform init
    
  5. Terraform で示した変更が、想定されているプランと一致していることを確認します。

    terraform plan
    
  6. デフォルトのフリート メンバー構成を作成します。

    terraform apply
    

フリートにクラスタを作成する

このセクションでは、共有クラスタ構成を作成してから、フリートにクラスタを作成します。

新しいクラスタを作成してフリートに登録するには、次の手順を行います。

  1. クラスタ構成の Terraform ファイルのディレクトリを作成します。そのディレクトリに、main.tf ファイルと variables.tf ファイルを追加します。

  2. variables.tf ファイルに次の行を追加します。

    variable "project" {
      type = string
      description = "GCP project ID"
    }

  3. プロジェクト ID やフリート ID など、すべてのクラスタで使用されるデフォルト値を含む cluster.tf ファイルを作成します。

    variable "location" {
      type = string
    }
    
    variable "cluster_name" {
      type = string
    }
    
    data "google_project" "project" {
      provider = google
    }
    
    resource "google_container_cluster" "cluster" {
     provider = google
     name               = var.cluster_name
     location           = var.location
     initial_node_count = 3
     project = data.google_project.project.project_id
     fleet {
       project = data.google_project.project.project_id
     }
     workload_identity_config {
       workload_pool = "${data.google_project.project.project_id}.svc.id.goog"
     }
     deletion_protection = false
    }
    
  4. main.tf ファイルに次の行を追加します。

    terraform {
      required_providers {
        google = {
        source = "hashicorp/google"
        version = ">=5.16.0"
        }
      }
    }
    
    provider "google" {
      project = var.project
    }
    
    module "MODULE_NAME" {
      source = "CLUSTER_CONFIGURATION_FILEPATH"
      cluster_name = "CLUSTER_NAME"
      location="CLUSTER_LOCATION"
    }
    

    次のように置き換えます。

    • MODULE_NAME: クラスタ モジュールに付ける名前。MODULE_NAMECLUSTER_NAME は同じ値にできます(例: us-east-cluster)。
    • CLUSTER_CONFIGURATION_FILEPATH: 作成した cluster.tf ファイルへの相対パス。
    • CLUSTER_NAME: クラスタの名前。MODULE_NAMECLUSTER_NAME は同じ値にできます(例: us-east-cluster)。
    • CLUSTER_LOCATION: クラスタのロケーション(us-east1 など)。

    クラスタは必要な数だけ作成できます。たとえば、次の main.tf ファイルでは、異なるリージョンに 3 つのクラスタが作成されます。

    terraform {
      required_providers {
        google = {
          source = "hashicorp/google"
          version = ">= 5.16.0"
        }
      }
    }
    
    provider "google" {
      project = var.project
    }
    
    module "us-west-cluster" {
      source = "./cluster"
      cluster_name = "us-west-cluster"
      location="us-west1-a"
    }
    
    module "us-east-cluster" {
      source = "./cluster"
      cluster_name = "us-east-cluster"
      location="us-east1-b"
    }
    
    module "us-central-cluster" {
      source = "./cluster"
      cluster_name = "us-central-cluster"
      location="us-central1-c"
    }
  5. 作成したディレクトリで Terraform を初期化します。

    terraform init
    
  6. Terraform で示した変更が、想定されているプランと一致していることを確認します。

    terraform plan
    
  7. クラスタを作成します。

    terraform apply
    

チームスコープとフリートの名前空間を構成する

このセクションでは、チームスコープを作成し、クラスタをこれらのスコープに関連付けます。次に、スコープごとに必要なフリートの名前空間(たとえば、チームごとに 1 つ)を作成すると、Config Sync は名前空間全体にリソースを作成します。

チームのスコープと名前空間を構成するには、次の手順を完了します。

  1. チームスコープと名前空間構成の Terraform ファイルのディレクトリを作成します。そのディレクトリに、main.tf ファイルと variables.tf ファイルを追加します。

  2. variables.tf ファイルに次の行を追加します。

    variable "project" {
      type = string
      description = "GCP project ID"
    }
    

  3. main.tf ファイルに次の行を追加します。

    1. プロバイダ情報を追加します。

      terraform {
        required_providers {
          google = {
            source = "hashicorp/google"
            version = ">=5.16.0"
           }
         }
       }
      
      provider "google" {
        project = var.project
      }
      
    2. チームスコープのリソースを追加します。

      resource "google_gke_hub_scope" "scope" {
        provider = google
        for_each = toset([
          "SCOPE_NAME",
          "SCOPE_NAME_2",
        ])
        scope_id = each.value
      }
      

      次のように置き換えます。

      • SCOPE_NAME: チームスコープの名前(例: backend)。
      • SCOPE_NAME_2: 追加のチームスコープ(作成した場合)。

      チームスコープは必要な数だけ追加できます。フリートの名前空間がクラスタに作成されると、その名前空間には自動的に fleet.gke.io/fleet-scope: SCOPE_NAME というラベルが付けられ、Config Sync は Kubernetes のリソースの同期時に存在する NamespaceSelector ラベルに基づいて名前空間を選択できるようになります。

      たとえば、フロントエンド チームとバックエンド チームの両方のスコープを含むチームスコープの Terraform リソースは次のようになります。

      resource "google_gke_hub_scope" "scope" {
        provider = google
        for_each = toset([
          "backend",
          "frontend",
        ])
        scope_id = each.value
      }
    3. チームスコープに適用するクラスタごとにフリート メンバーシップ バインディングを追加します。

      resource "google_gke_hub_membership_binding" "membership-binding" {
        provider = google
        for_each = {
          MEMBERSHIP_BINDING_NAME = {
            membership_binding_id = "MEMBERSHIP_BINDING_ID"
            scope = google_gke_hub_scope.scope["SCOPE_NAME"].name
            membership_id = "CLUSTER_NAME"
            location = "CLUSTER_LOCATION"
          }
          MEMBERSHIP_BINDING_NAME_2 = {
            membership_binding_id = "MEMBERSHIP_BINDING_ID_2"
            scope = google_gke_hub_scope.scope["SCOPE_NAME_2"].name
            membership_id = "CLUSTER_NAME_2"
            location = "CLUSTER_LOCATION_2"
          }
        }
        membership_binding_id = each.value.membership_binding_id
        scope = each.value.scope
        membership_id = each.value.membership_id
        location = each.value.location
      
        depends_on = [google_gke_hub_scope.scope]
      }
      

      次のように置き換えます。

      • MEMBERSHIP_BINDING_NAME: メンバーシップ バインディング名(例: us-east-backend)。
      • MEMBERSIP_BINDING_ID: メンバーシップ バインディング ID。これは MEMBERSHIP_BINDING_NAME と同じでかまいません。
      • SCOPE_NAME: NamespaceSelector を作成したときにチームスコープに指定したラベルセレクタ(例: backend)。
      • CLUSTER_NAME: クラスタの作成時に作成したクラスタの名前(例: us-east-cluster)。
      • CLUSTER_LOCATION: クラスタのロケーション(例: us-east1)。

      クラスタごとにフリート メンバーシップ バインディングを定義する必要があります。クラスタのチームスコープを定義しない場合、そのクラスタはその名前空間に対して作成されません。たとえば、リージョン us-east1us-west1us-central1 に 3 つのクラスタがあり、us-central1 クラスタがフロントエンド チーム用(メンバーシップ バインディング リソース)である場合、次のようになります。

      resource "google_gke_hub_membership_binding" "membership-binding" {
        provider = google
        for_each = {
          us-east-backend = {
            membership_binding_id = "us-east-backend"
            scope = google_gke_hub_scope.scope["backend"].name
            membership_id = "us-east-cluster"
            location = "us-east1"
          }
          us-west-backend = {
            membership_binding_id = "us-west-backend"
            scope = google_gke_hub_scope.scope["backend"].name
            membership_id = "us-west-cluster"
            location = "us-west1"
          }
          us-east-frontend = {
            membership_binding_id = "us-east-frontend"
            scope = google_gke_hub_scope.scope["frontend"].name
            membership_id = "us-east-cluster"
            location = "us-east1"
          }
          us-west-frontend = {
            membership_binding_id = "us-west-frontend"
            scope = google_gke_hub_scope.scope["frontend"].name
            membership_id = "us-west-cluster"
            location = "us-west1"
          }
          us-central-frontend = {
            membership_binding_id = "us-central-frontend"
            scope = google_gke_hub_scope.scope["frontend"].name
            membership_id = "us-central-cluster"
            location = "us-central1"
          }
        }
      
        membership_binding_id = each.value.membership_binding_id
        scope = each.value.scope
        membership_id = each.value.membership_id
        location = each.value.location
      
        depends_on = [google_gke_hub_scope.scope]
      }
    4. チームに定義する名前空間を追加します。

      resource "google_gke_hub_namespace" "fleet_namespace" {
        provider = google
      
        for_each = {
          FLEET_NAMESPACE = {
            scope_id = "SCOPE_NAME"
            scope_namespace_id = "FLEET_NAMESPACE_ID"
            scope = google_gke_hub_scope.scope["SCOPE_NAME"].name
          }
          FLEET_NAMESPACE_2 = {
            scope_id = "SCOPE_NAME"
            scope_namespace_id = "FLEET_NAMESPACE_ID_2"
            scope = google_gke_hub_scope.scope["SCOPE_NAME"].name
          }
      
      }
      
        scope_namespace_id = each.value.scope_namespace_id
        scope_id = each.value.scope_id
        scope = each.value.scope
      
        depends_on = [google_gke_hub_scope.scope]
      }
      

      次のように置き換えます。

      • FLEET_NAMESPACE: 名前空間に付ける名前(backend-a など)。
      • SCOPE_NAME: NamespaceSelector を作成したときにチームスコープに指定したラベルセレクタ(例: backend)。
      • FLEET_NAMESPACE_ID: 名前空間 ID。これは FLEET_NAMESPACE と同じでかまいません。

      たとえば、フロントエンド チームとバックエンド チームの両方に 2 つの名前空間を割り当てる場合、フリートの名前空間リソースは次のようになります。

      resource "google_gke_hub_namespace" "fleet_namespace" {
        provider = google
      
        for_each = {
          bookstore = {
            scope_id = "backend"
            scope_namespace_id = "bookstore"
            scope = google_gke_hub_scope.scope["backend"].name
          }
          shoestore = {
            scope_id = "backend"
            scope_namespace_id = "shoestore"
            scope = google_gke_hub_scope.scope["backend"].name
          }
          frontend_a = {
            scope_id = "frontend"
            scope_namespace_id = "frontend-a"
            scope = google_gke_hub_scope.scope["frontend"].name
          }
          frontend_b = {
            scope_id = "frontend"
            scope_namespace_id = "frontend-b"
            scope = google_gke_hub_scope.scope["frontend"].name
          }
        }
      
        scope_namespace_id = each.value.scope_namespace_id
        scope_id = each.value.scope_id
        scope = each.value.scope
      
        depends_on = [google_gke_hub_scope.scope]
      }
  4. 作成したディレクトリで Terraform を初期化します。

    terraform init
    
  5. Terraform で示した変更が、想定されているプランと一致していることを確認します。

    terraform plan
    
  6. フリートのスコープと名前空間を作成します。

    terraform apply
    

フリート スコープと名前空間を作成すると、Config Sync は新しい名前空間とスコープを検出し、フリートの名前空間内のリソースを選択して、構成ファイルと調整します。

リソースが正しいクラスタに適用されていることを確認するには、nomos status を使用するか、Google Cloud コンソールで Config Sync の [パッケージ] タブにアクセスし、 [クラスタ] の [表示] ラジオボタンをオンにします。

[PACKAGES] に移動

Config Sync は、信頼できる情報源に保存されている構成に従って、チームのスコープに基づいて Namespace 間でリソースを同期します。新しいリソースを追加するたびに、正しい NamespaceSelector アノテーションを含める限り、Config Sync はチームの Namespace 全体でそのリソースを自動的に調整します。

Config Sync の設定を既存のクラスタに適用する場合は、Config Sync インストール ガイドのフリートレベルのデフォルトの構成の手順をご覧ください。

次のステップ