开发团队的测试服务器

哈Ha! 在本文中,我想分享为开发团队部署测试服务器的经验。 简而言之,问题的实质-有一个开发团队和一些php项目。 尽管我们很少,而项目实际上是一个项目,但是我们使用了1个测试服务器,并向客户展示任务,因此开发人员将服务器“列为”一定时间。 如果没有及时的“窗口”,那么我们必须等待。 随着时间的推移,团队和任务的复杂性分别增加,验证时间和测试服务器的繁忙度增加,这对交付时间和奖金产生了负面影响。 因此,我不得不寻找解决方案,而且已经被削减了。

介绍性


什么是:

  1. 一台测试服务器
  2. Gitlab和Redmine在另一台服务器上
  3. 渴望解决问题

所有服务器都在我们的本地网络中,无法从外部访问测试服务器。

需要什么:

  1. 能够同时测试多个项目/分支
  2. 开发人员可以转到服务器上进行设置,而不破坏其他任何东西
  3. 一切都应该尽可能地方便,并在一个按钮上完成,最好从gitlab(CI / CD)开始。

决策选项


1.一台服务器,多台主机


最简单的选择。 我们使用同一台测试服务器,只有开发人员需要为每个分支/项目创建一个主机,并将其添加到nginx / apache2配置中。

优点:

  1. 很快,每个人都明白
  2. 可以自动化

缺点:

  1. 要求的第2条未得到满足-开发人员可以开始更新数据库,并且在某些情况下,可以将所有内容都放入其中(嗨,安德烈!)
  2. 带有大量配置文件的非常复杂的自动化

2.给服务器上的每个开发人员!


分配给每个服务器,开发人员应对其经济负责。

优点:

  1. 开发人员可以为您的项目完全自定义服务器

缺点:

  1. 要求的第2条未得到满足
  2. 昂贵的资源只会在开发过程中闲置,而不是进行测试
  3. 由于服务器不同,自动化程度比第1点还要复杂

3.容器化-docker,kubernetes


这项技术越来越渗透到我们的生活中。 在家里,我已经为项目使用docker很长时间了。
Docker-用于在操作系统级别自动化虚拟化环境中应用程序的部署和管理的软件。 允许您将应用程序及其所有周围环境和依赖项“打包”到一个容器中,该容器可以移植到内核中具有cgroups支持的任何Linux系统,并且还提供了一个容器管理环境。
优点:

  1. 使用一台服务器
  2. 满足所有要求。

缺点:

  1. 图像和容器有时会占用大量空间,您必须清洁已经过时的表冠以释放空间。

Docker实施


当使用gitlab,AutoDevOps时,kubernetes设置经常引起我的注意。 另外,参加各种聚会的有胡子的人告诉他们与kubernetes一起工作有多酷。 因此,决定尝试在群集中的设备上部署群集,服务器被请求(您不能触摸测试者,有人正在那里进行测试),它就开始了!

由于我有使用kubernetes 0的经验,因此按照手册进行了所有操作,试图了解所有这些集群的工作方式。 一段时间后,我设法提升了群集,但是随后出现了证书,密钥以及部署困难的问题。 我需要一个更简单的解决方案来教我的同事如何使用它(例如,我不想坐在Skype上度过同一个假期并进行设置)。 因此,kubernetes被独自留下。 Docker本身仍然存在,因此有必要找到一种用于容器路由的解决方案。 由于可以在不同的端口上拾取它们,因此可以将相同的nginx用于内部重定向。 这称为反向代理服务器。
反向代理服务器是一种代理服务器,可以将来自外部网络的客户端请求中继到逻辑上位于内部网络上的一个或多个服务器。 同时,它看起来像客户端一样,所请求的资源直接位于代理服务器上。

反向代理


为了不浪费时间,我开始寻找现成的解决方案。 发现了-这是traefik

Træfik是现代的HTTP反向代理和负载平衡器,可简化微服务的部署。 Træfik与现有的基础架构组件(Docker,Swarm模式,Kubernetes,Marathon,Consul,Etcd,Rancher,Amazon ECS等)集成,并且自动且动态地配置。 要使用docker,您只需要指定它的套接字即可,然后Træfik本身会找到所有容器并路由到它们(有关更多详细信息,请参阅“在docker中打包应用程序”)。

Træfik容器配置
我通过docker-compose.yml启动它

