将对象同步到多个命名空间

本页面介绍了如何使用 Config Sync 来管理命名空间,以及如何选择 Config Sync 要同步到命名空间的对象。

Kubernetes 资源对象可以是集群范围对象,也可以是命名空间范围对象,具体取决于资源类型。您可以通过配置客户端以与特定集群通信来选择集群。您可以通过在对象清单中配置 metadata.namespace 字段来选择命名空间。Config Sync 添加了其他功能:集群选择器和命名空间选择器,可让您进一步优化要同步的对象。

在阅读本页面之前,您应该已熟悉以下 Kubernetes 概念:

关于使用 Config Sync 确定对象范围

默认情况下,当您在集群上或作为舰队默认设置安装 Config Sync 时,Config Sync 会将可靠来源中的所有 Kubernetes 对象同步到安装了 Config Sync 的集群或舰队中的所有集群。不过,通过将对象限定为集群范围或命名空间范围,您可以控制哪些对象同步到集群或命名空间。

Config Sync 提供以下方法来限定对象的范围:

使用显式命名空间

我们建议您在配置 Config Sync 时使用显式命名空间声明,因为这样一来,您就可以管理命名空间元数据,并在日后需要时删除命名空间。

默认设置为 implicit,但您可以通过将 RootSyncRepoSync 对象中的 namespaceStrategy 字段设置为 explicit 来更改命名空间策略。如需了解详情,请参阅命名空间策略

关于命名空间选择器

命名空间选择器是 Config Sync 的一项功能,可让您将原本相同的资源对象部署到多个命名空间中。

使用命名空间选择器类似于使用 Kubernetes 标签选择器将Service映射到一组 pod,但多了一层间接寻址。由于您无法向现有资源类型添加自定义字段,因此您需要在 NamespaceSelector 对象中定义选择器。然后,您可以在要使用该选择器的对象的注解中按名称引用该选择器。

如需使用命名空间选择器,请执行以下操作:

  1. 在要部署到的命名空间中添加或选择现有标签。
  2. 在可靠来源中定义 NamespaceSelector 资源对象。 Config Sync 不会将 NamespaceSelector 对象同步到您的集群。
  3. 对于要同步到一个或多个命名空间的每个对象,请修改该对象的配置,以移除 metadata.namespace 字段并添加 configmanagement.gke.io/namespace-selector 注解,其值与 NamespaceSelectormetadata.name 匹配。

后续部分中的示例详细介绍了如何定义 NamespaceSelector 对象以及如何注解其他对象以使用 NamespaceSelector

准备工作

使用命名空间选择器

命名空间选择器可以通过基于等式的要求基于集合的要求来定义。您可以组合使用多个要求。

基于等式的标签选择器示例

以下示例展示了如何使用基于等式的选择器来选择配置所适用的命名空间:

  1. 向一个或多个命名空间添加标签:

    kubectl label namespace NAMESPACE app=gamestore
    

    NAMESPACE 替换为您的命名空间名称。

    针对要添加标签的每个命名空间运行此命令。

  2. 创建名为 gamestore-selector 的命名空间选择器。

    kind: NamespaceSelector
    apiVersion: configmanagement.gke.io/v1
    metadata:
      name: gamestore-selector
    spec:
      selector:
        matchLabels:
          app: gamestore
    

    如果另一对象的配置引用了此命名空间选择器,那么该配置只能应用于具有 app: gamestore 标签的命名空间中的对象。

  3. 除非您在另一项配置中引用命名空间选择器,否则该选择器不会产生任何作用。 创建引用命名空间选择器的示例对象配额:

    kind: ResourceQuota
    apiVersion: v1
    metadata:
      name: quota
      annotations:
        configmanagement.gke.io/namespace-selector: gamestore-selector
    spec:
      hard:
        pods: "1"
        cpu: "200m"
        memory: "200Mi"
    

    资源配额仅在具有 app: gamestore 标签的命名空间中创建。

基于集合的标签选择器示例

以下示例展示了如何使用基于集合的选择器来豁免命名空间继承对象:

  1. 向一个或多个命名空间添加标签:

    kubectl label namespace NAMESPACE quota-exempt=exempt
    

    NAMESPACE 替换为您的命名空间名称。

    针对要添加标签的每个命名空间运行此命令。

  2. 创建名为 exclude-exempt-namespaces 的命名空间选择器:

    kind: NamespaceSelector
    apiVersion: configmanagement.gke.io/v1
    metadata:
      name: excludes-exempt-namespaces
    spec:
      selector:
        matchExpressions:
          - key: quota-exempt
            operator: NotIn
              values:
                - exempt
    

    如果其他对象的配置引用了此命名空间选择器,那么该配置将应用于所有命名空间,具有 quota-exempt: exempt 键值对的命名空间除外。

  3. 除非您在另一项配置中引用命名空间选择器,否则该选择器不会产生任何作用。 创建引用命名空间选择器的示例对象配额:

    kind: ResourceQuota
    apiVersion: v1
    metadata:
      name: quota
      annotations:
        configmanagement.gke.io/namespace-selector: exclude-exempt-namespaces
    spec:
      hard:
        pods: "1"
        cpu: "200m"
        memory: "200Mi"
    

    资源配额是在除具有 quota-exempt: exempt 键值对的命名空间之外的所有命名空间中创建的。

