在舰队中管理团队资源

本页面介绍如何使用 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. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  5. 安装 Google Cloud CLI。
  6. 如需初始化 gcloud CLI,请运行以下命令:

    gcloud init
  7. Create or select a Google Cloud project.

    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  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_NAMENamespaceSelector 会使用该标签选择某个团队范围的所有舰队命名空间。如需查看有关如何包含或排除命名空间的更多示例,请参阅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 配置应用于舰队中创建的所有集群。

如需为 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 安装指南中有关配置舰队级默认设置的说明。

后续步骤