本文已超过一年。较旧的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes 命名空间:用例和见解

“谁在一垒,什么在二垒,我不知道在三垒” 

谁在一垒? 作者:Abbott 和 Costello

简介

Kubernetes 是一个包含多个概念的系统。其中许多概念在 RESTful API 中体现为“对象”(通常称为“资源”或“种类”)。其中一个概念是 命名空间。在 Kubernetes 中,命名空间是将单个 Kubernetes 集群划分为多个虚拟集群的方式。在本文中,我们将重点介绍我们的客户如何使用命名空间的示例。 

但首先,我们来打个比方:命名空间就像人类的姓氏。例如,姓氏“王”标识一个家庭单元。在王家内部,其中一位成员,例如王山,在家里可以直接被称为“山”。在家庭之外,为了避免“哪个山?”的问题,王山通常会被称为“王山”,甚至可能是“来自旧金山的王山”。  

命名空间是一种逻辑分区功能,它允许多个用户、用户团队或具有多个应用程序的单个用户使用一个 Kubernetes 集群,而无需担心不必要的交互。每个用户、用户团队或应用程序可以存在于其命名空间内,与集群的每个其他用户隔离,并且如同它是集群的唯一用户一样运行。(此外,资源配额提供了将 Kubernetes 集群资源的一个子集分配给命名空间的功能。)

对于 Kubernetes 的所有非最简单的用法,你都将受益于使用命名空间。在本文中,我们将介绍我们在 Google 云平台上看到的 Kubernetes 用户使用命名空间的最常见方式,但我们的列表并非详尽无遗,我们很乐意了解你的其他示例。

涵盖的用例

  • 企业中命名空间的角色和职责
  • 分区环境:开发 vs. 测试 vs. 生产
  • 非多租户场景的客户分区
  • 何时不使用命名空间

用例 1:企业中的角色和职责

一个典型的企业包含多个彼此独立运营的业务/技术实体,并通过企业本身管理某种形式的总体控制层。当定义了与 Kubernetes 相关的角色和职责时,在此环境中有效地运营 Kubernetes 集群是可行的。 

以下是一些建议的角色及其职责,这些角色和职责可以使大型组织中 Kubernetes 集群的管理更容易。

  • 设计者/架构师角色:此角色将定义整体命名空间策略,考虑到产品/位置/团队/成本中心,并确定如何最好地将它们映射到 Kubernetes 命名空间。为此角色投入资源可以防止命名空间的激增和“雪花”命名空间。
  • 管理员角色:此角色对所有 Kubernetes 集群具有管理员访问权限。管理员可以创建/删除集群并添加/删除节点以扩展集群。此角色将负责修补、保护和维护集群。以及在组织中不同实体之间实施配额。Kubernetes 管理员负责实施设计者/架构师定义的命名空间策略。 

这两个角色以及使用集群的实际开发人员还将收到来自企业安全和网络团队的支持和反馈,内容涉及诸如安全隔离要求以及命名空间如何适应此模型之类的问题,或者有关网络子网和负载均衡器设置的帮助。

反模式

  1. 没有集中控制的孤立 Kubernetes 使用“孤岛”:如果不在围绕 Kubernetes 管理建立集中控制结构方面进行初步投资,则存在最终形成“蘑菇农场”拓扑的风险,即组织内没有定义的集群大小/形状/结构。结果是难以管理,风险较高,并且由于资源利用率不足而导致成本增加。
  2. 旧世界的 IT 控制扼杀使用和创新:一种常见的趋势是尝试将现有的本地控制/程序转移到新的动态框架上。这导致这些框架的敏捷性受到限制,并抵消了快速动态部署的好处。
  3. 全能集群:延迟创建命名空间管理结构/机制的工作可能会导致形成一个大型全能集群,该集群很难分解成较小的使用组。 

用例 2:使用命名空间分区开发环境

软件开发团队通常将其开发管道划分为离散的单元。这些单元采用各种形式并使用各种标签,但往往会产生一个离散的开发环境、一个测试|QA 环境、可能一个暂存环境,最后是一个生产环境。生成的布局非常适合 Kubernetes 命名空间。管道中的每个环境或阶段都成为一个唯一的命名空间。

上述方法运作良好,因为每个命名空间都可以被模板化并镜像到开发周期中的下一个后续环境,例如,dev->qa->prod。每个命名空间在逻辑上是离散的事实使得开发团队可以在隔离的“开发”命名空间内工作。DevOps(Google 中最接近的角色称为站点可靠性工程“SRE”)将负责在管道中迁移代码,并确保为每个环境分配了适当的团队。最终,DevOps 全权负责最终的生产环境,在该环境中将解决方案交付给最终用户。

