微服务。 使用TFS在持续集成和部署系统CI / CD中进行版本控制的案例研究

发行


对于大型技术复杂的项目(通常,许多分布式团队同时工作),存在一个众所周知的版本软件开发问题,不同公司对此有不同的解决方案。

当前,我们的许多客户和合作伙伴通过安装其软件的最新/最新版本来手动将最新版本(CI / CD)交付到生产环境,并已在其他环境中进行了测试。 例如,如果我们要谈论客户端软件,则提供iOS,Android等应用程序的构建,或者如果我们谈论后端,则通过在docker环境中更新docker-images。 对于大型且重要的项目,由项目经理决定每次在生产中发布新版本,这样的决定是合理的,而且成本也不高,尤其是在发行版本不经常发布的情况下。 但是,对于测试开发环境(Dev / Stage环境),“手动”工具的使用会导致项目的复杂性,对客户的印象可能受到干扰等。 造成这种情况的原因可能很多,包括中间件软件上各种容器的版本不一致或缺少详细的发行历史。

我们必须亲自确保这一点,并在一个大型项目中遇到很多困难,在该项目中,每天发布CI系统中后端的6-8个新软件版本和2-3个前端系统的2-3个软件版本,测试工程师无法客观地应对负载和人们一直缺乏对当前前端/后端软件哪个版本稳定的理解。

我们的经验


我们公司在其工作中使用各种CI / CD系统,通常根据客户的要求来选择。 例如,我们的专家经常会遇到诸如Jenkins,TeamCity,Travis CI,Circle CI,Gitlab CI,Atlassian Bamboo等CI / CD系统,有时我们会完全在客户的基础架构上工作。 因此,使用这种方法,版本控制解决方案的问题完全在客户身上。

在为客户开发解决方案时,当我们有机会在自己的基础架构上进行此操作时,我们使用TFS版本2018作为持续集成/持续交付系统的基础,这使我们能够解决创建完整软件开发周期的主要任务,即:

  • 基于当前项目中使用的软件开发方法的任务说明(问题,错误,任务);
  • 存储项目源代码;
  • 部署用于不同操作系统(Windows,Linux,MacOS)的程序集的构建代理的基础结构;
  • 以“手动”模式和CI组装项目;
  • 以“手动”模式和CD部署项目;
  • 测试项目;
  • 形成有关员工在项目上花费的时间的数据,以及我们使用自己设计的TFS扩展和通过向WIT添加静态信息实现的许多其他功能(在这种形式下,TFS取代了我们的Redmine公司,并简化了项目背景下的统计信息,报告等的收集) )

在这种情况下,将解决版本问题的解决方案分配给TFS,最终为我们的任务和客户的愿望确定TFS功能是合乎逻辑的。 结果,TFS工具通过定制各种构建脚本和组织测试/发布环境,解决了为微服务体系结构项目构建版本控制系统的任务。

解决方案:使用TFS和第三方工具


因此,我们需要一个用于微服务体系结构项目的版本控制系统来组织测试环境和发布。

作为初始数据,我们有:

  • 编排-我们主要使用docker swarm来减少对其他第三方工具的使用。 同时,有用于转换配置的转换器-例如, Kompose实用程序,如果需要的话,它将允许您使用Kubernetes。
  • 构建代理-基于Linux服务器的VM。
  • 源存储库-基于TFS的Git。
  • 图像存储-VM上的Docker注册表

关于构建名称的问题


  • 使用现有的命名标准(例如, 语义版本规范)将是合乎逻辑的。
  • 在手动开始发行版本的构建过程时,我们会使用该名称,因为否则您将无法自动获得正确的名称(除非您手动将其输入代码中,这与CI意识形态几乎没有关系)。
  • 在用于“调试”软件版本的CI模式下,我们在不同项目中使用以下名称:

    1. 内置TFS扩展
    2. 根据当前日期和当天的内部编号进行编号;
    3. 开始构建的提交数。

例如,可以使用以Javascript编写的Calculator服务示例以及一些公开可用的项目,查看特定的解决方案。

决策算法


1.在TFS2018中,创建一个名为SibEDGE Semver的项目,然后将存储库导入本地存储库

图片
图1-TFS 2018存储库中的SibEDGE Semver项目

2.创建一个带有满足我们需求的程序集node.js的描述的Dockerfile文件( link )。

