使用werf和GitLab CI组装和部署相同的微服务



两年前,我们发表了文章“ 使用GitLab CI构建项目:一个用于数百个应用程序的.gitlab-ci.yml ”,现在,我们今天将讨论解决类似的问题。 新材料介绍了如何在.gitlab-ci.ymlinclude .gitlab-ci.yml以及用werf替代dapp的出现来为大量类似的应用程序构建CI / CD流程。

介绍性


在本文给出的进一步说明中,考虑了以下情况:

  • 有一个大型的客户端应用程序,它分为许多存储库。
  • 每个存储库都是一个单独的应用程序,必须在Kubernetes集群中运行。
  • 作为CI系统,使用了GitLab CI。
  • 部署(将代码部署到的基础结构)由Helm图表描述。
  • 使用werf构建映像并在Kubernetes中进行部署

为了简单和方便(并向时尚致敬),我们将继续称这些应用程序为微服务。 所有这些微服务都以相同的方式组装,部署和启动 ,并且使用环境变量配置特定的设置。

显然,复制.gitlab-ci.ymlwerf.yaml.helm会带来很多问题。 毕竟,对CI的任何编辑,组装过程或Helm-chart的描述都应添加到其他存储库中...

连接.gitlab-ci.yml中的模板


随着GitLab CE中的include:file指令( 自11.7版开始 )问世,制作一个通用CI成为可能。 include本身出现得更早(在11.4中),但是它只允许通过公共 URL连接模板,这在某种程度上限制了其功能。 GitLab文档完美描述了所有功能和用法示例。

因此,可以拒绝在存储库之间复制.gitlab-ci.yml并支持其相关性。 这是一个.gitlab-ci.yml示例,其中include

 include: - project: 'infra/gitlab-ci' ref: 1.0.0 file: base-gitlab-ci.yaml - project: 'infra/gitlab-ci' ref: 1.0.0 file: cleanup.yaml 

我们强烈建议您谨慎使用ref分支名称。 Include是在创建管道时计算的,因此您的配置项更改可能在最不适当的时刻自动落入生产管道。 但是, ref使用标记可以轻松地对CI / CD流程的描述进行版本控制。 更新时,所有内容看起来都尽可能透明,并且如果对标记使用语义版本控制,则可以轻松跟踪管道版本的更改历史记录。

从单独的存储库连接.helm


由于这些微服务的部署和运行方式相同,因此需要相同的Helm模板集。 为了避免在存储库之间复制.helm目录,我们使用了克隆存储Helm模板的存储库并检查所需标签的方法。 它看起来像这样:

  - git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/infra/helm.git .helm - cd .helm && git checkout tags/1.0.0 - type multiwerf && source <(multiwerf use 1.0 beta) - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose) - werf deploy --stages-storage :local 

使用git子模块也有一些变化,但似乎更像是一种解决方法...

现在有了最新的werf版本,他就有机会连接来自外部存储库的图表。 完全支持程序包管理器的功能,从而使我们能够透明地描述应用程序部署的依赖关系。

行动顺序


让我们回到解决微服务问题的角度。 让我们提高用于存储Helm图表的存储库-例如ChartMuseum 。 它可以轻松地部署到Kubernetes集群:

 helm repo add stable https://kubernetes-charts.storage.googleapis.com helm install stable/chartmuseum --name flant-chartmuseum 

添加入口:

 apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/force-ssl-redirect: "false" nginx.ingress.kubernetes.io/proxy-body-size: 10m nginx.ingress.kubernetes.io/ssl-redirect: "false" name: chart-museum spec: rules: - host: flant-chartmuseum.example.net http: paths: - backend: serviceName: flant-chartmuseum servicePort: 8080 path: / status: loadBalancer: {} 

部署flant-chartmuseum需要将环境变量DISABLE_API更改为false 。 否则(默认情况下),ChartMuseum API请求将不起作用,并且将无法创建新图表。

现在,我们描述将存储共享Helm图表的存储库。 其目录的结构如下:

 . ├── charts │ └── yii2-microservice │ ├── Chart.yaml │ └── templates │ ├── app.yaml └── README.md 

Chart.yaml可能看起来像这样:

 name: yii2-microservice version: 1.0.4 

templates目录应包含将应用程序部署到集群所需的所有必要的Kubernetes原语。 您可能已经猜到了,在这种情况下,微服务是基于yii2框架的PHP应用程序。 让我们用两个使用werf构建的nginx和php-fpm容器描述其最小部署:

 --- apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Values.global.werf.name }} spec: replicas: 1 revisionHistoryLimit: 3 template: metadata: labels: service: {{ .Values.global.werf.name }} spec: imagePullSecrets: - name: registrysecret containers: - name: backend {{ tuple "backend" . | include "werf_container_image" | indent 8 }} command: [ '/usr/sbin/php-fpm7', "-F" ] ports: - containerPort: 9000 protocol: TCP name: http env: {{ tuple "backend" . | include "werf_container_env" | indent 8 }} - name: frontend command: ['/usr/sbin/nginx'] {{ tuple "frontend" . | include "werf_container_image" | indent 8 }} ports: - containerPort: 80 name: http lifecycle: preStop: exec: command: ["/usr/sbin/nginx", "-s", "quit"] env: {{ tuple "frontend" . | include "werf_container_env" | indent 8 }} --- apiVersion: v1 kind: Service metadata: name: {{ .Values.global.werf.name }} spec: selector: service: {{ .Values.global.werf.name }} ports: - name: http port: 80 protocol: TCP 

变量.Values.global.werf.name包含werf.yaml文件中项目的名称,该文件使您可以获取服务和部署的必要名称。

在提交到master分支时,让我们最简单的自动化操作来推送图表的ChartMuseum。 为此,我们描述.gitlab-ci.yml

 Build and push to chartmuseum: script: - for i in $(ls charts); do helm package "charts/$i"; done; - for i in $(find . -type f -name "*.tgz" -printf "%f\n"); do curl --data-binary "@$i" http://flant-chartmuseum.example.net/api/charts; done; stage: build environment: name: infra only: - master tags: - my-shell-runner-tag 

通过更改Chart.yaml中的版本来对图表进行版本控制。 所有新图表将自动添加到ChartMuseum。

我们去终点线! 在.helm/requirements.yaml的项目存储库中.helm/requirements.yaml为图表编写依赖项:

 dependencies: - name: yii2-microservice version: "1.0.4" repository: "@flant" 

...并在包含存储库的目录中执行:

 werf helm repo init werf helm repo add flant http://flant-chartmuseum.example.net werf helm dependency update 

我们.helm/requirements.lock 。 现在,要将应用程序部署到集群,在运行werf deploy之前运行werf deploy werf helm dependency buildwerf deploy

要更新应用程序部署的描述,您现在需要遍历带有微服务的存储库,并应用一些具有补丁的小补丁程序,这些补丁会更改Requirements.yaml和requirements.yaml的哈希值和标记。 如果需要,也可以通过CI自动执行此操作:我们已经在上述文章中介绍了如何执行此操作。

结论


我希望所描述的为类似应用程序提供服务的操作顺序将对面临类似问题的工程师有用。 我们很乐意分享使用werf的其他实用秘诀。 因此,如果您遇到难以克服或难以理解的困难,请随时与Telegram联系或在评论中保留对将来材料的要求。

聚苯乙烯


另请参阅我们的博客:

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


All Articles