美文网首页喜茶技术分享
喜茶基于 Spring Cloud 和 Kubernetes 构

喜茶基于 Spring Cloud 和 Kubernetes 构

作者: c80bbe47f715 | 来源:发表于2019-10-10 11:14 被阅读0次

            喜茶互联网技术中心花了一年的时间,将一整套基于 Spring Cloud 和 Kubernetes 构建的云原生(Cloud-Native)微服务应用落地,目前服务都已经部署在云上,一直保持着非常良好的运行状态。

            在完成了首次应用落地之后,喜茶互联网技术中心将以更快的迭代速度落地更多的云原生应用。在过去这一年的落地实战过程中,我们始终坚持做一件正确的事——“技术和架构约定高于配置,推行大规模自动化建设的同时,在内部普及 DevOps 文化”。让内部的所有人都参与到这件事里面进来,甚至带有强制性,因为云原生微服务应用的构建非常依赖于契约,我们的未来是大规模云化和微服务化,所以只有当大家都有了契约意识之后,才能正常的开展各项工作,才能保持我们的整体形散而神不散。如果过去的这一年我们没有坚持做这件事情,估计在这个时间点还没办法写出这篇总结性的文章。

            关于云原生应用,《Migrating to Cloud-Native Application Architectures》的作者 Matt Stine 在书中解释得非常到位,总结的非常全面也比较抽象,有兴趣的可以研究一下,pivotal 官网提供了电子版(点击这里下载),内容 50 几页。其内容包含了技术和管理诸多方面的论证,简单的理解就是为了传统的单体应用和面向服务的应用更好地迁移到云上,更好地利用云优势,组织、技术和文化作出了必要的改变。

    DevOps 文化的普及

            虽然我们把“DevOps 文化的普及”排在“约定高于配置,大规模自动化建设,普及 DevOps 文化”三项任务(重要程度)的末尾,但实际上却是最先进行。DevOps 文化的推行直接影响到管理和组织结构,还有沟通方式、做事方式、技术栈、术语等等内容,所以在万事开头,让大家都知道我们接下来要做什么,然后才开始安排做的时间和怎么做似乎更符合我们的状态。当时我们评估过实际情况,发现缺少了一个云平台部门,也就说是缺少云端支持,两名运维人员也相对缺乏深入的容器云运维经验,于是我们开始转向“由后端开发主导”的方向,因为 DevOps 本身模糊了很多开发和运维的工作边界,如果能从开发侧找到 DevOps 的入口,我们依然可以在人力上更胜一筹。果不其然,在选定公有云为基础平台的前提下,我们不需要做太多关于云方面的运维,云厂商保障了我们所需的网络和存储高可用,借助 Kubernetes 和 Docker 容器技术,让我们的开发侧同学需要去涉及的运维工作仅仅到构建出一个镜像就可以止步,剩下的工作就是 Kubernetes 自动运维和应用参数调优。

            在我们的 DevOps 文化里,运维工作的目的并不是维持系统稳定,而是促进业务敏捷上线,系统稳定性的运维工作已经被自动化工具和云厂商大范围取代。而开发同学的工作除了常规业务开发外,还需要知道怎样快速无差别的交付代码到其他阶段环境运行,适当的参与运维或者指导运维再合适不过了。如此,开发和运维工作边界才变得有些模糊,但目的是统一的。

            DevOps 文化的普及第一步是让运维和开发融会贯通,抹平两边的边界障碍。然后,通过开发侧的控制和引导,让产品侧接受 DevOps 的操作方式,产品侧都是希望需求能快速推上线,更希望紧急需求可以极速上线,所以说如果 DevOps 方式能做到做好,那自然没有不接受的理由;通过运维侧的控制和引导,让测试和线上反馈接入 DevOps;通过逐渐引导 DevOps 文化,疏导规范流程,推进自动化,横向打通管理组织,纵向集成技术栈和工具链,保证质量和安全,提升交付能力,稳定交付节奏。

            更具体的表现为:(1)、开发侧控制了需求入口,总是让需求有大小、有轻重、有缓急地串行进入开发侧,不相关的需求安排成并行开发,然后并行测试,最后测试控制了需求出口,运维将需求串行快速上线,类似于总分总策略。(2)、重新工程化所有项目,项目的工程化是为了支持快速构建、发布和运行流程,在项目的生命周期中,需求、开发、测试、发布、维护的每一步都由多个角色组协作,从而每一环节可以平滑衔接。

            就这样开发侧作为 DevOps 入口,我们开始了 DevOps 的推行,首先是高仿真生产环境,在公司内部自建了一套 Kubernetes 环境用于开发调试、前后端联调以及技术预研,然后在云上创建了测试环境和预生产环境用于无限逼近生产环境。很自然地,从开发到测试再到生产的过度,环境相似度正在逐渐逼近生产环境,流转工作 90% 由自动化工具完成,使得阶段流转非常的快捷。

            当所有人都知道并熟悉这种文化和方式之后,我们发现,没有人工干预的环境出故障的机率微乎其微,人力都可以全力扑在需求设计和实现上,这大概就是我们普及的整个 DevOps 文化的核心部分。

            当然,前期也是障碍不断,比如喜欢按照传统方式做开发管理的同学会不断质疑,我怎么知道我在操作的对象是什么,我们对于那些没有经手操办的事情难免有些顾虑,这是严谨的态度,也是正常反应;又比如当并行开发的需求非常多时,如果只让一个人去管理所有事务,将会变的非常困难,只有扁平化的组织结构,权力下放给得力助手才能比较好的应付这种“高并发”模式。诚然,这类障碍归根到底还是 DevOps 普及不到位,只能慢慢磨合和过渡。

            一个最大的疑问是 DevOps 是否真的就适合我们!坦白说,答案只有在试运行之后才能知晓。这里说的“适合”指的是人和组织是否“适合”。我个人有过传统应用转云效率反而下降的经历,究其原因是组织固化,新文化推不动。当出现这种情况时,可以采取开辟新天地的方式,让新的应用系统先行,再逐步重构或者替换老的系统,前期用更多的资源来换取更高的成功率。我们公司在推行 DevOps 的过程中,尝试了两次 PHP 旧系统的云化后,还是决定放弃,转而直接进入新架构的云化进程,也就是实现基于 Spring Cloud 和 Kubernetes 的云原生新架构。其中的技术选型出于诸多因素的考虑,比如资源和未来的发展方向,我们的 DevOps 针对的也都是新架构下的技术栈和工具链,旧系统大体维持不变。

            普及 DevOps,工具很关键。开发团队和运维团队为了促进业务敏捷快速,需要一系列支持快速发布软件的工具和文化。其中工具包括:自动化构建、持续集成、持续部署、持续监控、机器人和统一平台等等。

    大规模自动化建设

            普及 DevOps 伴随着大规模的自动化建设,没有自动化的支持 DevOps 寸步难行。

            从代码编辑器、版本管理工具、配置管理、文档管理、构建工具、部署工具、测试工具、监控工具、数据采集工具再到机器人工具等等组成的工具链,从编程语言、框架、依赖管理、打包、数据持久化技术、分布式、高可用、安全,容灾等等组成的技术栈,都需要能够支持自动化或者被自动化。当自动化在这些方面帮我们完成的工作量低于 80% 时就会有明显的不顺畅感,我们的管理工具需要做到贯穿一整个项目的生命周期,也一并把工具链和技术栈整合在一起,像拉链一样工作。

            自动化建设本身不直接产生业绩之类的东西,短期内没能看出有什么明显的产出价值,虽然也可以白纸黑字的存在在那里,却没办法直接产生收益,终究不像业务需求那么直白明了,一个接着一个,有开始有结束,每个组织、每个部门都能清清楚楚地看到,老板也是喜闻乐见。即便如此,还是有一点需要特别提醒,自动化建设属于战略性的东西,讲的是铁打的营盘,业务需求属于战术,一般讲怎么快速获取更高的成功率。战略是航母,战术是航母上的战斗机,没战略也可以成功,有战略能走更远。

            做战略性的事情就需要分清主次,在 80% 常用功能的范围内才需要考虑做自动化,20% 的功能属于临时或者不规范的功能,即使做了自动化也是徒增维护成本。要 100% 实现自动化是不现实的,因为大规模自动化建设是要花大成本的,特别是初期,考虑到投入和产出,我们不会把那些突发奇想的需求纳入到建设进程,一般是做备忘录日后再说,我们的目标是支持突发奇想但不全为突发奇想。如今市面上花花绿绿各种方案,开源的,闭源的,一般都是需要精心挑选和自定义整合,最终也是半自研产品,没有见过百分百吻合公司需求的方案,即使是买也是花钱等。

            说到大规模自动化建设的目标就不得不提契约,毫无契约的自动化建设是盲目的,后果是失控和不堪重负。扩展性和灵活性我们可以量力而为,想用不变应万变是不存在的,约定高于配置、限制无节制的扩展更像是我们想要的东西。我们从目前的样子,预测未来大概会是个什么样子,然后制定几种约定好的模式,比如 Java 语言的工程用 Maven/Gradle 来管理,且构建产物为一个可执行的 jar 包,包名和工程名一致等等,只要任何 Java 工程都同时具备这几个要素,就可以接入自动化系统,那些突发奇想的需求尽可能去靠近约定,一切都将变得很顺利,这就是要求约定高于配置的原因之一。如果有人想突破约定,又能讲明白为什么也是可以的,能讲出个所以然,很大概率是我们需要升级一下自动化系统。

    技术和架构约定高于配置

            为了更好更规范的开展工作,约定高于配置(大道至简)一直是我们秉承的原则,这个原则也已经在业界备受欢迎,特别是在构建云原生应用领域,比如“12-因子(Twelve-Factor)”规范不仅仅方便了开发,同时也方便了运维。又比如 Ruby on Rails、Spring Boot、Seneca 等等框架,KISS(keep it simple and stupid),非常适合快速起步,同时也减轻了协作和维护成本,这是开发侧的例子,运维侧的比如 CI/CD 约定好流程怎么走,工程只要包含一个钩子,从开发到测试再到生产所有的环境就都已经就绪,DevOps 般的默契,一切尽在不言中。还有监控、机器人也是如此。他们的特点都是在约定的基础上横向扩展毫无压力。

            约定高于配置原则纵向(深度)的表现有点独裁,比如技术选型,往往是架构师独裁决定,当然不是那种用屁股思考做决定,而是根据当前实力做超前一点的决定,如果实力无法支撑,就实施备用计划,有时是在最求完美的背后留一手,有时是在预防碎片化。

            喜茶互联网技术中心之所以选择了 Spring Cloud 和 Kubernetes,一是约定高于配置,二是有实力支撑。

            Spring Cloud 的约定高于配置是因为基于 Spring Boot,Kubernetes 的约定高于配置是因为内置了自动化运维。从实力上来讲,Spring Cloud 开发和普通的 Spring 开发没有本质的区别,非常普遍;又我们有开发同学曾做过 Kubernetes 开发,对其工作原理非常熟悉,有什么功能我们可以直接使用,又有什么功能稍微打磨一下就可以变成金子,其中优劣了如指掌,在 Spring Cloud 和 Kubernetes 的结合上有着丰富的实战经验。

            选择 Kubernetes 作为稳定的自动化运维平台,依托云厂商,又不被锁定在特定的云厂商上,自建也压力不大,这是我们放心选择 Kubernetes 的主要原因之一,其他比如语言无关的微服务平台、潮流等等都不是我们目前重点考虑的因素。我们是做应用和应用平台,不是做运行平台,因此,“语言无关的微服务平台”其实并没有“语言无关的微服务协议”来的诱人,从技术角度上讲,HTTP 差不多算是“语言无关的协议”,其他的像 gPRC、Dubbo 协议,也都很好,就是感觉有点儿“语言有关”。

            选择 Spring Cloud 的原因很显然是因为 Spring 的前景和社区支持,另外就是她提供了一整套的解决方案并且非常的开放,最后就是她使用的是 HTTP 协议。前面两点无需解释,最后一点主要还是考虑到未来我们的系统大体上是 Spring Cloud 应用为主,其他语言的应用为辅的混合模式,HTTP 相比 gPRC、Dubbo 等协议性能差个 2-3 倍也无妨,目前横向扩展足够弥补 HTTP 协议性能稍差的缺陷,未来要不要整改也就是投入和产出的问题,架构都是需要演化的,前期追求的是易用性、完整性和扩展性,后期考虑性能优化,再者,都用微服务架构了,局部替换技术对整体的影响并不大,又得益于 Spring 一贯以来良好的设计抽象,技术也已经证明可行。

            有人说,有了 Kubernetes 就可以不用 Spring Cloud 那一套了!我个人认为不必这么武断。显然他们两者各有所长,如果可以做到扬长避短倒是顺势,如服务注册和发现、配置、负载、远程调用的选择等等,Kubernetes 固然是和语言无关的微服务架构,当我们的系统同时存在多种异构语言的服务时,这点相对 Spring Cloud 是个优势但不明显。有人说,Spring Cloud 的微服务架构模式是强耦合,仔细考察确实有那么一点,不过除了 Service Mesh 那种 Sidecar 模式,似乎没有不耦合的编程模式,使用了 HTTP 协议后也并非真的那么耦合。另外一点就是,在需要做微调的时候我们更加倾向于代码控制,而不是去做各种 Kubernetes ops 方面的操作,比如细粒度的灰度发布、细微的负载调整等等,所以,完全只用两者中的一个都会显得不那么完美。限于篇幅这里就先不展开两者之间的异同点,以后有机会再写一篇文章来详细简介 Spring Cloud 和 Kubernetes 在生产上的互补和相辅相成。这里只想明确一点:选 Kubernetes 是看中了她的自动运维,选 Spring Cloud 是看中了她提供了一整套微服务解决方案并且非常开放,前者大范围取代了运维的人工操作,后者大规模的简化了架构工作,两者的结合,在目前看来是一组最优解。

            坦白讲,我们的“技术和架构约定高于配置”始于技术选型服务于技术选型,归根到底还是看业务需求。为了形成可靠的交付节奏,在遵守每项技术的最佳实践中,制定了自己的最佳实践。我们把指导构建云原生应用的 Twelve-Factor 应用于实践中,但也杜绝本本主义,比如:早期日志系统没有稳定,我们的日志并非只输出到控制台,同时也文件存储,当某一天日志系统稳定了,环境变量切换一下即可,显然这种权衡状态下,开发关心了日志收集,分担了运维的一点工作,避免了日志丢失,但也只是短暂的。

    总结和展望

            云原生应用的落地涉及的技术和文化是方方面面的,这篇文章描述的内容只是指导原则中的三个大方面,点到为止,具体技术细节和实操过程只能在后续文章中再大篇幅展开。

            总之,喜茶云原生应用的构建以及 DevOps 文化的普及是在为业务快速发展布道,云化和自动化是为了节省更多的成本。经过过去一年的铺垫,我们在未来的一年里将开始展开多集群、多中心、跨区域,还有中间件的开发工作,最终要实现的目标是随喜茶出国而全球化。

    -- 2019.10.04 完

    相关文章

      网友评论

        本文标题:喜茶基于 Spring Cloud 和 Kubernetes 构

        本文链接:https://www.haomeiwen.com/subject/qquopctx.html