FROM node:7 WORKDIR /usr/src/app COPY package.json app.js LICENSE /usr/src/app/ COPY lib /usr/src/app/lib/ LABEL license MIT COPY tests tests ENV NODE_ENV dev RUN npm config set strict-ssl false RUN npm update && \ npm install -g mocha CMD ["mocha", "tests/test.js", "--reporter", "spec"] 

脚本1-用于构建构建的Dockerfile


3.在我们计划部署环境的测试台上(安装了docker),创建一个群集集群。 在我们的情况下,它将由一台服务器组成。

 $ docker swarm init 

4.创建一个具有微服务描述的yml文件,以满足我们的需求( link )。
请注意, vm-docker-registry.development.com:5000是该项目的内部存储库,我们已经预先准备了该存储库。 为了使测试台能够使用此存储库,必须在/etc/docker/certs.d/ <存储库名称> /ca.crt文件夹中的测试台上注册ssl证书。

 version: '3.6' services: #--- # Portainer for manage Docker #--- portainer: image: portainer/portainer:1.15.3 command: --templates http://templates/templates.json -d /data -H unix:///var/run/docker.sock networks: - semver-network ports: - 9000:9000 volumes: - /var/run/docker.sock:/var/run/docker.sock #--- #----Service Calculator Test# #--- semver-calc: image: vm-docker-registry.development.com:5000/calculator:latest networks: - semver-network #--- #----Pminder - Nginx# #--- nginx: image: nginx:1.9.6 depends_on: - mysql ports: - "8888:80" - "6443:443" networks: - semver-network # #----------------------------- # START NoSQL - Redis. #--- redis: image: redis:4.0 networks: - semver-network ports: - "8379:6379" # # END NoSQL - Redis. #--- #----Pminder - DB# #--- mysql: image: mysql:5.7 ports: - "3306:3306" environment: MYSQL_ROOT_PASSWORD: 'ODdsX0xcN5A9a6q' MYSQL_DATABASE: 'semver' MYSQL_USER: 'user' MYSQL_PASSWORD: 'uXcgTQS8XUm1RzR' networks: - semver-network #--- #----PhpMyAdmin # #--- phpmyadmin: image: phpmyadmin/phpmyadmin depends_on: - mysql environment: PMA_HOST: 'mysql' PMA_USER: 'user' PMA_PASSWORD: 'uXcgTQS8XUm1RzR' ports: - "8500:80" - "8600:9000" networks: - semver-network #--- networks: semver-network: 

脚本2是semver.yml文件的内容,该文件是docker-compose项目文件。


5.在TFS2018(内部定义)中创建内部描述。

6.我们脚本的第一个动作是构建docker容器镜像:

图片
图2-在TFS 2018中为我们的构建构建映像

7.将在构建机器上创建的docker容器映像发送到该项目的内部存储库:

图片
图3-在TFS 2018存储库中为我们的程序集保存docker-image

8.对于微服务描述文件中测试平台上的整个环境,将映像名称更改为新名称:

图片
图4-在TFS 2018中为我们的构建替换构建脚本中的映像名称

9.在测试台上,从内部存储库复制创建的docker容器映像,并在docker swarm中更新服务:

图片
图5-使用TFS 2018中的映像为我们的构建使用构建脚本部署Docker容器

结果,当我们退出TFS存储库时,我们有一个yml文件,其中包含docker映像的发行版,而该映像又具有整个项目的发行版名称。

10.我们将转到测试台并检查服务,并确保计算器服务已更新并使用了新版本的程序集。

 $ docker service ls 


图片
图6-更新计算器服务并在我们的测试平台上检查其当前版本

因此,在我们的Docker注册表映像存储中,我们拥有一组各种版本的微服务的映像(在这种情况下,仅更改了一个微服务的版本)。 通过启动单独的部署过程(通过更改yml描述文件的脚本),您可以随时获取在测试平台上进行测试所需的环境,并将此配置转移到QA部门。 经过测试(回归,负载等),我们得到的信息是,某个版本的微服务与该版本的其他微服务的发行版在该测试台上可以稳定运行,并且最终决定是否要更新将支架释放到新版本。

摘要-您在出口处得到的东西


由于在具有微服务架构的项目中实施了版本控制,因此获得了以下结果:

  • 版本中的混乱数量有所减少;
  • 在项目中部署新环境的速度有所提高;
  • 组件的质量得到了改善,错误的程度有所降低;
  • 增加项目经理和客户的开发透明度;
  • 部门之间的互动得到改善;
  • DevOps的工作有新的方向。

PS感谢我的同事Kirill B.帮助我写这篇文章。

Source: https://habr.com/ru/post/zh-CN437992/


All Articles