上映日期:2020年6月23日11时54分28秒
资料来源:51CTO
阅读量:566
作者:牧场主实验室
专栏:云计算
口述/作者:
江江,新东方信息管理部平台架构负责人
陈博轩,新东方信息管理部高级运维工程师
编辑:
牧场实验室
江江,新东方信息管理部平台架构负责人
陈博轩,新东方信息管理部高级运维工程师
2017年,新东方开始探索以容器化的方式服务中间件业务,使用基于Rancher 1.6的ES;2019年,新东方再次开始拓展中间件的业务服务,使用基于Kubernetes的Kafka、ES和Redis。利用容器化手段服务中间件,有效提高了运维团队的工作效率,大大缩短了软件开发流程。本文将分享新东方在中间件服务方面的尝试。
从幼儿园、小学、中学、大学、留学,新东方几乎涵盖了教育的每一个领域。我们的教育产品线很长,也很复杂。那么,我们用什么样的IT能力来支撑这么长的教育线呢?新东方云。
我们目前有16个云数据中心,包括自建和租赁的IDC。我们还通过云联网直接连接了阿里云和腾讯云,最终形成了跨越多个云提供商的混合云架构。新东方的云系统很特别。你可以在里面看到一些比较传统的部分,比如SQL Server,windows和柜台服务程序。但是也有一些新潮的东西,比如TiDB、容器、微服务等等。除此之外,还可以找到一些视频双师、互动直播等偏互联网应用。企业的IT架构与企业的业务阶段密切相关。像成千上万从传统业务转向互联网的企业一样,新东方正处于数字化转型的关键阶段。
接下来说说新东方的集装箱化。新东方做集装箱已经很多年了。2016年,新东方尝试了一些基于docker Swarm的商业解决方案,都不太理想。2017年是容器布局架构发生变化的一年。我们选择Rancher的牛机开始集装箱化的自主建设,也是在看行业趋势。2018年,新东方的集装箱建设再次进化,最终转向K8S。
那么大家怎么看待新东方的K8S呢?我们认为K8S是PaaS和IaaS之间的中间层,接口和规范都是针对IaaS下层和PaaS上层制定的。但是不关心功能实现。而我们想做一个完整的容器云,只有K8S是不够的,还需要引入其他开源组件来补充。
从上图可以看出,我们利用各种开源团体对K8S生态系统进行补充,组合成目前新东方的容器云平台。
我们的运行时组件基于Docker,主机操作系统选择Ubuntu,K8S网络组件使用Canal,采用Mellanox网卡加速技术。作为我们的k8s管理平台,Rancher 2.0提供了多租户管理、可视化、对AD域的权限对接等重要功能,帮助我们避免了大量的后台集成和整合工作,在节省人力的同时提供了稳定的图形化管理平台。
下面介绍一下我们的K8S做法。从上图可以看出,我们完全基于K8S的原生社区版本。通过kubeadm工具和nginx流负载均衡部署成三节点HA架构。
群集的关键组件以主机网络模式运行。这样可以减少网络上的资源消耗,获得更好的性能,比如Ingress组件,通过法兰绒构建覆盖容器网络,运行上层应用。
使用容器肯定需要涉及图像管理。新东方是Harbor的早期用户。我们从1.2版本就开始使用Harbor,后端存储与ceph对象存储相连。目前,我们正在尝试镜像分发功能,使用阿里云的开源蜻蜓。它可以将南北向的下载流量转换成东西向的,这使得在节点之间复制图像成为可能。当集群规模非常大的时候,减少在Harbor服务器上拉镜像带来的压力负载。
我们的K8S集群完全运行在物理机上。当集群规模较大时,物理机的数量会增加。我们必须使用物理机的管理软件来降低我们的运维成本。
这里我们使用的是Ubuntu的Maas,这是一个裸机管理平台,可以根据模板将没有操作系统的物理机安装成指定的标准物理机。我们将结合Ansible playbook对物理节点进行初始化,将其变成我们想要的物理机节点,并将其加入集群。
从上图可以看出,通过加载TiDB的角色,标准物理机变成了TiDB的一个节点,通过K8S的角色,标准物理机变成了K8S节点。我们会把Osquery和Filebeat推送到每个角色的物理机,他们可以收集物理机的机器信息,推送到CMDB进行资产管理。
我们的CI/CD是基于业务进行差异化的,一部分直接接入新东方自己的Jenkins,另一部分业务直接接入Rancher Pipeline功能实现CI/CD。
对于集群监控,我们现在使用开源社区Prometheus的操作员。一开始我们用的是原生普罗米修斯,但是原生普罗米修斯在配置告警发现和告警规则方面特别麻烦。
引用运营商后,运营商帮助我们简化配置流程,相对简单易用,推荐给大家使用。
值得一提的是,Rancher版之后的集群监控是基于Prometheus算子的。有兴趣的话可以回到下一个新版本的RANCHER去体验一下。
我们的日志设置为两个级别。业务日志通过sidecar运行filebeat,将数据收集到kafka集群中,再由logstash消费到ES中,可以减轻ES的压力负载。
另一方面是集群级,集群级的日志通过Rancher 2.2提供日志收集功能,用fluentd收集到ES集群中。
我们总共有五个集群,一个用于在线业务,两个用于生产和测试;一个是Platform1 cluster,运行中间件应用,如ES、Redis、Kafka,也分为生产和测试两套;还有一个测试集群,用于测试功能。K8S集群升级迭代,测试新组件,测试新功能都是在这个集群上完成的。
可能细心的朋友发现我们的集群是1.14.1版本,版本很新。为什么?因为Kubernetes 1.14有一个很重要的功能叫本地PV,已经是GA了,我们很看中这个功能,所以一路升级集群到1.14。
目前,商业应用主要在两个方面:
口袋泡泡APP和新东方APP后台服务都运行在容器云架构上。
中间件服务,如Kafka、Redis和es集群级中间件服务,都运行在我们的容器云架构上。
为什么要对中间件进行服务?
那么,我们为什么要服务中间件呢?
在我们看来,中间件如ES、queue、Redis缓存等。都有几个共同的特点,就像图中的怪物,很大。
我举个例子比较一下:比如我开一个商家的虚拟机,4C8G比较常见,前10个都是40C 80G。相比之下,40C80G可以启动elasticsearch的一个节点吗?40C 80G启动一个es节点是很紧张的。在实际生产中,一个高通量的ES节点一般需要100G以上的内存。从这个例子中我们可以认识到中间件负载的单个资源消耗是非常大的。
另外,项目中广泛使用中间件,任何应用肯定会用到Redis、MQ等组件。任何组件的单次部署都会占用多个虚拟机。每个项目都希望有一个小灶,独占一个环境。但是小灶消耗的资源更多,中间件的各种版本和配置难免不一样。我们需要雇佣很多人来维护中间件,这是个大问题。
当然,如果全公司只有十几个项目,完全用虚拟机也是可以的。但是新东方现在有三四百个项目,中间件消耗资源相当大。如果全部使用虚拟机资源,成本还是很高的。
那么我们如何解决这个问题呢?我们提供三支箭:集装箱化、自动化和服务。
集装箱化是最容易理解的。刚才提到了各种杂七杂八的配置,都是用容器统一的。你必须遵循我的标准。将容器直接部署到物理机上,以获得更好的性能和灵活性。
容器化的下一步是自动化,更准确地说实际上是编码。它是以迭代的方式对基础设施进行编码和管理。我们使用Helm和Ansible实现编码和自动化。
前两步做完了,就可以进入第三步了。如果用自己的管理规范和最佳实践来约束大家,可能效果不大。最简单的方法是导出服务,这样每个人都可以使用我们的服务。
逐步将小火炉合并成大锅饭,削峰填谷,避免资源浪费。每个公司或多或少都有一些超级VIP项目。这种生意就成了大锅里的另起炉灶。也是同样的机制,但是我会分别给你提供资源隔离和权限隔离。
在服务之前,我们对运维人员的了解更多的是项目的劳务输出。每天都很忙,却看不到多少成绩。服务后,将劳务输出转化为服务平台的建设,赋能一线人员,让二线人员做更有意义的事情。
我们的实践:ELK/ES
接下来,我们就来一一解释一下新东方的中间件的安排。
Elastic有个产品叫ECE,是业内第一个对ES进行容器化管理的平台。ECE是基于K8S的1.7(或1.8)实现的。通过容器和物理机的方式为用户提供各种版本的ES实例。但它也有一定的局限性:只能管理ES,其他中间件不能。
这给了我们很大的启发,我们想是否可以模仿,按照Rancher Docker的方式,做自己的服务平台。所以我们平台的第一个版本诞生了,用Rancher 1.6来管理麋鹿。
上图是我们的麋鹿群,是Rancher 1.6和k8s的混合体,目前正处于向k8s迁移的中期。
我们有两个版本的麋鹿布局:UAT环境布局和生产布局。在UAT环境中,我们采用rook(ceph)机制,ES节点由Statefulset启动。这个方案的好处是,万一哪个节点死了,存储和计算完全分离,你想漂移到哪里就漂移到哪里。
我们的生产环境将会不同。我们会把每个ES节点都做成一个部署,不会让它随波逐流。我们将使用污点和标签将部署限制在某个主机上。POD的存储不再使用RBD,而是直接写入本地磁盘hostpath,网络使用主机网络获得最佳性能。
如果我挂了呢?挂机等待本地复活。机器挂机,重启,换盘或者换硬件。如果不能复活呢?我们有一个机器管理,机器被杀,直接从池中拉出一个新的机器,并且是在线的,使用ES的复制功能复制数据。
你可能会奇怪为什么你有两套方案,制作安排这么难看。
我们相信简约的建筑是最美的建筑。中间环节元件越少,故障点越少,越可靠。本地磁盘性能优于RBD,本地网络优于K8s网络栈。最重要的是,我们安排的这些中间件应用其实都是分布式的(或者内置HA架构),都内置了复制机制,完全不用考虑做K8S级别的保护机制。
我们还对这两种方案进行了实验比较。如果节点挂起,本地重启时间比漂移时间短得多,RBD有时会有漂移的问题。物理部分彻底不及格的概率还是很小的。所以我们最终选择了在线环境下稍微保守一点的方案。
我们的实践:Redis
我们现在的Redis主要是哨兵方案,也是以部署仅限于特定节点的方式来安排的。我们的Redis不做任何持久化,纯粹作为缓存使用。这样会带来一个问题:如果主人挂机,那么K8S会立即重启,而这个重启时间必须小于哨兵发现它挂机的时间。它醒来的时候还是一个主,是一个空的主,然后剩下的从里面的数据会全部丢失,这是不能接受的。
我们之前做了很多研究,参考携程的做法,在容器启动的时候使用Supervisord启动Redis。即使POD中的Redis挂机,POD也不会立即重启,从而给哨兵足够的时间进行主从切换,然后通过人工干预恢复集群。
在Redis的优化中,我们为每个Redis实例绑定CPU。我们知道Redis进程会受到CPU上下文切换或者网卡软中断的影响。因此,我们对Redis实例所在的节点做了一些限制,并用taint标记。我们将操作系统所需的所有进程绑定到前N个CPU,留下CPU运行Redis。启动Redis时,进程和CPU会一一对应,以获得更好的性能。
我们的实践:卡夫卡
众所周知,Kafka是一个高吞吐量的分布式发布和订阅消息。与其他中间件相比,Kafka具有高吞吐量、持久化数据和分布式架构的特点。
那么,新东方如何使用卡夫卡呢?Kafka集群有什么特殊要求?
我们按照业务应用场景分组,将分为三类:第一类是使用Kafka作为交易系统的消息队列;第二种是使用Kafka作为业务日志的中间件;第三类是卡夫卡作为交易系统的消息队列。
如果要满足这三个应用场景,我们的Kafka必须满足安全需求。例如,交易数据不能以明文传输,因此必须进行安全加密。
接下来,我们来解释一下卡夫卡的原生安全加密。我们怎么做呢?你是怎么选择的?
除了金融行业,其他行业在使用Kafka时一般不会使用其安全协议。Kafka集群在不使用安全协议的情况下性能非常好,但是显然不符合新东方对Kafka集群的要求,所以我们开始了数据加密。
我们使用Kafka的原生支持,通过SSL加密Kafka的通道,把明文传输变成密文传输,通过SASL认证用户,通过ACL控制其用户权限。
让我们简单看一下两种SASL用户身份验证的区别。SASL_PLAIN就是将用户名和密码明文写在jaas文件中,然后将jaas文件以启动参数的形式加载到Kafka进程中,这样Kafka的客户端在访问服务器时就会拿着jaas文件进行认证,用户认证就开始了。
SASL GASSAPI是一个基于kerberos的KDC网络安全协议。熟悉AD领域的朋友一定知道Kerberos,Kerberos网络安全协议也在AD领域使用。客户端直接请求KDC服务器与KDC服务器交互,实现用户认证。
这两种方法各有利弊。最终,新东方选择了第一种SASL_PLAIN方法,原因很简单,我们可以避免单独维护KDC服务,降低运维部署成本。但是这种方法有一个问题,因为Kafka用户名和密码都是通过这个过程加载的。如果要更改文件,如添加用户和修改用户密码,必须重启Kafka cluster。
重启Kafka集群必然会影响业务,这是不可接受的。因此,我们采用灵活的方法,根据权限进行分组。jaas文件中预置了总共150个用户,管理员给项目分配不同的用户,避免了增加项目重启集群的尴尬。
如上图,我们在Kafka集群上开放了两个端口,一个是有用户认证和SSL加密的端口,另一个是没有SSL加密,只启用用户认证的SASL_PLAIN端口。连接到Kafka的客户端根据自己的需要选择要访问的端口。
架构之后,再来说说卡夫卡的编曲。我们的kafka和zk集群是通过主机网络部署的,数据量通过hostpath落到本地物理机上,以获得更好的性能。
Kafka和zk都部署在单个部署中,固定在节点上。即使有问题,我们也会让他在原机上重启,防止容器随意迁移。
监控采用exporter Prometheus方案,运行在overlay的容器网络上。
我们的实践:服务平台
我们做这个服务平台的时候,想法很简单:不要重复发明轮子,充分利用现有的技术栈,把helm、ansible、k8s结合起来。
以kafka为例,ansible根据环境生成helm chart,比如SSL证书和嵌入式用户配置,由ansible根据用户输入生成,生成的结果插入helm chart,然后helm根据chart创建相应的实例。
以下是我们平台1.0演示的一些截图。
这就是集群管理。当部署到不同的集群时,将有不同的集群门户来维护其状态。
上面显示的是申请服务的步骤。整个步骤非常简单,只需选择集群和所需的版本。
在这个管理界面中,您可以看到您的实例使用的IP、访问门户和端口(端口由平台自动分配)。如果是SSL连接,也可以获取自己的证书,可以直接从页面下载。稍后,我们还将访问集群到平台的日志。
我们的后台相当复杂。后台使用Ansible的AWX平台。这里可以看出,创建一个集群实际上需要大量的输入项,但是这些输入项都是在前台界面直接为用户生成的。
这是一个完整的Kafka集群部署,包括Zookeeper,Kafka和exporter进行监控。我们为每个集群配置了一个kafka管理器,这是一个图形化的管理控制台。你可以直接在管理器里管理卡夫卡。
监控报警必不可少,我们根据普罗米修斯算子制定了一些预设的报警规则。比如题目是否延时?当集群生成后,运营商会自动找到你的端点,也就是我们刚才看到的导出方。操作员找到端点后,会自动加入报警,无需手动接入。
我们为每个项目生成了可视化面板,需要监控时可以直接登录Grafana。
上图是一个简单的压力测量结果。512K消息和SSL ACL的配置是五个分区三个副本,大概是每秒100万条消息。配置是五个集装箱,16C 140G内存,SSD硬盘。我们发现,随着消息大小变大,性能也会下降。
服务平台路线展望
刚才我们谈到了今年的一些工作,那么明年我们想做什么呢?
从2020财年开始,新东方计划将这些服务全部服务化,比如Redis、es等,最终将这些暴露的API整合到云门家庭中,供集团内部用户或第三方系统调用。
还有一点不得不提的是运营商。上周,Elasticity发布了一个名为ECK的新项目,它是ES的官方运营商。
通过运营商,你只需要简单地输入CRD,运营商将自动生成你需要的集群。
我们相信基于舵的方法可以极大地简化Yaml的工作,但这不是目的。我们认为目的是运营商。
编者按:
本文基于2019年6月20日Rancher在京举办的第三届企业容器创新大会(ECIC)上新东方蒋江、陈博轩的演讲。今年的ECIC规模庞大,全天设置了17场主题演讲,吸引了近千名集装箱技术爱好者和超过10000名观众在线观看。可以在牧场主微信官方账号阅读更多大会发言记录的文章。
更多关于云服务器,域名注册,虚拟主机的问题,请访问西部数码代理官网:www.chenqinet.cn。