由于namespace本身的限制,Kubernetes对多租户的支持面临很多困难,本文梳理了K8S多租户支持的难点以及可能的解决方案。原文: Multi-tenancy in Kubernetes
是否应该让多个团队使用同一个Kubernetes集群?
是否能让不受信任的用户安全的运行不受信任的工作负载?
Kubernetes支持多租户吗?
本文将探讨支持多租户的集群所面临的挑战。
多租户可以分为:
实践中也可能是混合模式!
在租户之间共享集群的基本构建块是命名空间(namespace)。
名称空间对资源进行逻辑分组 —— 不提供任何安全机制,也不能保证所有资源都部署在同一节点中。
命名空间中的pod仍然可以与集群中的所有其他pod通信,向API发出请求,并使用尽可能多的资源。
开箱即用,任何用户都可以访问任何命名空间。
如何阻止访问呢?*
通过RBAC,可以限制用户和应用程序可以使用的命名空间或在命名空间内做什么。
常见操作是向有限的用户授予权限。
使用Quota和LimitRanges,可以限制在命名空间中部署的资源以及可用的内存、CPU等。
如果想限制租户对其命名空间的操作,这是个好主意。
默认情况下,所有pod都可以与Kubernetes中的任何pod通信。
但这并不适用于多租户,可以用NetworkPolicies来纠正这个问题。
NetworkPolicies类似于防火墙规则,可以隔离出站和入站流量。
很好,命名空间现在安全了吗?
别急。
基于RBAC、NetworkPolicies、Quota等作为多租户的基本构建块还是不够。
Kubernetes还有几个共享组件。
Ingress控制器就是一个很好的例子,通常在每个集群中只会部署一个。
如果提交具有相同路径的Ingress清单,最后一个会覆盖之前的定义,并且只有这一个才会生效。
更好的方法是为每个命名空间部署一个控制器。
另一个有趣的挑战是CoreDNS。
如果某个租户滥用DNS怎么办?
集群的其余部分也将受到影响。
可以用一个额外的插件[github.com/coredns/pol… external plugin)来限制请求。
Kubernetes API服务器也面临同样的挑战。
Kubernetes不知道租户,如果API接收到太多请求,将会触发全局流控。
我不知道是否有解决办法!
如果进一步考虑共享资源,那么kubelet和工作负载也存在挑战。
正如Philippe Bogaerts提到的,租户可以通过liveness探针接管集群中的节点。
这也不容易解决。
可以将扫描器(linter)作为CI/CD的一部分,或者用准入控制器(admission controller)来验证提交给集群的资源是否安全。
这里是Open Policy Agent的库和规则。
还有隔离机制比虚拟机更弱的容器。
Lewis Denham-Parry在这段视频中展示了如何从容器中逃逸。
如何解决这个问题?
可以用gVisor这样的容器沙箱,或者用轻型虚拟机作为容器(Kata Container,firecracker-containerd)或完整的虚拟机(virtlet作为CRI)。
希望你已经意识到这个主题的复杂性,以及在Kubernetes中为隔离网络、工作负载和控制器提供严格的边界是多么困难。
这就是为什么不建议在Kubernetes中提供硬多租户的原因。
如果需要硬多租户,建议使用多集群或集群即服务(Cluster-as-a-Service)工具。
- Cluster API
- HyperShift
- Kamaji
- Gardener
如果可以容忍较弱的多租户模型,以换取简单性和便利性,那么可以推出RBAC、Quota等规则。
还有一些工具可以把这些问题抽象出来:
- Virtual Cluster (wg-multitenancy)
- Vcluster
- Capsule
- Kiosk
最后,如果对这个话题感兴趣,可以进一步参考以下资源:
- 我们在Learnk8s上举办的Kubernetes研讨会
- twitter讨论集合
- 每周发布的Kubernetes时事通讯
你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!
本文由mdnice多平台发布