Assemblage et dĂ©ploiement des mĂȘmes microservices avec werf et GitLab CI



Il y a deux ans, nous avons publiĂ© l’article « GĂ©nĂ©rer des projets avec GitLab CI: un .gitlab-ci.yml pour des centaines d’applications », et nous allons maintenant parler de la rĂ©solution d’un problĂšme similaire aujourd’hui. Le nouveau matĂ©riel concerne la façon dont vous pouvez crĂ©er des processus CI / CD pour un grand nombre d'applications similaires avec l'avĂšnement d' include dans .gitlab-ci.yml et l'avĂšnement de werf pour remplacer dapp.

Introduction


Dans les instructions supplémentaires données dans l'article, la situation suivante est prise en compte:

  • Il existe une grande application cliente, divisĂ©e en plusieurs rĂ©fĂ©rentiels.
  • Chaque rĂ©fĂ©rentiel est une application distincte qui doit ĂȘtre exĂ©cutĂ©e dans un cluster Kubernetes.
  • En tant que systĂšme CI, GitLab CI est utilisĂ©.
  • Le dĂ©ploiement (l'infrastructure dans laquelle le code est dĂ©ployĂ©) est dĂ©crit par les graphiques Helm.
  • CrĂ©ez des images et dĂ©ployez-les dans Kubernetes Ă  l'aide de werf .

Pour plus de simplicitĂ© et de commoditĂ© (et en hommage Ă  la mode), nous continuerons Ă  appeler ces applications des microservices. Tous ces microservices sont assemblĂ©s, dĂ©ployĂ©s et lancĂ©s de la mĂȘme maniĂšre , et des paramĂštres spĂ©cifiques sont configurĂ©s Ă  l'aide de variables d'environnement.

De toute Ă©vidence, la copie de .gitlab-ci.yml , werf.yaml et .helm beaucoup de problĂšmes. AprĂšs tout, toute modification dans CI, le processus d'assemblage ou la description du Helm-chart doit ĂȘtre ajoutĂ©e Ă  d'autres rĂ©fĂ©rentiels ...

Connexion de modĂšles dans .gitlab-ci.yml


Avec l'avĂšnement de la directive include:file dans GitLab CE ( depuis la version 11.7 ), il est devenu possible de crĂ©er un CI commun. include lui-mĂȘme est apparu un peu plus tĂŽt (en 11.4), mais il a permis de connecter des modĂšles uniquement Ă  partir d' URL publiques , ce qui a quelque peu limitĂ© sa fonctionnalitĂ©. La documentation de GitLab dĂ©crit parfaitement toutes les fonctionnalitĂ©s et exemples d'utilisation.

Ainsi, il a été possible de refuser de copier .gitlab-ci.yml entre les référentiels et de soutenir sa pertinence. Voici un exemple .gitlab-ci.yml avec 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 

Nous vous recommandons fortement d'utiliser les noms de branche en ref avec prudence . Les inclusions sont calculées au moment de la création du pipeline, de sorte que les modifications de votre CI peuvent automatiquement tomber dans le pipeline de production au moment le plus inopportun. Mais l' utilisation de balises dans ref facilite la version de la description des processus CI / CD. Lors de la mise à jour, tout semble aussi transparent que possible et vous pouvez facilement suivre l'historique des modifications dans les versions de pipeline si vous utilisez le contrÎle de version sémantique pour les balises.

Connectez .helm à partir d'un référentiel distinct


Étant donnĂ© que ces microservices sont dĂ©ployĂ©s et exĂ©cutĂ©s de la mĂȘme maniĂšre, le mĂȘme ensemble de modĂšles Helm est requis. Pour Ă©viter de copier le rĂ©pertoire .helm entre les rĂ©fĂ©rentiels, nous avons utilisĂ© pour cloner le rĂ©fĂ©rentiel dans lequel les modĂšles Helm Ă©taient stockĂ©s et vĂ©rifiĂ©s sur la balise souhaitĂ©e. Cela ressemblait Ă  ceci:

  - 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 

Il y avait aussi des variantes utilisant des sous-modules git, mais tout cela ressemble plus Ă  une solution de contournement ...

Et maintenant, avec la récente version de werf, il a la possibilité de connecter des graphiques à partir de référentiels externes. La prise en charge complÚte des fonctions du gestionnaire de packages a, à son tour, permis de décrire de maniÚre transparente les dépendances pour le déploiement de l'application.

SĂ©quence d'actions


Revenons à la résolution de notre problÚme avec les microservices. Augmentons notre référentiel pour stocker les graphiques Helm - par exemple, ChartMuseum . Il se déploie facilement sur un cluster Kubernetes:

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

Ajouter une entrée:

 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: {} 

Le dĂ©ploiement flant-chartmuseum doit remplacer la variable d'environnement DISABLE_API par false . Sinon (par dĂ©faut), les requĂȘtes de l'API ChartMuseum ne fonctionneront pas et il ne sera pas possible de crĂ©er de nouveaux graphiques.

Nous décrivons maintenant le référentiel dans lequel les graphiques Helm partagés seront stockés. La structure de ses répertoires est la suivante:

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

Chart.yaml pourrait ressembler Ă  ceci:

 name: yii2-microservice version: 1.0.4 

Le rĂ©pertoire des templates doit contenir toutes les primitives Kubernetes nĂ©cessaires qui seront nĂ©cessaires pour dĂ©ployer l'application sur le cluster. Comme vous l'avez peut-ĂȘtre dĂ©jĂ  devinĂ©, dans ce cas, le microservice est une application PHP basĂ©e sur le framework yii2. DĂ©crivons son dĂ©ploiement minimal avec deux conteneurs nginx et php-fpm qui sont construits Ă  l'aide de werf:

 --- 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 

La variable .Values.global.werf.name contient le nom du projet à partir du fichier werf.yaml , ce qui vous permet d'obtenir les noms de services et de déploiements nécessaires.

Faisons l'automatisation la plus simple pour pousser dans le ChartMuseum de nos graphiques lors de la validation dans la branche principale. Pour ce faire, nous décrivons .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 

Les graphiques sont versionnés en changeant la version dans Chart.yaml . Tous les nouveaux graphiques seront automatiquement ajoutés au ChartMuseum.

Nous allons à la ligne d'arrivée! Dans le référentiel du projet en .helm/requirements.yaml écrivons les dépendances du graphique:

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

... et exécutez dans le répertoire avec le référentiel:

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

Nous .helm/requirements.lock . Maintenant, pour déployer l'application sur le cluster, il suffit d'exécuter la werf helm dependency build avant d'exécuter werf deploy .

Pour mettre Ă  jour la description du dĂ©ploiement de l'application, vous devez maintenant parcourir les rĂ©fĂ©rentiels avec des microservices et appliquer de petits correctifs avec des modifications des hachages et des balises dans requirements.yaml et requirements.lock . Si vous le souhaitez, cette opĂ©ration peut Ă©galement ĂȘtre automatisĂ©e via CI: nous avons dĂ©jĂ  dĂ©crit comment procĂ©der dans l' article mentionnĂ© .

Conclusion


J'espĂšre que la sĂ©quence d'actions dĂ©crite pour l'entretien d'applications similaires sera utile aux ingĂ©nieurs confrontĂ©s Ă  des problĂšmes similaires. Et nous serons heureux de partager d'autres recettes pratiques pour utiliser werf . Par consĂ©quent, si vous rencontrez des difficultĂ©s qui semblent insurmontables ou simplement incomprĂ©hensibles Ă  mettre en Ɠuvre, n'hĂ©sitez pas Ă  contacter Telegram ou Ă  laisser des demandes de futurs documents ici dans les commentaires.

PS


Lisez aussi dans notre blog:

Source: https://habr.com/ru/post/fr469541/


All Articles