version: '3' services: traefik: image: traefik:latest # The official Traefik docker image command: --api --docker # Enables the web UI and tells Træfik to listen to docker ports: - 443:443 - 80:80 # The HTTP port - 8080:8080 # The Web UI (enabled by --api) volumes: - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events - /opt/traefik/traefik.toml:/traefik.toml - /opt/traefik/certs/:/certs/ networks: - proxy container_name: traefik restart: always networks: proxy: external: true 


在这里,我们告知代理,我们需要侦听端口80,443和8080(代理的Web界面),安装Docker套接字,配置文件和证书文件夹。 为了方便命名测试站点,我们决定创建一个本地域区域* .test。 访问该站点上的任何站点时,用户都将进入我们的测试服务器。 因此,traefik文件夹中的证书是自签名的,但它支持“加密”。

证书生成

 openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout domain.key -out domain.crt 

在开始之前,您需要在docker中创建一个代理网络(您可以自己命名)。

 docker network create proxy 

这将是用于将traefik与php网站容器连接的网络。 因此,通过在参数external:true中指定,可以在服务的网络参数中以及整个文件的网络中指定它。

Traefik.toml文件
 debug = false logLevel = "DEBUG" defaultEntryPoints = ["https","http"] #  insecureSkipVerify = true #   [entryPoints] [entryPoints.http] address = ":80" [entryPoints.https] address = ":443" [entryPoints.https.tls] [docker] endpoint = "unix:///var/run/docker.sock" domain = "docker.localhost" watch = true exposedbydefault = false 


这里的一切都非常简单-我们指定http和https流量的入口点,如果证书是本地的,请不要忘记设置insecureSkipVerify = true。 在entryPoints.https.tls部分中,您无法指定证书,然后traefik将替换其证书。

您可以启动服务

 docker-compose up -d 

如果您访问site.test ,则将收到404错误,因为此域未绑定到任何容器。

我们将应用程序打包在Docker中


现在,您需要使用应用程序配置容器,即:

1.在网络中指定代理网络
2.添加带有traefik配置的标签

以下是应用程序之一的配置

docker-compose.yml应用程序
 version: '3' services: app: build: data/docker/php #   restart: always working_dir: /var/www/html/public volumes: - ./:/var/www/html #    - /home/develop/site-files/f:/var/www/html/public/f #       links: - mailcatcher - memcached - mysql labels: - traefik.enabled=true - traefik.frontend.rule=Host:TEST_DOMAIN,crm.TEST_DOMAIN,bonus.TEST_DOMAIN - traefik.docker.network=proxy - traefik.port=443 - traefik.protocol=https networks: - proxy - default mailcatcher: image: schickling/mailcatcher:latest restart: always memcached: image: memcached restart: always mysql: image: mysql:5.7 restart: always command: --max_allowed_packet=902505856 --sql-mode="" environment: MYSQL_ROOT_PASSWORD: 12345 MYSQL_DATABASE: site volumes: - ./data/cache/mysql-db:/var/lib/mysql #      phpmyadmin: image: phpmyadmin/phpmyadmin restart: always links: - mysql environment: MYSQL_USERNAME: root MYSQL_ROOT_PASSWORD: 12345 PMA_ARBITRARY: 1 PMA_HOST: mysql_1 labels: - traefik.enabled=true - traefik.frontend.rule=Host:pma.TEST_DOMAIN - traefik.docker.network=proxy - traefik.port=80 - traefik.default.protocol=http networks: - proxy - default networks: proxy: external: true 


在应用程序服务的“网络”部分,您需要指定代理服务器和默认代理,这意味着它将在两个网络中可用,从配置中可以看出,我不转发外部端口,一切都在网络上进行。

接下来,配置标签

  - traefik.enabled=true # traefik    - traefik.frontend.rule=Host:TEST_DOMAIN,crm.TEST_DOMAIN,bonus.TEST_DOMAIN #    traefik     - traefik.docker.network=proxy #   - traefik.port=443 #,     ssl   80   http - traefik.protocol=https #  #  phpmyadmin   http  

在常规网络部分,指定外部:true

TEST_DOMAIN常量必须替换为域,例如site.test

启动应用程序

 docker-compose up -d 

现在,如果您转到域site.test,crm.site.test,bonus.site.test,则可以看到工作站点。 在pma.site.test域上,将使用phpmyadmin来方便地使用数据库。

配置GitLab


我们创建一个任务处理程序,为此我们运行

 gitlab-runner register 

我们指定gitlab网址,令牌以及执行任务的执行者(执行者)。 由于我的测试和gitlab在不同的服务器上,因此我选择ssh executor。 您需要指定通过ssh连接的服务器地址和登录名/密码。

