管理整个舰队中的团队资源

本页面介绍如何使用 Config Sync 和 Terraform 在一系列集群中动态创建团队级资源。Config Sync 扩展了舰队团队管理功能,可以在舰队中创建和管理基础架构与集群配置。

本指南假定您已熟悉舰队团队管理概念,例如团队范围和舰队命名空间。如需了解详情,请参阅舰队团队管理概览

如需查看包含示例配置的端到端教程,请参阅示例代码库中的舰队租户教程

如需查看 Terraform 中 Config Sync 支持的字段列表,请参阅有关 GKE 舰队功能的 Terraform 参考文档

工作流示例

您是平台管理员,希望在一组具有不同需求的集群之间动态创建资源。例如,您可能希望将 NetworkPolicy 应用于后端团队的命名空间,而不是前端团队的命名空间。在此场景中,在命名空间中创建团队级资源的过程如下:

  1. 选择或创建您要用来为团队管理资源的舰队。
  2. 设置可信来源。可信来源包含用于在团队范围内选择舰队级命名空间的 NamespaceSelector 对象,以及要在这些命名空间之间同步的任何资源(例如 NetworkPolicy)。
  3. 为 Config Sync 创建舰队级默认配置。从上一步中创建的可信来源进行同步时,Config Sync 会使用这些默认设置。这些 Config Sync 设置适用于在舰队中创建的任何新集群

  4. 在舰队中创建集群。

  5. 创建前端和后端团队范围和命名空间,以便 Config Sync 可以检测和协调命名空间中的资源。

完成这些步骤后,Config Sync 会根据 NamespaceSelector 创建 NetworkPolicy 并将其应用到后端团队的命名空间。如果您更改或添加任何资源,Config Sync 会持续检测任何更改并将其应用到您的配置文件、团队范围、舰队命名空间和舰队成员。

价格

Config Sync 和舰队团队管理功能仅适用于已启用 GKE Enterprise 的用户。如需详细了解 GKE Enterprise 价格,请参阅 GKE 价格页面

准备工作

  1. 登录您的 Google Cloud 账号。如果您是 Google Cloud 新手,请创建一个账号来评估我们的产品在实际场景中的表现。新客户还可获享 $300 赠金,用于运行、测试和部署工作负载。
  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_NAMENamespaceSelector 对象的名称,例如 backend-scope
    • SCOPE_NAME:团队范围的名称,例如 backend

    属于舰队命名空间的任何命名空间都会自动带有 fleet.gke.io/fleet-scope: SCOPE_NAME 标签。NamespaceSelector 会使用该标签选择团队范围的所有舰队命名空间。如需查看有关如何包含或排除命名空间的更多示例,请参阅 NamespaceSelector 示例

  3. 创建要跨命名空间同步的任何对象。

    如需将对象仅同步到特定团队,请在该对象的元数据中设置以下注解:

    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:包含配置文件的代码库的网址。
    • 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 映像代码库的网址。
    • DIRECTORY:包含要同步的资源的目录的绝对路径。留空以使用根目录。
    • SECRET:密钥身份验证类型。

    如需查看 Config Sync oci 代码块中支持的设置的完整列表,请参阅有关 GKE Hub 功能的 Terraform 参考文档

    例如,以下 main.tf 文件将 Config Sync 配置为从 Git 代码库进行同步,并同步 config 目录中存在的所有对象:

    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. 创建一个 cluster.tf 文件,其中包含在所有集群中使用的默认值,例如项目和舰队 ID:

    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
    

配置团队范围和舰队命名空间

在本部分中,您将创建团队范围并将集群与这些范围相关联。然后,您将在每个范围内创建所需的舰队命名空间(例如,为每个团队创建一个命名空间),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 中有三个集群,但 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 相同。

      例如,如果您希望前端和后端团队各拥有两个命名空间,则舰队命名空间资源可能如下所示:

      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 软件包标签页,并将查看方式单选按钮更改为集群,检查资源是否已应用于正确的集群。

前往“软件包”

Config Sync 会根据您的团队范围根据可信来源中存储的配置,在命名空间之间同步资源。每当您添加新资源,只要添加正确的 NamespaceSelector 注解,Config Sync 就会自动在团队命名空间中协调该资源。

如果要将 Config Sync 设置应用于现有集群,请参阅 Config Sync 安装指南中配置舰队级默认设置的说明。

后续步骤