命名空间继承和抽象命名空间

本页面介绍如何在 Config Sync 分层代码库中利用命名空间继承的概念。

根据代码库的结构,Config Sync 会自动将配置应用于所有存在(或应该存在)命名空间的集群中的命名空间组。这些命名空间称为抽象命名空间

非结构化代码库不支持命名空间继承和抽象命名空间。如果您使用的是非结构化代码库并希望实现类似功能,请使用层次结构控制器

命名空间继承功能的工作原理

命名空间继承适用于分层代码库及其所有子目录的 namespaces/ 目录。代码库中其他目录(例如 cluster/)下的配置不受继承功能的约束。

在分层代码库中,namespaces/ 目录可以包含两种不同类型的子目录:

  • 命名空间目录包含命名空间的配置。包含该配置的文件名称并不重要,但是这项配置必须具有 kind: Namespace。命名空间目录还可以包含其他类型的 Kubernetes 对象的配置。命名空间目录不能包含子目录。命名空间配置表示集群中的实际命名空间。

  • 抽象命名空间目录包含命名空间目录,还可以包含其他 Kubernetes 对象的配置,但不能直接包含命名空间的配置。抽象命名空间目录不代表 Kubernetes 集群中的对象,但其后代命名空间目录可以。

为了帮助确保您的命名空间和抽象命名空间代码库具有正确的配置和结构类型,请在出现问题时报告错误 KNV1003: IllegalNamespaceSubdirectoryError

命名空间目录中的配置仅应用于该命名空间。但是,抽象命名空间目录中的配置将应用于该抽象命名空间的所有后代命名空间目录(或者与配置的 NamespaceSelector(如果存在)匹配的后代命名空间)。

命名空间继承示例

配置中 namespaces/ 的继承在很大程度上取决于该配置在代码库中的目录树中的位置。如需了解哪些配置应用于给定集群中的给定命名空间,您可以浏览命名空间继承示例代码库

命名空间继承示例代码库中的 namespaces/ 目录具有以下架构:

├── namespaces # Abstract namespace directory
│   ├── eng # Abstract namespace directory
│   │   ├── analytics # Namespace directory
│   │   └── gamestore # Namespace directory
│   ├── rnd # Abstract namespace directory
│   │   ├── incubator-1 # Namespace directory
│   │   └── incubator-2 # Namespace directory
|   |── network-policy-default-deny-all.yaml
|   |── viewers-rolebinding.yaml

如需详细了解此示例代码库的工作原理,请先探索 viewers-rolebinding.yaml

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: viewers
subjects:
- kind: Group
  name: system:serviceaccounts:foo
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: view
  apiGroup: rbac.authorization.k8s.io

由于此 RoleBinding 位于 namespaces/ 目录的根目录中,因此它会向 system:serviceaccounts:foo 群组中的所有人授予 Config Sync 管理的每个命名空间中的 view ClusterRole。

接下来,通过浏览器中打开 namespaces/eng/ 目录。eng 目录是一个抽象命名空间目录,因为其中不包含命名空间的配置。eng 目录包含以下配置:

  • eng-role.yaml
  • eng-rolebinding.yaml
  • network-policy-allow-gamestore-ingress.yaml
  • quota.yaml
  • selectors.yaml

eng 目录也有两个子目录:analyticsgamestore。这些子目录是命名空间目录,因为它们分别包含命名空间的配置。在此示例中,命名空间配置称为 namespace.yaml,但您可以随意调用它们。analyticsgamestore 中的每个命名空间都会继承 eng 抽象命名空间目录中的 eng-role.yamleng-rolebinding.yamlnetwork-policy-allow-gamestore-ingress.yaml 配置。

quota.yaml 中定义的 ResourceQuota 对象使用 NamespaceSelector,因此此 ResourceQuota 对象仅在 analyticsgamestore 命名空间中创建。

gamestore 命名空间目录包含适用于 bob-rolebinding RoleBinding 的其他配置,但 analytics 命名空间目录不含此配置,因此 analytics 命名空间不包含该 RoleBinding(除非有人手动创建此绑定)。

命名空间继承代码库还具有 README.md 文件,其中进一步提供了命名空间继承的工作原理示例。