Runner可以附加到一个或多个项目。 由于我的工作逻辑在所有地方都是相同的,因此创建了一个共享运行器(所有项目都通用)。
最后一点是创建CI配置文件

.gitlab-ci.yml
 stages: - build - clear #  develop build_develop: stage: build #   build tags: #     - ssh-develop environment: # ,       -   name: review/$CI_BUILD_REF_NAME #  url: https://site$CI_PIPELINE_ID.test #url     on_stop: clear when: manual script: - cd ../ && cp -r $CI_PROJECT_NAME $CI_PIPELINE_ID && cd $CI_PIPELINE_ID #     - cp -r /home/develop/site-files/.ssh data/docker/php/.ssh #  ssh - sed -i -e "s/TEST_DOMAIN/site$CI_PIPELINE_ID.test/g" docker-compose.yml #   - docker-compose down #   - docker-compose up -d --build #  - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar install --prefer-dist \"" #   - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar first-install $CI_PIPELINE_ID\"" #     #  production build_prod: stage: build tags: - ssh-develop environment: name: review/$CI_BUILD_REF_NAME url: https://site$CI_PIPELINE_ID.test on_stop: clear when: manual script: - cd ../ && cp -r $CI_PROJECT_NAME $CI_PIPELINE_ID && cd $CI_PIPELINE_ID - cp -r /home/develop/site-files/.ssh data/docker/php/.ssh #  ssh - docker-compose down - docker-compose up -d --build - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar install --prefer-dist --no-dev\"" - script -q -c "docker exec -it ${CI_PIPELINE_ID}_app_1 bash -c \"cd ../ && php composer.phar first-install $CI_PIPELINE_ID\"" clear: stage: clear tags: - ssh-develop environment: name: review/$CI_BUILD_REF_NAME action: stop script: - cd ../ && cd $CI_PIPELINE_ID && docker-compose down && cd ../ && echo password | sudo -S rm -rf $CI_PIPELINE_ID #       when: manual 


在此配置中,描述了两个阶段-构建和清除。 构建阶段有2个选项-build_develop和build_prod



Gitlab建立了一个易于理解的流程图。 在我的示例中,所有进程都是手动启动的(当:manual参数时)。 这样做是为了使开发人员在部署测试站点之后,可以将其编辑内容拖入容器中,而无需重建整个容器。 另一个原因是域名-站点$ CI_PIPELINE_ID.test,其中CI_PIPELINE_ID是启动程序集的进程号。 也就是说,他们使用域site123.test提交了站点以进行验证,并且为了进行热编辑,开发人员会立即将所做的更改倒入容器中。

ssh执行程序的一个小功能。 连接到服务器后,将创建一个表单文件夹。

 /home//builds/_runner/0/_/_ 

因此,添加了一行

 cd ../ && cp -r $CI_PROJECT_NAME $CI_PIPELINE_ID && cd $CI_PIPELINE_ID 

在其中,我们转到上面的文件夹,然后将项目复制到带有进程号的文件夹中。 因此,您可以部署一个项目的多个分支。 但是在处理程序的设置中,需要选中“锁定到当前项目”,因此处理程序将不会尝试同时扩展多个分支。

清除阶段将停止容器并删除文件夹,您可能需要root特权,因此我们使用echo密码|。 sudo -S rm其中password是您的密码。

垃圾收集


您不时需要删除未使用的容器,以免占用空间,为此,带有此类内容的脚本会挂在顶部

 #!/bin/bash #   : docker ps --filter status=dead --filter status=exited -aq | xargs -r docker rm -v #   : yes | docker container prune #    : yes | docker image prune #    : yes | docker volume prune 

每天执行一次。

结论


该解决方案帮助我们极大地优化了测试和新功能的发布。 准备回答问题,接受建设性的批评。

红利


为了不每次都从Dockerfile收集图像,您可以将它们存储在本地Docker注册表中。

文件docker-compose.yml
 registry: restart: always image: registry:2 ports: - 5000:5000 volumes: - /opt/docker-registry/data:/var/lib/registry #     


此选项不使用身份验证,这不是安全的方法(!!!),但适用于存储非关键图像。

您可以配置gitlab以查看

  gitlab_rails['registry_enabled'] = true gitlab_rails['registry_host'] = "registry.test" gitlab_rails['registry_port'] = "5000" 

之后,图像列表出现在gitlab中

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


All Articles