命名空间继承概览

本页面介绍 Anthos Config Management 如何根据代码库的结构将配置应用于层次结构中属于您集群的命名空间。 您还可以了解如何配置命名空间和命名空间级对象

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

Anthos Config Management 最强大的一个方面是能够根据配置在代码库中的位置,在存在(或应该存在)命名空间的所有集群中自动将配置应用于命名空间组。

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

存储库中,namespaces/ 目录可以包含两种不同类型的子目录:

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

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

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

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

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

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

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

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

现在,通过浏览器中打开 namespaces/online/ 目录。online 目录是一个抽象命名空间目录,因为其中不包含命名空间的配置。点击 shipping-app-backend 目录。该目录也是抽象命名空间目录,其中包含两项配置(pod-creator-rolebinding.yamlquota.yaml)。它的三个子目录都是命名空间目录,因为其中包含命名空间的配置。该文件的名称并不重要,但按照惯例,此代码库会对所有命名空间配置使用该文件名。其中每个命名空间都会继承 shipping-app-backend 抽象命名空间目录中的 pod-creator-rolebinding.yamlquota.yaml 配置。

shipping-dev 命名空间目录包含 job-creators RoleBinding 的附加配置,但其他两个命名空间目录不含这项配置,因此它们不具有该 RoleBinding(除非有人手动创建此绑定)。

namespaces/ 中不允许使用的名称

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

  • config-management-system

示例配置

命名空间配置

此配置会创建一个名为 audit 的命名空间。

apiVersion: v1
kind: Namespace
metadata:
  name: audit

创建命名空间配置时,您还可以向该命名空间添加标签。在与 NamespaceSelector 结合使用时,这种做法非常实用。

以下配置会在名为 shipping-prod 的命名空间尚不存在时创建该命名空间,以及在该命名空间已存在但尚无 configmanagement.gke.io/managed 标签时为其分配 env: prod。这项配置还会确保该命名空间的 audit 注释设置为 true。如果有人手动修改或删除该注释,Anthos Config Management 会快速将其重置为配置中的值。

apiVersion: v1
kind: Namespace
metadata:
  name: shipping-prod
  labels:
    env: prod
  annotations:
    audit: "true"

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。

从继承中排除命名空间

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

以下示例允许根 /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

如需详细了解 Anthos Config Management 中的 NamesspaceSelectors,请参阅受配置影响的命名空间限制

Git 操作对命名空间的影响

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

namespaces/ 中创建目录

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

namespaces/ 中删除目录

删除命名空间目录是一种破坏性操作。此操作将从由 Anthos Config Management 管理并存在命名空间的每个集群上删除命名空间及其所有内容。

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

重命名 namespaces/ 中的目录

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

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

移动 namespaces/ 中的目录

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

与层次结构控制器集成

层次结构控制器与抽象命名空间支持的命名空间继承概念非常相似,如层次结构控制器文档中所述。

选择相关命名空间

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

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

<namespace-name>.tree.hnc.x-k8s.io/depth: <depth>

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

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

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

例如,shipping-prod 命名空间具有以下树标签:

shipping-prod.tree.hnc.x-k8s.io/depth: 0
shipping-app-backend.tree.hnc.x-k8s.io/depth: 1
online.tree.hnc.x-k8s.io/depth: 2
root.tree.hnc.x-k8s.io/depth: 3

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

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

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

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

kubectl hns create shipping-prod-v1 -n shipping-prod

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

shipping-prod-v1.tree.hnc.x-k8s.io/depth: 0
shipping-prod.tree.hnc.x-k8s.io/depth: 1
shipping-app-backend.tree.hnc.x-k8s.io/depth: 2
online.tree.hnc.x-k8s.io/depth: 3
root.tree.hnc.x-k8s.io/depth: 4

后续步骤