命名空间继承概览

本页面介绍 Config Sync 如何根据分层代码库的结构将配置应用于层次结构中属于您集群的命名空间。您还可以了解如何配置命名空间和命名空间级对象。 对于非结构化代码库,您可以使用层次结构控制器实现类似功能。

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

Config Sync 最强大的方面之一是能够根据配置在分层存储库中的位置,自动将配置应用于命名空间组,在这些命名空间存在(或应该存在)的所有集群中。

Config Sync 在存储库的 namespaces/ 目录及其所有子目录中引入了继承概念。存储库中其他目录(例如 cluster/)下的配置不受继承功能的约束。

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

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

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

如果您忘记将命名空间的配置添加到命名空间目录,或者您将目录添加到命名空间子目录,或将命名空间的配置添加到抽象命名空间目录,则结果会出错:KNV1003: IllegalNamespaceSubdirectoryError

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

因为 namespaces/ 目录中某项配置的继承情况很大程度上取决于该配置在存储库目录树中的位置,所以您可以浏览存储库来了解哪些配置应用于指定集群中的指定命名空间。

下图显示了命名空间继承示例代码库namespaces/ 目录中配置的继承方式。蓝色矩形表示抽象命名空间目录,橙色矩形表示 Kubernetes 中的实际命名空间。

显示示例代码库中的配置继承情况的图表

例如,通过浏览器打开 viewers-rolebinding.yaml 文件。该文件会在每个已注册集群的每个命名空间(由 Config Sync 管理)中向 system:serviceaccounts:foo 群组中的所有人授予 view ClusterRole,因为它位于 namespaces 目录本身中。

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

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

它的两个子目录都是命名空间目录,因为其中包含命名空间的配置。该文件的名称并不重要,但按照惯例,此代码库会对所有命名空间配置使用该文件名。其中每个命名空间都会继承 eng 抽象命名空间目录中的 eng-role.yamleng-rolebinding.yamlnetwork-policy-allow-gamestore-ingress.yaml 配置。quota.yaml 中定义的 ResourceQuota 对象仅适用于与对应 NamespaceSelector 匹配的命名空间。

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

namespaces/ 中不允许使用的名称

以下名称均预留给系统,不得用作存储库 namespaces/ 目录中的命名空间或抽象命名空间目录:

  • config-management-system

示例配置

ResourceQuota 配置

本示例会创建一个名为 quota 的 ResourceQuota,该对象设置了硬性限制,即 1 个 Pod、0.1 CPU(100 milli-CPU)和 100 MiB 内存。

kind: ResourceQuota
apiVersion: v1
metadata:
  name: quota
spec:
  hard:
    pods: "1"
    cpu: "100m"
    memory: 100Mi

如果将该配置放入应用于特定命名空间的目录 (namespaces/[NAMESPACE_NAME]) 中,那么这项配置将仅应用于该命名空间。如果将该配置放入包含命名空间后代的抽象名称空间目录 (namespaces/) 中,那么系统会对每个后代命名空间应用不同的 ResourceQuota。 如果您使用 NamespaceSelector 注释创建 ResourceQuota,则配置将仅应用于与 NamespaceSelector 匹配的命名空间。

从继承中排除命名空间

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

以下示例允许根 /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 中的 NamesspaceSelectors,请参阅限制配置影响的命名空间

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>

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

我们可通过回顾示例代码库的图表来说明此概念。

显示示例代码库中的配置继承情况的图表

例如,gamestore 命名空间具有以下树标签:

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

后续步骤