本文是 KubeZoo 系列技术文章的第二篇,将重点介绍 KubeZoo 的中心理念和关键完结 —— 协议转化。

github.com/kubewharf/k…

理念简介

从租户的视角来看,无论是 namespace scope 还是 cluster scope 的资源,用户都具有完好和独立的视角,比方租户 A 具有姓名为 foo 的 namespace,租户 B 也能够具有姓名为 foo 的 namespace,而且这两个 namespace 仅仅姓名相同,其资源和权限实践上是相互阻隔的。

可是从 Kubernetes 的视角来看,其对 namespace 的资源要求在 namespace 内是命名仅有的,关于 cluster scope 的资源,其要求在大局上也是命名仅有的。

当一切的租户都共享同一个 Kubernetes 时,为了处理多个租户具备完好独立视角和 Kubernetes 要求在 namespace/scope cluster 不同层次命名的仅有性的对立,咱们提出了协议转化的理念,以此处理命名仅有性的问题。

一文了解字节跳动 KubeZoo 的核心理念——协议转换

如上图所示,因为每个租户的姓名/ID 是大局仅有的,因而假如在相关的资源姓名上添加租户的标志,也就直接确保了在实践的 Kubernetes 控制面上确保了资源大局的仅有性;从租户的视角来看,假如咱们对租户出现其资源时,将相关的前缀剥离,即确保了租户的实在出现视角和阻隔性。

以 namespace 视角为例,比方租户 tenant2 有 default 和 prod 两个 namespace,其在上游的实在 namespace 则是加上了租户的前缀,故为 tenant2-default 和 tenant2-prod。

因而 KubeZoo 在租户和上游的 Kubernetes 集群充当了中心的转化适配层,接受租户的恳求和上游 Kubernetes 的回来,并依据不同类型的资源进行不同的处理。

中心完结

KubeZoo 基于“协议转化”中心理念完结控制面多租户功能,经过在资源的 name/namespace 等字段上添加租户的仅有标志,然后处理不同租户的同名资源在同一个上游物理的 K8s 抵触问题,该思维和 Linux 内存办理有如出一辙之处。

K8s 原生 API 大致能够被划分为如下 4 类:

  • Namespace scope:如 pod, pvc, statefulset, deployment etc;
  • Cluster scope:如 pv, namespace etc;
  • Custom:用户界说的资源;
  • Non-resource:如 openapi / healthz / livez / readyz 以及日志监控等 etc。

经过对上述 API 采纳对应的协议转化计划,终究为绝大部分的 API 供给多租户才能。经分析检验, KubeZoo 的一致性测试经过率高达 86%。

Namespace Scope 资源

K8s 大概有 40 多种 namespace scope 的资源,比方 deployment / statefulset / pod / configmap 等。经过在每个资源的 namespace 字段相关租户信息,然后完结 namespace scope 资源的多租户才能。

一文了解字节跳动 KubeZoo 的核心理念——协议转换

关于租户不同类型的恳求,KubeZoo 首要从恳求的证书中解析租户信息,之后详细转化如下:

  • POST:在 request body 的 namespace 和 request url 的 namespace(假如有的话) 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源创立;关于 response body,删去 namespace 中的租户前缀,最终把恳求回来给租户。

  • GET

    • 查询/监听某个资源:在 request url 的 namespace 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源查询;关于 response body,去除 namespace 中的租户前缀,最终把恳求回来给租户。
    • 罗列/监听 ns 的资源:在 request url 的 namespace 字段添加租户前缀,调整 label selector 中触及 namespace 相关的值,然后将恳求转发至上游 K8s 完结资源查询;关于 response body,去除 namespace 中的租户前缀,最终把恳求回来给租户。
    • 罗列/监听租户的资源:查询上游 K8S 一切此类资源,KubeZoo 依据 namespace 的租户前缀匹配本租户的一切此类资源;一起去除 namespace 中的租户前缀,最终把恳求回来给租户。
  • PUT:在 request body 的 namespace 和 request url 的 namespace(假如有的话) 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源更新;关于 response body,去除 namespace 中的租户前缀,最终将恳求回来给租户。

  • DELETE

    • 删去某个资源:在 request url 的 namespace 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源删去;关于 response body,去除 namespace 中的租户前缀,最终将恳求回来给租户。
    • 删去某些资源:在 request url 的 namespace 字段添加租户前缀,调整 label selector 触及 namespace 相关的值,然后罗列符合要求的资源,关于归于本租户的资源,逐一删去;关于 response body,去除 namespace 中的租户前缀,最终把恳求回来给租户。