与团队范围和舰队命名空间集成

在 Google Cloud 中创建的舰队命名空间会自动具有 fleet.gke.io/fleet-scope: your-scope 标签。所有命名空间还具有 Kubernetes kubernetes.io/metadata.name: your-namespace 标签。您可以使用这些默认标签来设置命名空间选择器,以用于选择舰队命名空间。

舰队租户教程更详细地介绍了如何将命名空间选择器与舰队和团队范围搭配使用,以便为不同团队选择性地管理对象。

分层模式下的命名空间范围对象

虽然我们建议在大多数使用情形下使用非结构化代码库,但您可以使用命名空间选择器,通过分层代码库限定对象的范围。命名空间选择器的使用方式相同,但对于如何在可靠来源中整理命名空间配置,还有一些额外的限制和要求。

限制

将命名空间选择器配置与分层代码库搭配使用时,请注意以下限制和要求:

  • 您必须将命名空间和命名空间范围对象的所有配置文件存储在分层代码库namespaces/ 目录及其后代目录中。
  • 您必须在 namespaces/NAMESPACE 子目录中明确指定命名空间配置,其中 NAMESPACE 与命名空间的名称匹配。所有其他命名空间范围对象都必须存储在同一子目录中。如果缺少命名空间配置,Config Sync 会返回 KNV1044 错误。
  • 引用命名空间选择器的资源会应用于从抽象命名空间继承指定配置的命名空间,无论 namespaces/ 目录的目录结构如何。

命名空间选择器位置

在分层代码库中,您可以将命名空间选择器配置放置在任何抽象命名空间目录中,但不能放置在命名空间目录中。

以下示例代码库架构显示了命名空间选择器的有效位置和无效位置:

namespace-inheritance
...
├── namespaces
│   ├── eng
│   │   ├── gamestore
│   │   │   ├── namespace.yaml
│   │   │   └── ns_selector.yaml  # invalid
│   │   └── ns_selector.yaml  # valid
│   ├── ns_selector.yaml  # valid
│   ├── rnd
│   │   ├── incubator-1
│   │   │   ├── namespace.yaml
│   │   │   └── ns_selector.yaml  # invalid
│   │   └── ns_selector.yaml  # valid

由于 namespacesengrnd 目录表示抽象命名空间,因此您可以在这些目录中添加选择器。但是,由于 gamestoreincubator-1 目录表示实际命名空间,因此您无法在这些命名空间中放置命名空间选择器。

配置抽象命名空间

对于分层代码库,您可以选择使用抽象命名空间。

以下示例展示了如何将命名空间目录移动到包含命名空间所继承的其他配置的抽象命名空间:

  1. 在代码库中,创建一个抽象命名空间目录。抽象命名空间目录不包含任何命名空间配置,但其后代命名空间目录包含配置。

  2. 在您创建的抽象命名空间目录中,为 Role 创建配置,以针对最终继承该 Role 的任何命名空间中的所有对象授予 getlist 权限:

    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: ROLE_NAME
    rules:
    - apiGroups: [""]
      resources: ["*"]
      verbs: ["get", "list"]
    

    ROLE_NAME 替换为角色的名称。

  3. 为角色绑定创建配置,以将角色绑定到邮件群组:

    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: ROLE_NAME
    subjects:
    - kind: Group
      name: group@example.com
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name:  ROLEBINDING_NAME
      apiGroup: rbac.authorization.k8s.io
    

    ROLEBINDING_NAME 替换为Role的名称。

  4. 将您在上一部分中创建的命名空间配置从 namespaces/ 目录移动到您在本部分中创建的抽象命名空间目录。

禁止继承对象

您可以有选择地针对任何配置停用继承功能,只需将 hierarchyMode 字段设置为 none 即可。HierarchyConfig 存储在存储库的 system/ 目录中。以下示例会禁止继承角色绑定。

# system/hierarchy-config.yaml
kind: HierarchyConfig
apiVersion: configmanagement.gke.io/v1
metadata:
  name: rbac
spec:
  resources:
  # Configure role to only be allowed in leaf namespaces.
  - group: rbac.authorization.k8s.io
    kinds: [ "RoleBinding" ]
    hierarchyMode: none