配置命名空间和命名空间级对象

本主题说明了如何使用 Config Sync 来管理命名空间和命名空间级对象。

配置命名空间

对于非结构化代码库和分层代码库,配置命名空间的方式有所不同。以下示例重点介绍了这些差异。

非结构化代码库

命名空间和命名空间级对象的配置可以位于代码库的目录或子目录中的任何位置。

完成以下步骤,以在每个已注册的集群中配置名为 gamestore 的命名空间:

  1. 创建一个包含以下内容的 namespace-gamestore.yaml 文件。

    apiVersion: v1
    kind: Namespace
    metadata:
      name: gamestore
    

    您只需要创建一个包含命名空间配置的 YAML 文件。

  2. 创建包含 namespace-gamestore.yaml 配置的提交,并将该提交推送到远程存储库:

    git add multirepo/root/namespace-gamestore.yaml
    git commit -m "Created gamestore namespace config"
    git push REMOTE_NAME BRANCH_NAME
    

    替换以下内容:

    • REMOTE_NAME:远程代码库的名称。
    • BRANCH_NAME:您要提交到的分支。

    此示例将文件添加到根目录,但您可以将此文件移动到代码库的任何子目录。

分层代码库

命名空间和命名空间级对象的所有配置都位于分层代码库namespaces/ 目录及其后代目录中。

请按照以下步骤在每个已注册的集群中配置名为 gamestore 的命名空间:

  1. 在代码库的本地克隆中,创建一个命名空间目录。命名空间目录包含命名空间的配置。命名空间目录的名称必须与命名空间的名称一致。在此示例中,命名空间目录名为 namespaces/gamestore

    mkdir namespaces/gamestore
    
  2. 在命名空间目录中,创建一个包含以下内容的 gamestore.yaml 文件:

    apiVersion: v1
    kind: Namespace
    metadata:
      name: gamestore
    

    metadata.name 必须与命名空间目录的名称相匹配。

  3. 创建包含 gamestore.yaml 配置的提交,并将该提交推送到远程存储库:

    git add namespaces/gamestore/gamestore.yaml
    git commit -m "Created gamestore namespace config"
    git push REMOTE_NAME BRANCH_NAME
    

    替换以下内容:

    • REMOTE_NAME:远程代码库的名称。
    • BRANCH_NAME:您要提交到的分支。

稍等片刻之后,系统就会在每个已注册的集群中创建 gamestore 命名空间。如需进行验证,请描述该命名空间:

kubectl describe namespace gamestore

如需移除配置并从已注册的集群中删除 gamestore 命名空间,请创建一项新的提交以移除相应文件,然后将该提交推送到远程代码库。如果要为分层代码库配置抽象命名空间,请不要移除配置。

配置命名空间级对象

在非结构化代码库中,您可以将命名空间级对象存储在任何目录或子目录中,而无需命名空间配置。如果缺少命名空间配置,Config Sync 会自动创建隐式命名空间对象,并将所有配置应用于该命名空间。

可以使用 namespaceStrategy 字段修改此行为。如果 namespaceStrategy 设置为 explicit,则 Config Sync 不会自动创建隐式命名空间对象。如需了解详情,请参阅命名空间策略

在分层代码库中,您必须在 namespaces/NAMESPACE 子目录中明确指定命名空间配置,其中 NAMESPACE 必须与命名空间的名称匹配。所有其他命名空间级配置也必须存储在同一子目录中。如果缺少命名空间配置,Config Sync 会返回 KNV1044 错误,表示缺少命名空间配置。

配置抽象命名空间

本部分仅适用于分层代码库,因为非结构化代码库不支持抽象命名空间。

此示例在配置命名空间中的示例基础上进行了延伸,将 gamestore 命名空间目录移动到包含 gamestore 命名空间所继承的其他配置的抽象命名空间。

  1. 在存储库的本地克隆中,创建一个名为 eng 的抽象命名空间目录:

    mkdir namespaces/eng
    

    抽象命名空间目录不包含命名空间的配置,但其后代命名空间目录包含该配置。

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

    # namespaces/eng/eng-role.yaml
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: eng-viewer
    rules:
    - apiGroups: [""]
      resources: ["*"]
      verbs: ["get", "list"]
    
  3. 为名为 eng-admin 的 RoleBinding 创建配置,以将 eng-viewer 角色绑定到 eng@example.com 群组:

    # namespaces/eng/eng-rolebinding.yaml
    kind: RoleBinding
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: eng-admin
    subjects:
    - kind: Group
      name: eng@example.com
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: eng-viewer
      apiGroup: rbac.authorization.k8s.io
    
  4. gamestore 命名空间目录从 namespaces/ 移动到 namespaces/eng/ 目录:

    mv namespaces/gamestore /namespaces/eng/
    
  5. 提交所有更改并将其推送到远程存储库。

Config Sync 会注意到这些更改,并将新的 Role 和 RoleBinding 应用于所有已注册集群上的 gamestore 命名空间。

如需移除这些配置并从已注册的集群中删除 gamestore 命名空间,您可以创建一个新提交实例来移除整个 eng 抽象命名空间,并将该实例推送到远程存储库。

限制受配置影响的集群