关于 POST / GET / PUT 操作的协议转化进程,所依赖的 ownerReference 资源姓名也需求做相关处理,关于 Cluster Scope 的资源姓名,其处理逻辑请见下节“Cluster Scope Resource”;关于 Custom Resouce 的资源姓名,其处理逻辑等请见下文“Custom Resource”。

ownerReference 的命名转化是遍及适用的场景,不只适用于本节 namespace scope resource,还包含 cluster scope resource 和 custom resource 等,后文不再累述。

Cluster Scope 资源

K8s 大概有 20 多种 cluster scope 的资源,比方 pv / namespace / storageclass 等等。经过在 name 相关租户信息,然后完结 cluster scope 资源的多租户才能。

一文了解字节跳动 KubeZoo 的核心理念——协议转换

关于租户不同类型的恳求,KubeZoo 首要从恳求的证书中解析租户信息,之后详细转化如下:

  • POST:在 request body 的 name 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源创立;关于 response body,去除 name 中的租户前缀,最终把恳求回来给租户。

  • GET

    • 查询/监听 某个资源:在 request url 的 name 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源查询;关于 response body,去除 name 中的租户前缀,最终把恳求回来给租户。
    • 罗列/监听 租户的资源:查询上游 K8s 一切此类资源,KubeZoo 依据 name 匹配的租户前缀匹配本租户的一切此类资源;一起去除 name 中的租户前缀,最终把恳求回来给租户。
  • PUT:在 request body 的 name 和 request url 的 name(假如有的话)字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源更新;关于 response body,去除 name 中的租户前缀,最终将恳求回来给租户。

  • DELETE

    • 删去某个资源:在 request url 的 name 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源删去;关于 response body,去除 name 中的租户前缀,最终将恳求回来给租户。
    • 删去某些资源:罗列符合要求的资源,关于归于本租户的资源,逐一删去;关于 response body,去除 name 中的租户前缀,最终把恳求回来给租户。

关于 node 类型的资源,因为 KubeZoo 计划是倾向由弹性容器供给数据面多租户的才能,因而上游集群不会纳管实践的核算节点,故完结上采纳屏蔽 node 类型的资源的做法。

Custom 资源

Custom Resource Definition(CRD)是一种特别的 cluster scope 资源,因为其 name 由 group + plural 组成,咱们挑选在 group 前缀相关租户信息。除此处细节差异外,其它的逻辑则和上述 “cluster scope resource” 基本保持一致。详情如下图所示:

一文了解字节跳动 KubeZoo 的核心理念——协议转换