受限命名空间

config-management-system 是受限命名空间。您不能将其用作抽象命名空间目录。从 1.11.0 版及更高版本开始,您可以定义 config-management-system 命名空间。但是,config-management-system 命名空间唯一允许的资源类型是 RootSync

从继承中排除命名空间

您可以使用命名空间选择器豁免特定命名空间从树中继承资源。

以下示例允许根 /namespaces 目录中正确注释的 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

如需详细了解 Config Sync 中的 NamespaceSelectors,请参阅限制配置影响的命名空间

Git 操作对命名空间的影响

namespaces/ 目录中创建或删除命名空间目录的 Git 操作可能会产生与您最初的预期不同的效果。以下几个部分介绍了这些互动情况。

namespaces/ 中创建目录

当您将有效的 namespaces/ 层次结构提交到存储库时,Config Sync 会创建命名空间,然后在这些命名空间中为命名空间目录包含或继承的每项配置创建 Kubernetes 对象。

namespaces/ 中删除目录

删除命名空间目录是一种破坏性操作。此操作将从由 Config Sync 管理并包含相关命名空间的所有集群中删除该命名空间及其全部内容。

如果您删除包含后代命名空间目录的抽象命名空间目录,则所有这些命名空间及其内容都将从 Config Sync 管理的所有集群中删除。

重命名 namespaces/ 中的目录

重命名命名空间目录是在创建操作之后执行的删除操作,因此也是一种破坏性操作。

重命名抽象命名空间目录不会产生任何外部可见的影响。

移动 namespaces/ 中的目录

namespaces/ 中移动命名空间或抽象命名空间目录不会删除命名空间或其中的对象,除非命名空间由于其层次结构发生更改而开始或停止从抽象命名空间目录继承配置。

与层次结构控制器集成

层次结构控制器使您可以使用分层命名空间,这与抽象命名空间类似。层次结构控制器还支持额外的功能,例如分层资源配额自助命名空间

选择相关命名空间

有时,您可能希望将政策应用于通过共同祖先实体关联的命名空间集。层次结构控制器通过使用树标签的概念来支持此功能。即使未启用层次结构控制器,抽象命名空间也支持树标签。

树标签是具有以下格式的 Kubernetes 标签:

NAMESPACE_NAME.tree.hnc.x-k8s.io/depth: DEPTH

这些标签允许您编写命名空间选择器(例如,可以用作网络政策的一部分),以允许相关命名空间的子树内的流量,但禁止该子树外部的流量。

我们可通过返回示例代码库来说明此概念。

├── namespaces # Abstract namespace directory
│   ├── eng # Abstract namespace directory
│   │   ├── analytics # Namespace directory
│   │   └── gamestore # Namespace directory
│   ├── rnd # Abstract namespace directory
│   │   ├── incubator-1 # Namespace directory
│   │   └── incubator-2 # Namespace directory
|   |── network-policy-default-deny-all.yaml
|   |── viewers-rolebinding.yaml

假设在本例中,gamestore 抽象命名空间目录中的 namespace.yaml 具有以下树标签:

eng.tree.hnc.x-k8s.io/depth: "1"
gamestore.tree.hnc.x-k8s.io/depth: "0"

您可以使用 kubectl 命令直接在集群上检查这些关系,而无需访问 Git 代码库:

# View all descendants of 'eng'
kubectl get namespaces -l 'eng.tree.hnc.x-k8s.io/depth'

# View any immediate children of 'eng'
kubectl get namespaces -l 'eng.tree.hnc.x-k8s.io/depth=1'

层次结构控制器还会将任何树标签从抽象命名空间传播到任何后代命名空间。例如,如果您按如下方式创建 gamestore 的子命名空间:

kubectl hns create gamestore-v1 -n gamestore

在这种情况下,gamestore-v1 命名空间将包含其父级的所有标签以及其自身的标签,并适当调整深度:

eng.tree.hnc.x-k8s.io/depth: 2
gamestore-v1.tree.hnc.x-k8s.io/depth: 0
gamestore.tree.hnc.x-k8s.io/depth: 1

后续步骤