你使用Kubernetes命名空间的方式对吗?

简介

Kubernetes 中有不少概念,这些概念在 RESTful API 中表现为对象 (“resource” 或 “kinds”)。

其中一个比较重要的概念是 namespace (命名空间)。 Kubernetes中,命名空间将单个集群分拆成多个虚拟的集群。本文的主题是命名空间的应用场景。

首先我们举个生活中的例子,做一个类比:命名空间就像家族的姓氏。比如一个家族的姓是”张”,有个家族成员叫”张三”,那么在这个家族中,大家说 “三”,我们可以唯一地确定是 “张三”。但是在家族外,如果要唯一确定这个人,则必须带上姓: “张三”,或者更准确一点 “赵家庄的张三”。

命名空间定义了一个逻辑分区,实现了一定程度上的隔离,它使得单个集群可以由多个用户(组) 使用,或者拥有多个应用的单个用户使用,而不用关心不同的应用会互相影响。

每个用户、用户组或应用都能够与其它用户和操作隔离开,仿佛这个集群只有这一个用户一样。此外,通过Resource Quota,我们能够把Kubernetes集群资源的一个子集分配给某个特定的命名空间。

对于大多数应用场景,命名空间都非常受用。在这篇文章中,我们将涵盖谷歌云平台上Kubernetes用户对命名空间的常见使用方式,具体体现在下面几个方面:

  1. 命名空间在企业中的角色和责任
  2. 分区:dev vs. test vs.prod
  3. 非多租户场景下的客户分区
  4. 什么时候不使用命名空间

用例# 1:命名空间在企业中的角色和职责

一个典型的企业包含多个业务/技术实体,这些实体的操作相互独立,但又都在企业的管控之下。只要Kubernetes 相关的角色和职责被定义好,在这样一个环境下管理 Kubernetes  集群并不难。

下面是一些关于角色和职责的建议,有了他们,在大型组织中管理 Kubernetes集群将会更简单:

设计师/架构师角色:该角色定义了整体的命名空间策略,需要考虑到产品/定位/团队/成本中心这些因素,并确定如何把这些因素映射到 Kubernetes 命名空间。设计这样一个角色能防止命名空间膨胀和碎片化。

管理员角色:该角色管理所有kubernetes集群的访问:创建/删除集群、添加/迁移节点来伸缩集群。除此之外,该角色还负责集群的更新、安全和维护,以及组织中不同实体间的配额实现。kubernetes管理员负责实施由设计师/架构师定义的命名空间策略。

这两个角色以及实际开发者使用集群的过程中也会收到企业安全和网络团队对问题的支持和反馈。常见的问题有:安全隔离要求,命名空间如何适应这种模型,或协助网络子网和负载均衡器设置。

反模式

使用命名空间进行隔离,但是没有中心化的控制:初期没有围绕kubernetes管理建立一套中心化的控制结构,有很大的风险建立起用“蘑菇农场”的拓扑结构:即没有统一的尺寸/形状/结构。 结果就是难以管理、高风险和由于资源利用不足导致的高成本。

旧的 IT 控制妨碍了正常使用和创新:一个常见的趋势是尝试将现有的内部控制机制和流程应用到新的、动态的框架。这样会降低新框架的敏捷性,也抹杀了快速动态部署的优点。

大杂烩集群:延迟为命名空间创建管理机制和结构,最终会导致一个功能杂乱的大杂烩集群,到时候再根据功能分拆成较小的使用组会非常困难。

用例# 2:使用命名空间划分DevOps职责

开发团队通常把开发流水线划分为离散的单元。这些单元会采用不同的形式或者被打上不同的标签,但是最终会被划分到几类:开发环境、测试 (QA)环境、staging环境、生产环境。最终产生的布局非常适合Kubernetes命名空间。流水线中的每个环境或阶段都有唯一的命名空间。

以上工作以及每个命名空间在开发周期中可以模板化并镜像到下一个后续的环境,例如开发->测试->产品。事实上每个命名空间逻辑离散允许开发团队在一个隔离的“ development ”命名空间内工作。

DevOps(谷歌最接近的角色,被称为网站可靠性工程,简称“SRE”)将负责在流水线各阶段迁移代码并确保为每个团队分配适当的环境。从根本上来说,DevOps仅负责最终的生产环境,这些环境运行着交付给终端用户的解决方案。

