on
Kubernetes 层级命名空间 HNC - 3 Why
为什么使用 namespaces?
在深入讨论层级空间前,我们有必要先考虑一下为何 Kubernetes 使用了命名空间的概念。
首先,也是最重要的,命名空间提供了一种组织 Kubernetes 对象的方式,可以防止同名问题,即集群中的任何 Kind 的实例对象命名必须唯一的问题。对于不同的 Kind 对象命名是可以相同的,但是同一种对象在同一命名空间下是不允许重现重名。对于 Kubernetes 用户,这也有利于用户使用简短的命名,如 frontend 或 database, 而不必担心在集群中产生命名冲突。
其次,重要也很巧妙的设计是,在控制面中命名空间是安全隔离的主要单元和身份标示。他们具有排他性,也就是说,命名空间中的对象属于且仅属于一个命名空间。如上所述,它将对象进行分组。这些分组的独立性使他们可以自然的关联一组相关的对象。 例如,命名空间被作为各种策略的默认目标,如 RoleBinding, Network Policies, 这也适用于 Kubernetes 扩展,如 Istio Polices。
当然,在命名空间内应用策略也是可行的,但是 Kubernetes 对他的支持有限,且容易引起错误,同时在 Kuberenets 生态系统中容易使用户产生困惑。例如,RBAC 策略可以应用于目标对象的名称,但是这些策略很难以维护。
再如,命名空间中的 Pod 可以使用同空间下的任何 Service Account 运行, 甚至是远超过 Pod 运行所需的特权。管理员在不借助 Validting Admission Contoller 或 OPA Gatekeeper 等高级技术情况下,通常无法直接限制。结果是,作用于 Service Account 的各种策略是弱策略,除非这些 Service Account 来自不同的命名空间。
总之,命名空间对于组织架构,安全及工作负载身份起到了至关重要的作用。
为什么使用层级命名空间?
由于命名空间非常有用,你可能会发现你在集群中创建了非常多的命名空间。然而,就像如果没有命名空间,对象就难以管理一样。你会发现管理大量命名空间时你会遇见如下问题:
- 你可能希望为很多命名空间应用相同的策略,如允许 team 中的所有成员访问他们。然而,由于 RoleBinding 是每个命名空间下的独立资源,你必须为每一个命名空间创建 RoleBinding, 这将是个枯燥乏味且容易出错的过程。同样的问题也出现在其他的策略中,如 Network Polices 和 Limit Ranges。
- 同样,你可能希望一些 Team 可以自己创建命名空间,使他们的服务在隔离的命名空间中运行。然而,创建命名空间是集群级别权限,通常你希望密切的控制这些权限。
- 最后,你可能希望避免为每个命名空间找到一个唯一命名。
层级命名空间通过将命名空间组织为树状结构,并允许你将策略应用于这些树或子树,以及在这些树中创建子命名空间,以帮助你解决前面两个问题。
然而,由于 Kubernetes 本身的限制,HNC 无法接触命名空间名称必须唯一的问题。但是,在实践过程中这通常并不是一个严格的需求。
何时不应使用层级命名空间?
层级结构是表示拥有关系及应用策略的理想模式,然而他们是一维结构 – 一个命名空间只能有一个父空间。然而现实世界往往更加复杂,你可能希望根据拥有者在命名空间上应用一组策略,但是其他策略也许是依赖于它环境(如 staging 和 prod)或是运行方式(如,批处理和实时)。
Lable 是种与层级空间不同,但可以应用于这些场景的更灵活的策略, 但是他们也有自身的缺点:
- Kubernetes 中 Label 几乎没有任何权限控制,如果你有编辑对象的权限,就可以编辑任何你期望的标签。这并不适用于使用策略的场景,除非你信任每个编辑者。
- Label 更加灵活的同时,也增加了出错的可能性。
如果层级空间不能适用于你的需求,你可以借助其他的工具如 Namespace Configuration Operator 或Anthos Config Management。你也可以使用 OPA Gatekeeper 等工具保证 Label 被正确的应用。