通常,Config Sync 会将配置应用到每个已注册的集群。如果配置位于分层代码库namespaces/ 子目录中,则 Config Sync 会先在每个集群中创建命名空间,然后再将所有继承的配置应用到该命名空间。如需根据每个集群的标签来限制特定配置影响的集群,请使用 ClusterSelector。如需了解详情,请参阅使用 ClusterSelector

限制受配置影响的命名空间

如需限制配置影响的命名空间,请使用 NamespaceSelector。NamespaceSelector 是一种使用 Kubernetes labelSelector 的特殊类型配置。您可以将 NamespaceSelector 与非结构化代码库分层代码库中命名空间级对象的配置一起声明,以限制哪些命名空间可以继承该配置。注意:NamespaceSelector 与 ClusterSelector 相似,但不完全相同。NamespaceSelector 缩小配置所适用的命名空间池。

要声明 NamespaceSelector,请添加 metadata.namespaceNamespaceSelector 注释。如果同时声明这两个注释,则这样的声明是无效的。如果命名空间级资源未声明 metadata.namespaceNamespaceSelector 注释,则 Config Sync 使用集群的“默认”命名空间。

非结构化代码库中的 NamespaceSelector

非结构化代码库不必为代码库中的命名空间级对象声明所有命名空间。对象可以定义 metadata.namespace,但非结构化代码库中没有匹配的命名空间对象。如果集群上已存在命名空间,Config Sync 会在该命名空间内创建对象。如果集群上不存在该命名空间,Config Sync 会隐式地创建命名空间。

在创建包含以前在分层代码库中使用的对象的非结构化代码库之前,请验证 NamespaceSelectors 是否不适用于其他资源。

当您从非结构化代码库中移除命名空间级对象时,Config Sync 会删除这些对象,但不会移除可能已为这些对象隐式创建的任何命名空间。之所以发生行为,是因为 Config Sync 无法推断出何时才能安全地删除隐式创建的命名空间,因此此命名空间会始终保留在集群上。

NamespaceSelector 模式

在非结构化代码库中,声明 NamespaceSelector 注解的对象会应用于满足 NamespaceSelector 条件的所有命名空间。在 1.17.0 之前的 Config Sync 版本中,NamespaceSelector 注解仅适用于在可靠来源中静态声明的匹配命名空间。在 1.17.0 版及更高版本中,NamespaceSelector 对象通过将 spec.mode 设置为 dynamic 来支持动态模式。在动态模式下,选择范围会扩展到静态声明的命名空间和动态存在于集群上的命名空间。动态选择的命名空间已存在于集群上,因此不由 Config Sync 管理。默认模式为 static

分层代码库中的 NamespaceSelector

在分层代码库中,无论 namespaces/ 目录的目录结构如何,声明 NamespaceSelector 注解的对象都会应用于从抽象命名空间继承指定配置的命名空间。无论一项配置是针对集群级对象还是命名空间级对象,ClusterSelector 都会将该配置所适用的集群池缩小到一定的范围。

NamespaceSelector 位置

在非结构化代码库中,您可以将 NamespaceSelector 置于任何目录或子目录中。

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

以下示例代码库架构显示了使用分层代码库时 NamespaceSelector 的有效位置和无效位置:

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 目录表示实际命名空间,因此您无法在这些命名空间中放置 NamespaceSelector。

NamespaceSelector 示例

您可以将 NamespaceSelector 与标签选择器搭配使用,以包含或排除命名空间。Kubernetes 支持基于等式和基于集合的选择器。您可以结合使用这两种类型的选择器,以进一步优化所选的命名空间。

基于等式的标签选择器

以下配置会创建一个名为 gamestore-selector 的 NamespaceSelector。如果您在另一项配置中引用了此 NamespaceSelector,那么该配置只能应用于具有 app: gamestore 标签的命名空间中的对象。

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

如需在配置中引用 NamespaceSelector,请将 configmanagement.gke.io/namespace-selector 注释设置为 NamespaceSelector 的名称。

当您在另一个配置中引用 NamespaceSelector 之后,该 NamespaceSelector 才会生效。 如果 gamestore-selector NamespaceSelector 位于与以下 ResourceQuota quota 相同的层次结构中,那么系统将仅在具有 app: gamestore 标签的命名空间中创建 ResourceQuota:

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

总而言之,使用 NamespaceSelector 的过程分为三个步骤:

  1. 向 Namespace 添加标签。
  2. 创建 NamespaceSelector 配置。
  3. 在另一个配置中引用 NamespaceSelector 对象。

基于集合的标签选择器

您可以通过基于集合的标签选择器,使用命名空间选择器豁免特定命名空间从树中继承资源。

在此示例中,当设置注解 configmanagement.gke.io/namespace-selector: excludes-exempt-namespaces 以便通过 NamespaceSelectorResourceQuota 添加注解时,系统会在每个命名空间中都创建 ResourceQuota,但带有标签 quota-exempt: exempt 的任何命名空间除外:

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

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

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

禁止继承某个对象类型

非结构化代码库不支持 HierarchyConfig Kubernetes 对象。 以下示例仅适用于分层代码库

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

# 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

后续步骤