
我们创建了一个将Docker和Maven集成在一起的工具,以帮助我们的数百名开发人员以最少的努力通过数百种服务来管理复杂的开发环境。 这是关于一个疯狂的想法如何成为现实的故事。 这就是
卡诺泽特的故事。
这一切始于大约五年前(大约发布日期为2017年8月3日),Swissquote迅速发展壮大。 当时,我们大约有70个开发人员在处理大型(大约Monolithic)Java项目,要求他们每个人花1-2天的时间在本地配置项目的启动。 我们讨厌在重复的任务上浪费时间! 因此,决定通过使用Vagrant和Chef来自动化我们本地开发环境的部署来改进此过程。 这标志着我们第一个Sandbox项目(Sandbox,大约)的开始。
我们希望共享轻量级,可复制,隔离和可移植的开发和测试环境。
有一阵子,一切都很顺利。 开发人员只需下载项目,执行“无用功”即可开始工作。 我们使用这种方法大约两年了,对此感到非常满意。
随后,由于业务逻辑变得更加复杂(对我们的交易平台加白标签),处理这些大型应用程序变得更加困难。 我们决定做大多数组织在2014年所做的事情:将逻辑分解为微服务。
一切进展顺利,到2016年,我们已经生产了大约150种(微型)服务。 但是用于配置虚拟机的Chef脚本已经增长并且不受控制。 对于某些具有大约30个依赖项的应用程序,开发环境变得更加复杂。 我们还发现,Chef的知识不属于我们开发人员标准技能的一部分。 因此,许多人有时会通过复制错误的示例来使脚本正常工作。 为了不破坏其他团队的配置,他们为自己的团队需求创建了长期存在的早午餐,结果,开发环境配置代码不再公开。

我们不得不修复它。
我们的沙箱存在以下弱点:
- 需要认识厨师。 对于现有开发人员和初学者而言,学习此框架是一种非常昂贵的乐趣。
而且,这仅对开发/测试环境是多余的。 - 无法轻松地抽象/组合或重用部分环境配置。 这导致人们不得不深入研究其项目的依赖项配置的所有细节和细微差别,而这些细节和细微差别通常会得到其他团队的支持。 这导致了团队之间的分歧和不必要的互动。
为了解决第一点,决定改用Docker。 它具有较低的入门门槛,还提供了其他好处,例如标准化,PaaS支持以及更易于在多个环境中进行部署。
我们还考虑了仅使用docker-compose。 它看起来非常有前途,但是尽管有它的名字,但它缺少诸如组合的可能性,以及抽象和重用之类的东西。 我们需要这些方面。 我们梦想着能够采用现有的开发/测试环境,向其中添加一项服务,并可以选择重新定义其配置的一部分。 我们想要实现这一目标,而不必复制添加的服务的配置,也不必深入研究传递依赖及其配置的详细信息。
那时我们有了这个想法:“如果我们采用Maven,即用来构建Java应用程序的依赖管理系统,并开始使用它来构建环境,该怎么办?” 这将使我们能够抽象可传递依赖项,程序包配置,创建它们的版本并重新使用它们。 也将无需学习新的依赖管理系统。
经过多次尝试,我们得出以下解决方案:
- 每个Maven工件都代表一个功能完备的环境,可用作其他环境中的依赖项。 (最小环境可以由一项服务表示,例如数据库)
- JAR文件包含配置。 环境变量,应用程序配置文件,映像Docker名称等
- 如有必要,可以在依赖关系层次结构中位于较高位置的模块中覆盖此配置。
- Java库可以从一个Maven模块(GAV或pom.xml)提升整个环境(在后台使用docker-compose)。
Maven使分发和版本化这些工件(“环境工件”)成为可能,并且我们可以轻松地在团队之间共享源代码。 这个过程变得更加简单,开发人员开始使用其他团队的模块。 并创建和维护自己的。
另外,可以在这里使用所有与Maven配合使用的工具。 例如,使用IntelliJ IDEA生成的依赖关系图现在向我们展示了依赖关系交互的体系结构图:)
来自docker-compose的
投票应用程序示例的架构
同时,存在一些实现上的困难,例如,迫使所有团队使用Docker(dockerize)打包应用程序并将配置打包到单独的Maven模块中。 众所周知,从其他团队导入应用程序并支持复杂的开发环境变得更加容易。
大约一年前,我们开始朝这个方向努力,现在,我们已有大约200个模块用于开发和测试。 我们得出的结论是,该库对于在CI平台上管理用于端到端测试的临时环境也非常有用。
我们目前正在研究如何通过在Kubernetes中而不是docker-compose中启动容器来重用这项技术来管理UAT /集成环境,从而确保在更大的环境中滚动更新和计算弹性。
我希望您会高兴地知道我们的项目是在Apache 2.0许可下打开的,并且可以在Github上找到:
github.com/swissquote/carnotzet使用:)