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

Kubernetes 名字空间:用例和见解

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

谁在一垒?由 Abbott 和 Costello 创作

引言

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

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

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

除了最简单的 Kubernetes 用法,您都将受益于使用命名空间。在本文中,我们将介绍我们观察到的 Google Cloud Platform (GCP) 用户使用命名空间的最常见方式,但我们的列表并非详尽无遗,我们很乐意从您那里了解其他示例。

涵盖的用例

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

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

典型的企业包含多个业务/技术实体,它们相互独立运作,并由企业自身管理某种形式的总体控制层。在这种环境中有效运行 Kubernetes 集群,需要定义与 Kubernetes 相关的角色和职责。

以下是一些推荐的角色及其职责,它们可以使大型组织中管理 Kubernetes 集群变得更容易。

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

这两个角色和实际使用集群的开发人员还将获得企业安全和网络团队的支持和反馈,解决诸如安全隔离要求以及命名空间如何适应此模型,或协助设置网络子网和负载均衡器等问题。

反模式

  1. 没有集中控制的孤立 Kubernetes 使用“孤岛”:如果最初没有投入建立围绕 Kubernetes 管理的集中控制结构,则存在最终形成“蘑菇农场”拓扑的风险,即组织内部集群没有定义的规模/形状/结构。结果是难以管理、风险更高且由于资源利用不足而导致成本升高。
  2. 旧式 IT 控制扼杀使用和创新:一种常见的倾向是尝试将现有的本地控制/程序移植到新的动态框架上。这导致动态框架的敏捷性受到拖累,并抵消了快速动态部署的好处。
  3. 全能集群:推迟创建命名空间管理结构/机制的工作可能导致一个庞大的全能集群,难以将其拆分为更小的使用组。

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

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

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

将命名空间应用于开发周期的主要好处是,可以在不同环境之间保持软件组件(例如微服务/端点)的命名一致性,而不会发生冲突。这是由于 Kubernetes 命名空间的隔离特性,例如,开发环境中的 serviceX 在所有其他命名空间中也将被称为 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 参与讨论。