容器云应该采用什么样的部署方式?
周末参加一个的技术研讨会上,提到容器云平台组件、中间件、微服务等的部署问题,是虚拟机、物理机、还是容器化部署好?这个问题我们前面的文章也讨论过一点,也可能没有标准答案,仁者见仁、智者见智,所谓兵无常势、水无常形,需要根据具体的业务环境、业务需求、技术要求等选择合适的方案。不过正好我们也在考虑决定容器云测试、UAT、生产环境应该采用什么样的部署架构和方式,在此也分享一下我们的思考,希望对大家能有所助益。
一、全容器化部署?
目前应该是几乎所有的容器云厂商在容器云交流和PoC时都强调所有组件都容器化。这样实施安装部署相对容易,一键部署、半小时搭建容器云平台。但我们在PoC测试中也发现了一些问题,比如容器资源分配的问题,Kubernetes多集群部署问题,控制节点高可用部署问题,镜像仓库定位和部署问题,中间件和不同的环境部署和定位问题等;也发现容器云平台容器异常,新的容器创建,旧的依然在,导致很多无用的容器占用资源,也带来一些理解上的困难。虽然是平台自身实现的问题,但明显是在设计时一些问题没考虑到。
二、环境管理
全容器化部署的好处是可以快速的构建一致性的环境,这也是实现DevOps的一个重要方面。所以在开发测试环境全容器化部署是没有问题的。因为这些环境需求变化快,传统维护开发测试环境需要花费大量的时间和人力,如果采用容器化方式,可以快速构建一个开发测试环境域,用于完成服务的测试。主要完成功能性方面的测试,对于可能涉及到性能测试,我们建议放到UAT环境来做。UAT和生产环境保持软硬件和部署架构一致。UAT和生产环境容器云基础组件建议部署到虚拟机或物理机上,比如集中日志、监控、服务注册发现、服务网关等组件。这样部署的目的一方面是为了更好的利用容器云的轻量化特性,另一方面也是基于安全、运维管理等考虑。
我们也一直说要用简单的方式解决复杂的问题,基于容器云基础设施,我们希望建设企业级服务中台,一家企业只需要维护一套日志系统,一套监控系统,没必要每次都重复建设。这些组件相对固定,并不需要经常改变,而且数据需要保证绝对的安全。通常集中日志系统、监控系统等都需要集群化部署,不是一台机器一个实例能满足需求的。所以在开发测试环境是为了利用容器的快速构建特性,在UAT、生产环境则要保持稳定、安全。采用容器云在环境管理环境部署方面可以有所差别。
各个环境保持独立而又通过镜像仓库联系起来,镜像是联系各个环境的标准交付物。
三、镜像仓库
镜像仓库在容器云平台如何定位?在DevOps中起什么样的价值?这是我们考虑采用容器云平台过程中也一直考虑的问题。以前的讨论中我们提到过,考虑把镜像仓库作为开发测试和生产之间的媒介,开发测试都止于镜像仓库,生产起于镜像仓库。镜像作为标准交付物,在各个环境间传递,镜像仓库通过镜像的安全检查等机制保证镜像安全。也就是DevOps持续集成止于镜像仓库,镜像仓库是部署运营的起点。
镜像仓库要不要部署于容器?其实这个在我们看来不是很重要。首先镜像仓库是基础组件,不会经常需要更改变化,所以其实更适合稳定的部署。另外公共镜像和私有镜像会需要很多的磁盘空间,IO能力会成为一个因素。镜像仓库可以作为镜像的分发中心,也就是我们所说的各环境之间的媒介,或者不同集群之间的媒介。从这个角度来说,镜像仓库可以作为一个独立的部分,只是为容器云平台提供镜像分发服务和镜像管理服务。它可以独立部署,不依赖于容器云平台。物理机或虚拟机部署或许更合适一点,当然,部署于容器也不是不可以。
镜像仓库高可用部署是需要考虑的,这也是很多容器云厂商宣传的一个重要的功能点。如果有充足的资源,我们还是建议镜像仓库部署高可用,毕竟这样可以多一份保障,减少一些意外,但高可用节点不是越多越好,通常主备节点就可以了。不部署高可用通常也不会有太大问题,只要数据不丢失,很快的恢复,没有大的影响。
四、集群部署
Kubernetes理论上可以管理成千上万的节点,但现实总会有不小的差距。有测试显示Kubernetes集群节点数超过500就会出现超时,增加Kube Master节点并不能真的解决问题,所以每个Kubernetes集群节点数有一定的限制,在达到500左右时就需要考虑优化措施,或者按业务条线分集群部署。
通常我们这样的传统企业,节点数也不会很快达到500以上,单一集群一定时间内也可以满足需求。随着节点数的增加,Kube Master节点数也需要增加。其实最初我们考虑只要Kubernetes能保证在Master节点宕机时不影响到业务应用的正常运行,Kubernetes集群的管理工作我们可以忍受一段时间的中断,所以我们没考虑Master节点高可用,但节点数的增加可能必须部署Master节点的高可用,否则可能无法支持kubectl的正常操作。随着节点数的增加master节点数也需要增加。但master节点数超过10就也会带来一些问题,所以通常master节点数是3、5或7比较合适,支持几百个节点。
所以初始情况下,可以用简单的方式,化繁为简,化大为小,采用按业务条线多集群部署方式。这样每个集群确保不会有超过500以上的节点。超过的话考虑新建集群进行拆分。但有些情况下可能需要很大的集群,这个目前采用Mesos可能是更好的方案,从《scaling kubernetes to 2500 nodes》一文中我们了解到Kubernetes可能需要采取不少的优化措施。我们还远未达到这样的集群数量,也没有条件进行测试,所以目前还不能确切知道是否可行。也不知道是否有什么潜在的问题,厂商似乎在这方面也没有太多经验。所以如果可能的话,把大集群拆分为多个小集群,按业务条线、或者按区域等划分,应该是一个可行的方案。
五、控制节点
控制节点就是我们说的master节点,是集群中的大脑和中枢神经,控制和指挥着整个集群的运转。控制节点不可用,整个集群就会陷入瘫痪。最初我们考虑,是否有必要占用那么多的资源来部署控制节点高可用,对我们来说我们可以忍受一段时间内控制节点不可用,只要能及时恢复。部署并不是每时每刻发生,只要部署的业务服务能正常运行,业务不受影响,控制节点暂时的不可用是不会有太大的影响。所以最初我们只考虑部署一个控制节点,不考虑高可用部署。这也是基于我们ESB运维的经验。ESB的控制监控节点故障,不影响业务服务,所以我们有充足的时间来调试恢复ESB控制监控节点。不过Kubernetes跟ESB不同的是,随着节点数的增加,可能需要部署更多控制节点,实现控制节点高可用部署。
Kubernetes控制节点有多个组件,包括kube-apiserver、kube-controller、kube-scheduler和etcd等,这些组件是分开部署还是一个节点上部署?随着集群节点数的增加,可能也是一个不得不考虑的问题。Etcd应该需要单独部署,不同的场景选择合适的磁盘,以及是否使用不同的etcd集群,比如配置中心如果使用etcd,是否和平台合用同一个etcd还是新建一个,需要根据具体节点数量等情况来确定。从《scaling kubernetes to 2500 nodes》文中我们知道,etcd使用了串行 I/O, 导致 I/O 之间的延迟叠加,在节点数超过500的时候延迟就增加很多,导致Kubectl操作超时,所以etcd在改用本地SSD磁盘后,etcd终于正常了。另外Kubernetes Events 也可以存储在一个单独的 etcd 集群里,这样对 Events 的操作就不会影响到主 etcd 集群的正常工作。但这也带来了更多的资源投入,以及管理的复杂度。
六、基础组件部署
我们讨论过多次,要建设容器云平台,仅有Kubernetes是远远不够,还需要很多的基础组件来支撑整个业务应用。比如日志、监控、配置、注册发现、服务网关等组件。这些组件是容器化部署好还是虚拟机/物理机上部署好,都是绕不开的问题。
初始节点数量和服务数量少的情况下,可能基础组件容器化部署是个不错的选择。其实就像我们所说的开发测试环境,目的是为了快、敏捷,所以量不会很大。随着节点数增加,服务量增加,不只是Kubernetes自身组件会遇到瓶颈,服务治理服务管理等平台基础组件也会遇到同样的问题。
七、中间件部署
我们建设容器云,很重要的原因是希望利用云上中间件的能力。如果没有中间件服务,那将需要很多的工作来构建这些服务,不过幸运的是,已经有很多中间件可以在容器云上部署。不过同样面临一个“量”的问题,量大的情况下,是否能支撑,是否比非容器化需要成倍的资源来支撑,是否给运维带来一些困难。比如某证券的Kafka集群有20多台,内存配置一般选择64G,采用SSD硬盘,并做了raid5冗余,这样的配置在容器云平台肯定是不合适的,所以需要部署于虚拟机或者物理机上。
在开发测试环境我们还是建议使用容器化环境。在生产根据实际的情况和业务场景选择合适的部署方式。数据库什么的可能就不是很合适,虽然也支持,可以部署,但从运维、安全、组件稳定性等方面考虑,非容器化部署可能更合适。
八、微服务/业务服务部署
微服务肯定是要部署到容器上。目的就是为了利用容器的轻量、隔离、标准化、弹性伸缩等特性。微服务/业务服务往往是需要不断的改进、更新,所以服务整个生命周期要足够敏捷,不只是开发敏捷。其实从这点我们也可以看到,容器化部署比较适合经常变化的、轻量的,那些笨重的、基本没有太大变化的组件如果容器化部署可能无法展现容器的优点。把容器当虚拟机用,有点画蛇添足。其实很多公司选择互联网应用场景部署于容器云作为采用实施容器云的开端,也是因为这些原因吧。看来是英雄所见略同。
我们还讨论过容器化部署时,每个镜像可能会不小,几百兆、甚至上G,跟我们传统ESB服务部署对资源需求就有很大不同。容器化隔离更好,但是每个容器都会重复占用资源。比如java应用,通常一台机器安装一个JDK就可以了,可以运行很多个Java应用。但对于容器来说,每个容器都需要一个JDK,所以每个镜像都需要打包JDK,在网络传输、存储、运行时资源占用,似乎都没有节约。