将命名空间应用于开发周期的主要好处是,可以维护软件组件(例如,微服务/端点)的命名,而不会在不同的环境中发生冲突。这是由于 Kubernetes 命名空间的隔离,例如,dev 中的 serviceX 将在所有其他命名空间中被这样引用;但是,如果需要,可以使用其完全限定名称 serviceX.development.mycluster.com 在 mycluster.com 的开发命名空间中唯一引用它。

反模式

  1. 滥用命名空间的好处会导致开发管道中出现不必要的环境。因此;如果你不进行暂存部署,请不要创建“暂存”命名空间。
  2. 过度拥挤的命名空间,例如,将你的所有开发项目放在一个巨大的“开发”命名空间中。由于命名空间试图进行分区,因此也使用这些来按项目进行分区。由于命名空间是扁平的,因此你可能希望类似以下内容:projectA-dev、projectA-prod 作为 projectA 的命名空间。

用例 3:你的客户的分区

例如,如果您是一家咨询公司,希望为每个客户管理单独的应用程序,那么命名空间提供的分区功能非常适合。您可以为每个客户、客户项目或客户业务部门创建一个单独的命名空间,以保持它们的独立性,而无需担心跨项目重复使用相同的资源名称。

这里一个重要的考虑因素是,Kubernetes 目前没有提供跨命名空间强制执行访问控制的机制,因此我们建议您不要将使用此方法开发的应用程序对外暴露。

反模式

  1. 多租户应用程序不需要 Kubernetes 命名空间的额外复杂性,因为应用程序已经强制执行了这种分区。
  2. 客户到命名空间的不一致映射。例如,您在全球企业中赢得了业务,您可能最初会考虑为整个企业设置一个命名空间,而没有考虑到该客户可能更喜欢进一步的分区,例如 BigCorp 会计和 BigCorp 工程。在这种情况下,客户的每个部门都可能需要一个命名空间。

何时不使用命名空间

在某些情况下,Kubernetes 命名空间将无法提供您需要的隔离。这可能是由于地理、计费或安全因素造成的。尽管命名空间具有逻辑分区的优势,但目前还无法强制执行分区。Kubernetes 集群中的任何用户或资源都可以访问集群中的任何其他资源,而不管命名空间如何。因此,如果您需要保护或隔离资源,那么最终的命名空间是一个单独的 Kubernetes 集群,您可以在其中应用常规的安全|ACL 控制。

另一个可能考虑不使用命名空间的情况是,当您希望反映地理分布的部署时。如果您希望部署在美国、欧盟和亚洲客户附近,建议在每个区域本地部署一个 Kubernetes 集群。

当需要细粒度的计费时,例如按成本中心或按客户进行回款,建议将计费委托给您的基础设施提供商。例如,在 Google Cloud Platform (GCP) 中,您可以使用单独的 GCP 项目结算帐户,并将 Kubernetes 集群部署到特定客户的项目中。

在需要客户之间完全不透明的保密性或合规性情况下,每个客户/工作负载一个 Kubernetes 集群将提供所需的隔离级别。同样,您应该将资源的分区委托给您的提供商。

目前正在努力提供 (a) Kubernetes 命名空间上的 ACL,以能够强制执行安全性;(b) 提供 Kubernetes 集群联邦。这两种机制都将解决这些反模式中单独 Kubernetes 集群的原因。

一个容易理解的 Kubernetes 命名空间的**反模式**是版本控制。您不应使用命名空间作为消除 Kubernetes 资源版本歧义的方法。容器和容器注册表以及 Kubernetes Deployment 资源中都存在对版本控制的支持。多个版本应该通过利用 Kubernetes 容器模型共存,该模型还提供了使用部署在版本之间自动迁移的功能。此外,版本范围的命名空间会导致集群内命名空间的大量增殖,使其难以管理。

注意主管

您可能希望,但您不能创建命名空间的层次结构。命名空间不能相互嵌套。例如,您不能创建 my-team.my-org 作为命名空间,但可能可以创建 team-org。

命名空间易于创建和使用,但也容易无意中将代码部署到错误的命名空间中。良好的 DevOps 实践建议记录和自动化流程,这将有所帮助。避免使用错误命名空间的另一种方法是设置一个 kubectl 上下文

如前所述,Kubernetes (目前) 没有提供跨命名空间强制执行安全性的机制。您应该仅在受信任的域(例如内部使用)中使用命名空间,并且当您需要保证 Kubernetes 集群的用户或其资源无法访问任何其他命名空间的资源时,不要使用命名空间。此增强的安全功能正在 Kubernetes 特殊兴趣小组(负责身份验证和授权)中讨论,请访问 SIG-Auth 参与其中。