将命名空间应用到开发周期的主要优势是:软件组件(微服务/endpoints)很容易维护,在不同的环境之间不会产生命名冲突。这一点是借助于命名空间的隔离性实现的,比如 dev 环境下的 serviceX 对于其它命名空间而言是唯一的;但是,如果有必要,可以使用全名 service.development.mycluster.com 唯一地表示它。

反模式

在开发流水线中滥用命名空间,会产生一些不必要的环境。因此,如果你不做 staging 部署,就不要创建一个 ”staging” 命名空间。

拥挤的命名空间。比如,把所有的开发项目都放到 “devepment” 的命名空间下。由于命名空间类似于分区,你也可以对项目进行分区。由于命名空间是扁平的(不分层),你可能会希望这样使用:projectA-dev,projectA-prod 作为projectA 的命名空间。

用例 #3:对客户进行分区

举个例子,如果你是一家咨询公司,希望为每个客户管理单独的应用程序,那么你可以使用命名空间进行分区。你可以为每个客户、客户项目或客户业务单元创建一个单独的命名空间,既能区分这些客户,同时不需要担心不同项目使用相同的资源名称。

有一点需要注意:目前 Kubernetes 还没有提供命名空间级别的访问权限控制,对于你使用这种方式开发的应用,我们建议不要暴露给外界。

反模式

多租户应用不需要使用 Kubernetes 的命名空间,因为应用本身已经执行了分区。如果使用的话,反而增加了额外的复杂度。

客户到命名空间的映射方式不统一。例如,你赢得一个跨国企业客户,可能最初考虑给它一个命名空间,而没有考虑到它们内部需要进一步分区,比如分成 BigCorp Accounting 和 BigCorp Engineering两个区。这种情况下,客户的每一个部门都要保证有一个命名空间。

什么时候不使用命名空间

在某些情况下,Kubernetes 命名空间提供的隔离不是你想要的,或者无法提供你想要的隔离。原因可能是地理,计费或安全因素。命名空间形成的逻辑分区有很多优势,但是目前还没有能力保证利用分区的优势。Kubernetes集群中的任何用户或资源,在不考虑命名空间时,可以访问任意的集群资源。所以,如果你需要保护或隔离资源,终极的命名空间是一个单独的Kubernetes集群,你可以定期对它做安全和ACL控制。

如果你希望使用跨地理的部署,也不要考虑命名空间。举个例子,你希望部署在接近美国、欧洲和亚洲客户的地理位置,那么最好在每个区部署一个kubernetes集群。

如果客户要求细粒度的计费账单,那么建议将账单留给你基础设置提供商。比如,在Google云计算平台,你可以使用一个单独的GCP项目或计费账户,针对特定客户的项目创建一个kubernetes集群。

如果你要求客户的保密和合规对其他客户是完全不透明的,每个客户一个集群的模式可以提供这种级别的隔离。而且,你需要将资源分区委托给底层的基础设置供应商。

目前我们正在致力于两个方面的开发:

  1. 为命名空间提供ACL,以增强安全性;
  2. 提供集群联邦。

这两个特性背后的机制都会说明为什么要分离Kubernetes集群。

一个很容易理解的反模式是使用命名空间进行版本控制。你不应该使用命名空间区分集群资源的版本。容器和registry已经提供了版本管理的功能,在Kubernetes中部署资源时也支持版本管理。

充分利用kubernetes的容器模型,可以实现多个版本共存,借助于 deployment 也可以实现版本的自动更新。另外,基于版本的命名空间会导致命名空间的不断膨胀,增加了管理上的困难。

再次警告

你可能希望创建层级的命名空间,然而事实上并不能。命名空间不能嵌套。比如说,你不能创建一个my-team.my-org 的命名空间,尽管你在 my-org 下可能有 my-team。

命名空间易于创建和使用,但是它也容易把代码部署到错误的命名空间下。好的DevOps应该把这类工作文档化和自动化,以充分减少错误的可能。另外,还要避免为kubectl 上下文设置错误的命名空间。

如前所述,Kubernetes 目前不提供命名空间级别的安全机制。只有在信任域内(例如内部使用)你才可以使用命名空间;如果你需要保证一个集群用户或资源没有权限访问其他命名空间的资源,不要使用命名空间。对于这部分增强安全特性,涉及到 SIG-auth, 在Kubernetes特殊兴趣小组 Authentication & Authorization 分组已经讨论过。

K8S中文社区微信公众号
分享到:更多 ()

评论 抢沙发

评论前必须登录!