若是你使用Kubernetes做为应用程序的操做平台,那么你应该会遇到一些有关使用集群的方式的基本问题:前端
你应该有多少集群?数据库
它们应该多大?后端
它们应该包含什么?安全
本文将深刻讨论这些问题,并分析你所拥有的一些选择的利弊。网络
做为一个软件建立者,你应该开发并运行了多个应用程序。并且,你应该在不一样的环境中运行这些应用程序的多个实例——例如,你应该有开发、测试以及生产环境。那么,不一样的环境和应用程序的组合,咱们能够获得一个“矩阵”:架构
在以上例子中,有3个应用程序和3个环境,两两组合为9个应用程序实例。每一个应用程序实例是一个独立的部署单位,能够独立运行。app
请注意,一个应用程序实例可能由多个组件组成,如前端、后端、数据库等。在一个微服务应用程序中,一个应用程序实例将由全部微服务构成。负载均衡
那么做为一个Kubernetes用户,此时会遇到一些问题:框架
应该在一个集群中运行全部应用程序实例吗?运维
或者每一个应用程序实例都应该有一个单独的集群吗?
或者应该以上二者相结合?
以上这些都是行之有效的方法——Kubernetes是一个灵活的系统,它并不会直接告诉你某一条指定的使用方法。
关于集群的搭配你有如下选择:
一个大型的共享集群
许多小型的一次性集群
每一个应用程序有一个集群
每一个环境中有一个集群
前两种方法分别是大型集群和小型集群的极端,其规模大小关系以下:
总而言之,若是一个集群包含了大量的节点和Pod,那么它就能够被定义为大于另外一个集群。例如,一个有10个节点和100Pod的集群大于有1个节点和10个Pod的集群。
厘清了概念和选项,那么咱们如今开始吧!
这个方法是指将你全部的工做负载都运行在一个集群中:
经过这种方法,咱们能够像通用基础架构平台同样使用该集群——不管你须要运行什么,均可将其部署到现有的Kubernetes集群中。
Kubernetes中有一个命名空间的概念,能够 在逻辑上将集群的各个部分彼此分开。在上述状况下,你能够为每一个应用程序实例建立单独的命名空间。
接下来,咱们来看看这个方法的优劣势。
若是你只有一个Kubernetes集群,那么你只须要拥有运行和管理Kubernetes集群所需的全部资源的一个副本。这包含了master节点——一个Kubernetes集群一般有3个master节点。若是你只拥有一个集群,你一共只须要3个master节点(比起拥有10个集群,须要30个master节点来讲轻松很多)。
固然了,确定不止master节点,还包括其余集群范围的服务,例如负载均衡器、Ingress controller、身份验证、日志和监控。若是你只有一个集群,你能够为全部工做负载重复使用这些服务,而且不须要拥有多个副本。
因为上述缘由,较少的集群一般更便宜,由于集群数量较大,意味着资源更多,所以会花费更多的费用。对于主节点来讲尤为如此,这可能会用掉你大量的费用——不管你的集群是在本地仍是在云中。
有一些Kubernetes托管服务会提供免费的控制平面,如Google Kubernetes Engine(GKE)或Azure Kubernetes Service(AKS),在这种状况下成本也许就不是问题。然而,有些托管的Kubernetes服务会为运行一个Kubernetes集群收取固定的费用,如Amazon Elastic Kubernetes Service(EKS)。
管理一个集群总比管理多个集群简单不少。管理集群可能包含如下任务:
升级Kubernetes版本
设置CI/CD流水线
安装一个CNI插件
设置用户身份验证系统
安装一个admission controller
等等……
若是你只有一个集群,这一切你只须要完成一次便可。若是你有许多集群,那么你须要将以上任务执行不少次,这须要你开发一些自动化流程以及工具,使其可以在全部集群中同步。
如今来讲说缺点
若是你只有一个集群,若是这个集群刚好崩溃了,那么你的全部工做负载都会宕机。
有不少方式可能会致使出错:
Kubernetes升级过程当中产生的“反作用”
集群范围的组件(如CNI 插件)没法正常运行
对集群的其中一个组件进行了错误的配置
底层基础架构发生故障
若是只有一个共享集群,那么只要相似的事情发生可能会对全部工做负载形成重大损害。
若是有多个app运行在同一个Kubernetes集群中,这意味着这些应用程序在集群的节点上共享硬件、网络和操做系统。具体而言,在同一节点上运行的两个不一样的应用程序的两个容器是在相同硬件和操做系统内核上运行的两个进程。
Linux容器提供了一些隔离的形式,但这种隔离不如虚拟机所提供的隔离强。在后台,容器中的进程仍然只是在主机操做系统上运行的进程。
从安全角度来看,这的确是一个问题。从理论上讲,它容许不相关的应用程序(有意地和无心地)彼此交互。并且,在一个Kubernetes集群中的全部工做负载共享某些集群范围的服务,如DNS——它能够容许应用程序发现集群内的其余APP的服务。
以上所提到的这些也许会成为一个问题,也许不会,这取决于应用程序对安全性的要求。
Kubernetes自己提供了各类方法来防止安全漏洞,如PodSecurityPolicies以及NetworkPolicies。可是,要彻底正确地使用这些工具须要一些经验,而且它们也没法防止全部的安全漏洞。
请牢记一点,Kubernetes是为共享而设计的,而不是隔离和安全。
既然在Kubernetes集群中有许多共享资源,那么许多不一样的应用程序就能够经过各类方式互相挤占资源。例如,一个app可能独占了某些共享资源,如CPU或内存,所以致使同一节点上运行的其余应用没有资源可用。
Kubernetes提供各类方法来控制这一行为,如resource requests and limits、ResourceQuota以及LimitRanges。可是,一样地,要正确使用这些工具并不是易事,并且它们也没法防止全部没必要要的反作用。
若是你只有一个集群,那么在企业内部会有许多人必须得访问这一集群。越多的人访问,破坏的风险就会越高。
在集群内部,你能够控制哪些人可使用基于角色的访问控制(RBAC)进行操做。可是,这仍然不能防止用户在受权范围内进行破坏。
若是你给全部的工做负载使用一个集群,这个集群规模大几率已经很大了(从节点和Pod的角度来讲)。然而,Kubernetes集群没法无限扩大。理论上,集群的大小是有上限的,在Kubernetes中的定义大概事5000节点、150,000Pod以及300,000个容器。
然而,实际上,比上述规模更小的集群已经会开始面临诸多挑战,例如500节点。缘由是较大的集群对Kubernetes控制平面形成了更大的压力,这须要仔细计划以保持集群的功能和效率。
接下来,咱们来看看第二个选项——许多小型集群
使用这种方法,你能够为每一个部署单元使用单独的Kubernetes集群:
在本文中,一个部署单元即为一个应用程序实例——如一个应用程序的开发版本。
经过这种策略,Kubernetes就能够像用于各个应用程序实例的专用应用程序运行时同样使用。
接下来,咱们看看这种方法的优点和劣势。
若是一个集群出现故障,那么仅会损害运行在该集群上的工做负载,并非全部工做负载都会受到影响。
各个集群中运行的工做负载不会共享资源,如CPU、内存、操做系统、网络以及其余服务。这样能够在不相关的应用程序之间提供强大的隔离,对于提高应用程序安全性十分有效。
若是每一个集群仅运行一小组工做负载,那么就只须要更少的人访问这一集群。越少的人访问集群,集群出现故障的几率就越低。
接下来看一下这一方法的缺点。
正如以前所说起的,每一个Kubernetes集群须要一组管理资源,如master节点、控制平面组件、监控和日志解决方案等。若是你有许多小型集群,那么你只能为这些管理功能牺牲资源使用的百分比。
低效的资源利用天然就会致使更高的成本。例如,若是你必须运行30个master节点,而不是3个才能得到相同的计算机功能,你看看每个月的帐单就能体会到这一点。
同时管理许多Kubernetes集群比管理单个集群要复杂得多。例如,你须要为每一个集群设置身份验证和受权;若是你想升级Kubernetes版本,你须要执行这一操做不少次。你可能须要开发一些自动化流程,这样会使这些操做更高效。
接下来,咱们看一下其余场景的集群。
使用这种方法,对于特定应用程序的全部实例,你都有一个单独的集群:
你能够将其视为每一个团队单独拥有本身的集群,由于一般一个团队会开发一个或多个应用程序。
接下来,咱们看看这个方法的优劣。
若是一个应用程序有特定的需求,这些需求能够在它的集群内安装,而无需影响其余集群。这样的要求可能包括GUI worker节点、一个特定的CNI插件、一个服务网格或其余服务。如此以来,每一个集群均可以彻底配备相应应用程序所需的配置——很少也很多。
这个方法的一个不足时来自不一样环境的应用程序实例运行在同一个集群中。例如,应用程序的生产版本和开发版本都运行在同一个集群中,这意味着开发人员须要在生产版本应用程序运行的相同集群中工做。
因此,若是开发人员或一个有bug的开发版本在集群中形成了某些损害,那么生产版本绝对会所以受到影响——这是一个巨大的不足。
使用这种方法,你能够为每一个环境建立一个单独的集群:
例如,你能够分别有一个开发、测试和生产集群,你能够在其中运行特定环境中的全部应用程序实例。
一般状况下,这个方法会使得全部环境彼此隔离,而这对生产环境而言十分重要。生产版本的应用程序如今不会受到其余集群以及应用程序环境的任何影响。因此,若是某些错误配置在你的开发集群中形成破坏,你的生产版本的app依旧能够持续运行,仿佛什么也没发生。
你能够为环境优化每一个集群,例如:
安装开发和调试工具在开发集群中
安装测试框架和工具在测试集群中
给生产集群使用性能更好的硬件和网络
这样可以同时提高app的开发和运维效率。
没有人真的须要在生产集群内工做,因此你能够限制访问它。你甚至能够根本不向任何人授予生产集群的访问权限——能够经过自动化CI/CD工具对该集群进行部署。这将极大下降生产集群中人为错误的风险,这十分重要!
如今,来看看缺点。
这一方法的主要不足是应用程序之间缺乏硬件和资源的隔离。不相关的应用程序共享集群资源,例如操做洗头膏内核、CPU、内存和其余服务。如上文所述,这多是一个安全问题。
若是一个app有特殊的要求,这些要求则必须在全部集群中获得知足。例如,若是一个应用程序须要一个GPU,那么每一个集群至少必须得有一个GPU worker节点——即使只有一个应用程序使用它。这会致使更高的成本和更低效的资源利用。
总而言之,若是你有给定的一组应用程序,你能够将它们运行在几个大型集群上或多个小型集群上。本文讨论了从几个大型集群到多个小型集群的各类方法的优缺点:
一个大型的共享集群
许多小型的一次性集群
每一个应用程序有一个集群
每一个环境中有一个集群
如下一张表格,总结了不一样方法的优劣势:
因此你应该选择哪一种方法呢?
一般状况下,这取决于你的实际用例——你必须权衡不一样方法的优缺点,才能找到最合适你的解决方案。可是,选择不只限于上述示例,也能够是它们的任意组合。例如,您可能考虑为每一个团队创建两个集群:一个开发集群(用于开发和测试环境)和一个生产集群(用于生产环境)。
经过了解以上示例方案,您能够相应地结合特定方案的利弊。
做者: Daniel Weibel