宜信公司从2018年初开始建设容器云,至今,容器云的常用基本功能已经趋于完善,主要包括服务管理、应用商店、Nginx配置、存储管理、CI/CD、权限管理等,支持100+业务线、3500+的容器运行。伴随公司去VMware以及DevOps、微服务不断推进的背景,后续还会有更多的业务迁移到容器云上,容器云在宜信发挥着越来越重要的作用。本次分享主要介绍宜信容器云平台的背景、主要功能、落地实践及未来规划。
宜信容器云平台的建设背景主要包括:
在上述背景下,我们结合宜信的业务场景开发建设宜信容器云平台。
宜信容器云平台经过一年多时间的建设和开发,基本的常用功能已经具备。如图所示。
上图左侧是宜信容器云平台的主要功能,包括:服务管理、CI/CD、代理出口、配置管理、文件存储、告警策略、镜像管理、用户管理、权限管理、系统管理等。
右侧是一个服务管理的界面,从中可以看到服务列表、服务名称、服务状态及当前服务数量,还有当前镜像版本及更新时间。
上图所示为整个容器云平台的架构图,在各种开源组件(包括Harbor镜像仓库、Kubernetes容器管理、Prometheus 监控、Jenkins构建、Nginx流量转发和Docker容器虚拟化等)的基础之上,我们自研开发了5个核心模块。
最上面是对用户提供的web-portal页面,一个用户自助的终端。
本次分享的标题是《宜信容器云的A点与B点》,之所以称为A点和B点,这与我们的公司文化有关,我们以“A点”代指现在已经做到的事情,以“B点”代指未来或者下个阶段要做的事情。
目前整个宜信容器云平台已经完成了大部分主要功能点的开发,这部分已经实现的功能即为“A点”,包括服务管理、应用商店、域名管理、CI/CD、镜像管理、文件存储、监控告警、定时任务、配置管理等。后续还有部分功能需要添加和完善,即为“B点”,主要包括:对象存储、大数据容器云、全面日志收集、自定义指标伸缩、智能调度和混部、多集群管理、安全隔离、站点监控等,
上图为宜信容器云平台的整体功能图,其中蓝色代表已经完成的功能、黄色代表需要优化和改善的功能。
整个系统从资源管理的角度来看:
下面将通过页面截图的方式,详细介绍容器云的主要功能点。
上图是服务管理页面的截图,逐一介绍各个功能。
除了上文介绍的一排容器按钮以外,还有一些针对服务的相关操作,比如服务的基本配置:环境变量、域名解析、健康检查,服务的升级,替换镜像、扩缩容等操作。
很多业务场景有这样的需求:希望可以在测试环境里实现一键启动中间件服务,如MySQL、Zookerper 、Redis、Kafka等,不需要手动去配置kafka等集群。因此我们提供了中间件容器化的解决方案,将一些常用的中间件导入容器中,后端通过Kubernetes维护这些中间件的状态,这样用户就可以一键创建中间件服务。
但由于这些中间件服务本身相对来说比较复杂,所以目前我们的应用商店功能主要是为大家提供测试环境,等这部分功能成熟之后,会把应用商店这些常用的中间件拓展到生产环境上,到时候就可以在生产环境使用容器化的中间件服务了。
CI/CD是代码构建流,我们内部称为codeflow。其实代码构建流程非常简单,一句话概括起来,就是:拉取仓库源代码,通过用户指定的编译脚本构建出执行程序,将执行程序放到用户指定部署路径,并通过启动命令启动这个服务。系统会为每个codeflow生成对应的Dockerfile用于构建镜像,用户不需要具备Docker使用经验。
上面的流程是代码编译,下面是通过系统预先生成的Dockerfile,帮用户打包成Docker Image,这就是从代码拉取、代码编译、打包到Docker Image并推送到镜像仓库的整个流程。
用户完成配置并点击提交代码后,就可以通过手动或Webhook的方式触发整个构建流程。也就是说只要用户一提交代码,就会触发整个构建流程,编译源代码、打包Docker镜像、推送镜像仓库并触发滚动升级,用户可以在分钟级别看到效果。 在这里我们还做了一些小的功能:
容器通常需要业务进行无状态的改造,所谓“无状态”是需要把一些状态数据放在外部的中间件或存储里。
我们提供了两种存储方式:NFS和Cephfs文件存储。用户在页面选择存储的容量,然后点击创建,就可以直接创建一个Cephfs文件存储,并且可以在服务管理页面指定将这一存储挂载到容器的某一个路径下,当容器重启或者迁移后,文件存储会保持之前的目录挂载,从而保障数据不丢失。
公司有大概100多个Nginx集群,之前这些Nginx集群都是通过运维人员手动方式变更配置和维护,配置文件格式不统一,且容易配置错误,问题和故障定位都很困难。为此我们在容器云集成了Nginx配置管理,通过模板的方式生产Nginx配置。Nginx配置的功能比较多,包括健康检查规则、灰度发布策略等相关配置。
上图是一个系统管理员可以看到的页面,其中部分项目开放给业务用户,允许用户自己定义部分Nginx配置,如upstream列表,从而将公司域名配置模板化。
除此之外,我们还做了配置文件的多版本对比,Nginx的每次配置都会生成一个对应的版本号,这样就可以看到在什么时间Nginx被谁修改了哪些内容等,如果发现Nginx配置修改有问题,可以点击回滚到Nginx的历史版本。
泛域名解析,主要适用于测试环境。之前每一个测试服务都需要联系运维人员单独申请一个域名,为了节省用户申请域名的时间,我们为每个服务创建一个域名,系统通过泛域名解析的方式,将这些域名都指定到特定的Nginx集群。
Nginx后端可以包含容器也可以包含虚拟机,这是在业务迁移过程中非常常见的,因为很多业务迁移到容器都并非一蹴而就,而是先将部分流量切换到容器内运行。
现在的架构提倡代码和配置分离,即在测试环境和生产环境使用相同的代码,不同的配置文件。为了能够动态变更配置文件,我们通过Kubernetes的Configmap实现了配置文件管理的功能:将配置文件挂载到容器内,用户可以在页面上传或者编辑配置文件,保存后,系统将配置文件更新到容器内。
就是说当用户在页面上传或编译某个配置文件以后,平台会自动把配置文件刷新到容器里,容器就可以使用最新的配置文件了。为了避免用户误删配置文件,当系统发现配置文件被使用则不允许删除。
告警管理功能基于Prometheus实现。平台会把所有的监控数据,包括容器相关的(CPU、内存、网络IO等)、Nginx相关的、各个组件状态相关的数据,都录入到Prometheus里,用户可以基于这些指标设置监控阈值,如果达到监控阈值,则向运维人员或业务人员发送告警。
值得一提的是,我们提供了一种特殊的告警:单个容器性能指标。按常理,每个容器监控指标应该是类似的,没有必要针对单个容器设置告警,但在实际生产环境中,我们遇到过多次由于某个特定请求触发的bug导致CPU飙升的场景,所以开发了针对单个容器的性能告警。
前面介绍了系统的一些常用功能,接下来介绍宜信容器云平台落地过程中的实践。
容器的使用方式建议用户将日志输出到控制台,但传统应用的日志都是分级别存储,如Debug日志、Info日志、Error日志等,业务需要采集容器内部指定目录的日志,怎么实现呢?
我们通过二次开发Kubelet,在容器启动前判断是否有“KUBERNETES_FILELOGS”这个环境变量,如果存在,则将“KUBERNETES_FILELOGS”指定的容器目录挂载到宿主的“/logs/容器名称”这个目录下面,配合公司自研的日志采集插件Watchdog便可以将宿主机上这个目录下的文件统一收集。
在实际过程中我们经常遇到网络对外提供服务的场景,系统中除了Nginx提供的 HTTP反向代理以外,还有一些需要通过TCP的方式对外提供的服务,我们通过系统中指定的两台机器安装Keepalive和配置虚IP的方式,对外暴露TCP服务。
自动扩容,主要是针对业务指标的一些突发流量可以做业务的自动伸缩。其原理非常简单:因为我们所有的性能指标都是通过Prometheus统一采集,而Cluster-mgr负责多集群管理,它会定时(默认30s)去Prometheus获取容器的各种性能指标,通过上图的公式计算出每个服务的最佳副本个数。公式很简单:就是每个容器的性能指标求和,除以用户定义目标指标值,所得结果即为最佳副本数。然后Cluster-mgr会调用Ipaas操作多个集群扩容和缩容副本数。
举个例子,现在有一组容器,我希望它的CPU利用率是50%,但当前4个副本,每个副本都达到80%,求和为320,320除以50,最大副本数为6,得到结果后就可以自动扩容容器的副本了。
传统模式下,单个Kubernetes集群是很难保证服务的状态的,单个集群部署在单个机房,如果机房出现问题,就会导致服务不可用。因此为了保障服务的高可用,我们开发了多集群管理模式。
多集群管理模式的原理很简单:在多个机房分别部署一套Kubernetes集群,并在服务创建时,把应用部署到多个Kubernetes集群中,对外还是提供统一的负载均衡器,负载均衡器会把流量分发到多个Kubernetes集群里去。避免因为一个集群或者机房故障,而影响服务的可用性。
如果要创建Kubernetes相关或Deployment相关的信息,系统会根据两个集群的资源用量去分配Deployment副本数;而如果要创建PV、PVC以及Configmap等信息,则会默认在多个集群同时创建。
集群控制器的功能是负责检测Kubernetes集群的健康状态,如果不健康则发出告警,通知运维人员切换集群,可以将一个集群的服务迁移到另一个集群。两个集群之外通过Nginx切换多集群的流量,保障服务的高可用。
这里有3点需要注意:
如何加速整个CI/CD构建的流程?这里总结了四点:
什么样的程序适合运行在容器里?
在实践过程中会遇到很多问题,本节将列举一些已经踩过的坑,逐一与大家分享我们的避坑经验。
这种情况可能是因为服务被放在了后台启动,容器的方式和之前虚拟机的方式有很大区别,不能把容器服务放在后台启动,容器启动的进程的PID是1,这个程序进程是容器里唯一的启动进程,如果程序退出了容器就结束了,这就意味着程序不能退出。如果把程序放到后台启动,就会出现进程起来了但容器服务没有起来的情况。
之前使用虚拟机的时候,由于配置比较高(4核8G),很多业务人员没有关心过这个问题。使用容器之后,平台默认会选中1核1G的配置,运行速度相对较慢,这就导致了业务在访问业务的时候会觉得服务启动和访问变慢。
这和配置的健康检查策略有关,如果某应用的配置健康检查策略不通过的话,Kubernetes的Liveness探针将会重启该应用;如果业务是健康的,但提供的健康检查接口有问题或不存在,也会重启这个容器,所以业务要特别注意这个问题。
这个问题非常常见,大多是由于编译环境和服务器环境的不一致导致的。很多业务在本地编译的时候,本地有一些开发工具的加持,有一些工作开发工具帮助完成了,而服务器上没有这些工具,因此会出现这个问题。
这个问题和容器使用相关,容器里默认会为用户保存最近两天的日志,主机上有一个清理的功能,日志超过两天就会被清理掉。那这些超过两天的日志去哪里查看呢?我们公司有一个统一的日志采集插件Watchdog,负责采集存储历史日志,可以在日志检索系统中检索到这些历史日志。
每次容器重启,其IP地址都会发生变化,希望业务人员的代码不要依赖这些IP地址去配置服务调用。
容器已经异常了,为什么还有流量过来?这个问题具体表现为两种情况:业务没起来,流量过来了;业务已经死了,流量还过来。这种两种情况都是不正常的。
很多时候这些容器还没有起来,此时当然就无法登陆。
这几个问题也经常遇到。在业务使用过程中会配置CPU、内存相关的东西,如果没有合理配置,就会导致容器的OOM。我们新版的容器镜像都是自适应、自动调整JVM参数,不需要业务人员去调整配置,
容器不是虚拟机,所以有些容器的使用方式并不能和虚拟机完全一致。在我们的业务场景里还有一个问题:业务需要调整时钟。
容器和虚拟机的其中一个区别是:虚拟机是独立的操作系统,修改其中一个虚拟机里的任何东西都不会影响其他虚拟机。而容器除了前面说的几种隔离以外,其他东西都不是隔离的,所有的容器都是共享主机时钟的,这就意味着如果你改了一个容器的时钟,就相当于改了整个所有容器的时钟。
如何解决这个问题呢?我们在网上找到一种方案:通过劫持系统调用的方式修改容器的时钟。但这个方案有一个问题:faketime不能睡着了。
经过几年的推广,目前宜信容器云平台上已经支持了100多条业务线,运行了3700个容器,累计发布17万次,还荣获了“CNCF容器云优秀案例”。
前文介绍了宜信容器云平台目前取得的一些小成就,即宜信容器云平台的A点,接下来介绍宜信容器云的B点,即未来的一些规划。
公司有很多文件需要对外提供访问,如网页中的图片、视频、pdf、word文档等,这些文件大部分都是零散地保存在各自系统的存储中,没有形成统一的存储管理。如果文件需要对外提供访问,则是通过Nginx反向代理挂载NAS存储的方式,这些文件的维护成本非常高,安全性也得不到保障。
我们基于Ceph开发一个统一的对象存储服务,把公司零散在各个系统的小文件集中到对象存储中去,对于可以提供外网或公网访问的部分,生成外网访问的HTTP的URL。目前对象存储已经在业务的测试环境上线。
站点监控是一个正在重点研发的功能。公司开源了智能运维工具UAVstack,侧重于应用的监控,还缺乏服务外部的站点监控。站点监控是为了监控服务接口的运行状态,并发送告警。
我们通过在公司外部部署采集Agent,这些Agetnt会根据用户定义的监控URL定时调用接口是否正常运行,如果接口返回数据不符合用户设定条件则发出告警,如HTTP返回5xx错误或者返回的body中包含ERROR字符等。
在大部分业务迁移到容器后,我们开始尝试将各种大数据中间件(如Spark、Flink等)也迁移到Kubernetes集群之上,利用Kubernetes提供的特性更好地运维这些中间件组件,如集群管理、自动部署、服务迁移、故障恢复等。
公司有很多长任务,这些长任务有一个非常明显的特点:白天访问量较高,晚上访问量较低。对应的是批处理任务,批处理主要指公司的跑批任务,如报表统计、财务账单等,其特点是每天凌晨开始执行,执行时对CPU和内存的消耗特别大,但只运行十几分钟或几个小时,白天基本空闲。
为了得到更高的资源利用率,我们正在尝试通过历史数据进行建模,将批处理任务和长任务混合部署。
最后介绍我们整个平台的DevOps规划。
回到之前容器云的背景,业务需要一套统一的DevOps平台,在这个平台上,可以帮助业务完成代码构建、自动化测试、容器发布以及应用监控等一系列功能。
其实这些功能我们基础研发部门都有所涉及,包括自动化测试平台 Gebat、应用监控UAVStack、容器云平台等,但是业务需要登录到不同的平台,关联不同的数据,而各个平台之间的数据不一致、服务名称不对应,没办法直接互通,操作起来非常麻烦。 我们希望通过建立一个统一的DevOps平台,把代码发布、自动化测试、容器运行和监控放到同一个平台上去,让用户可以在一个平台完成所有操作。
领取专属 10元无门槛券
私享最新 技术干货