Custom Resource(CR)能够分为 namespace scope 和 cluster scope,咱们以 namespace scope 的 CR 的恳求为例,KubeZoo 从证书解析租户信息后,详细的转化逻辑如下:

  • POST:往 request url 的 group / namespace 和 request body 的 group / namespace 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源创立;关于 response body,去除 group / namespace 中的租户前缀,最终将恳求回来给租户。

  • GET

    • 查询/监听某个资源:向 request url 的 group / namespace 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源查询;关于 response body,去除 group / namespace 中的租户前缀,最终把恳求回来给租户;
    • 罗列/监听 ns 的资源:在 request url 的 group / namespace 字段添加租户前缀,调整 label selector 中和 namespace 相关的值,然后将恳求转发至上游 K8s 完结资源查询;关于 response body,去除 namespace / group 中的租户前缀,最终把恳求回来给租户;
    • 罗列/监听租户的资源:查询上游 K8s 一切此类 CR,KubeZoo 依据 group 匹配的租户前缀匹配本租户的一切此类资源;关于 response body,去除 namespace / group 中的租户前缀,最终把恳求回来给租户。
  • PUT:往 request url 的 group / namespace 和 request body 的 group / namespace 字段添加租户前缀,然后将恳求转发至上游 K8s 完结资源更新;关于 response body,去除 group / namespace 中的租户前缀 ,最终把恳求回来给租户。

  • DELETE

    • 删去某个资源:向 request url 的 group / namespace 字段正确的注入租户信息,然后将恳求转发至上游 K8s 完结资源删去;关于 response body,去除 group / namespace 中的租户前缀,最终将恳求回来给租户;
    • 删去某些资源:在 request url 的 group / namespace 字段添加租户前缀,调整 label selector 触及 namespace 相关的值,然后罗列符合要求的资源,关于归于本租户的资源,逐一删去;关于 response body,去除 group / namespace 中的租户前缀,最终把恳求回来给租户。

关于 cluster scope 的 CR,结合上述逻辑易于推导,此处不再胪陈。

Cross Reference 资源

需求留意的是,同一租户的不同类型的资源 Spec 中的字段可能会存在资源引证的依赖状况,pvc 的 spec.volumeName 为对应的 pv,大体上能够将引证分为两类:

  • namespace 内引证:例如 pod 引证 pvc / configmap / serviceaccount 等,此类上下游资源为 namespace scope 资源,且同属一个 namespace,因而不需求做任何处理。
  • namespace 与 cluster 之间引证:pvc 引证 cluster scope pv,serviceaccount 引证 clusterrolebinding 等。关于此类的资源,需求精确了解其资源字段的意义,并在 KubeZoo 解析其 Body,完结资源姓名的精确转化。

以 pvc 详细 case 为例,租户视角的 pvc:

一文了解字节跳动 KubeZoo 的核心理念——协议转换

上游 K8s 视角的 pvc:

一文了解字节跳动 KubeZoo 的核心理念——协议转换

常见触及 namespace 和 cluster 之间穿插依赖的资源有如下 10 种:

clusterrole / clusterrolebinding / endpoint / endpointslice / pv / pvc / role / rolebinding / tokenreview / volumeattachment。

Non-resource 资源

除了上述中心资源以外,K8s 还有一部分 Non-resource API,首要包含监控、日志、Doc 等。

关于 readyz / healthz / livez / version 等类型近 60 个 GET 类型的 API,这些 API 首要用于表明 master / etcd / poststarthook 各类 controller 的健康状况、版别信息等。因而关于此类 API,KubeZoo 只需求将恳求转发至下游 K8s 即可。

关于 /openapi/v2 API,KubeZoo 首要需求从上游 K8s 获取其支撑的 openapi 资源,并从相关的资源过滤出租户的 CRD,然后合并原生 API 资源,终究回来给租户。

关于 /metrics API,这些 metrics 信息无法从租户粒度进行区分,且关于托管版别的 Serverless K8s 用户效果相对有限,因而暂不考虑支撑详细的租户等级的 metrics。

关于 /logs API,因为其仅简单展现拜访的审计信息,因而暂未支撑详细的租户等级的 logs。从完结的视点能够在 KubeZoo 侧供给记录和审计才能,并将审计信息存储到 KubeZoo 的存储中。

总结

本文详细介绍了 KubeZoo 的中心理念和详细规划,然后确保了资源阻隔的视图和逻辑的精确性;因为不同类型的资源存在一些差异,因而针对 namespace scope、cluster scope、custom 和 non-resource 等类型的资源别离进行了处理,既供给了阻隔才能,又确保了精确性。

关于“数据面阻隔”详细规划,敬请期待系列文章。

最终,KubeZoo 已在 GitHub 开源,欢迎多多关注、体会。

github.com/kubewharf/k…

一文了解字节跳动 KubeZoo 的核心理念——协议转换

扫描二维码,加入 KubeZoo 项目群聊