Bleu/vert déploiement de portainer à l'aide de gitlab CI/CD

0

La question

J'ai webservice utiliser les websockets, et de la nécessité de mettre en œuvre zéro temps d'arrêt de déploiement. Parce que je ne veux pas tomber les connexions existantes sur de déployer, j'ai décidé de mettre en œuvre le bleu/vert déployer. Ma solution réelle ressemble à:

  1. J'ai créé deux services identiques dans portainer, à l'écoute sur des ports différents. Chaque service a mis en nœud environnements d'identification, par exemple alfa et beta
  2. Les deux services sont cachés derrière d'équilibrage de la charge et de l'équilibreur est de vérifier périodiquement l'état de chaque service. Si le service répond sur itinéraire précis (/équilibreur-keepalive-case) avec de la ficelle "OK", ce service est actif et balancer peut routage à ce service. Si le service est de répondre avec de la ficelle "STOP", équilibrage de la marque de ce service comme inaccessible, mais les connexions actives seront préservés
  3. qui service est actif et qui est arrêté est synchronisé sur le redis. Dans le redis il y a des clefs lb.service.alfa et lb.service.beta qui peut contenir des valeurs de 1 pour actif et 0 pour les inactifs. Exemple de mise en œuvre /d'équilibrage-keepalive-vérifier route dans nestjs:
    import {Controller, Get} from '@nestjs/common';
    import {RedisClient} from "redis";
    const { promisify } = require("util");
    
    
    @Controller()
    export class AppController {
    
        private redisClient = new RedisClient({host: process.env.REDIS_HOST});
        private serviceId:string = process.env.ID;  //alfa, beta
    
        @Get('balancer-keepalive-check')
        async balancerCheckAlive(): Promise<string> {
            const getAsync = promisify(this.redisClient.get).bind(this.redisClient);
            return getAsync(`lb-status-${this.serviceId}`).then(status => {
                const reply: string = status == 1 ? 'OK' : 'STOP';
                return `<response>${reply}</response>`;
            })
        }
    }
  1. dans gitlab CI créer docker image marqués par le tag sur valider et redémarrer le service d'appel portainer webhook de service spécifiques. Cela fonctionne bien pour 1 service, mais ne savez pas comment l'utiliser 2 différents DEPLOY_WEBHOOK CI variables et basculer entre eux.
image: registry.rassk.work/pokec/pokec-nodejs-build-image:p1.0.1
services:
  - name: docker:dind

variables:
  DOCKER_TAG: platform-websocket:$CI_COMMIT_TAG

deploy:
  tags:
    - dtm-builder
  environment:
    name: $CI_COMMIT_TAG
  script:
    - npm set registry http://some-private-npm-registry-url.sk
    - if [ "$ENV_CONFIG" ]; then cp $ENV_CONFIG $PWD/.env; fi
    - if [ "$PRIVATE_KEY" ]; then cp $PRIVATE_KEY $PWD/privateKey.pem; fi
    - if [ "$PUBLIC_KEY" ]; then cp $PUBLIC_KEY $PWD/publicKey.pem; fi
    - docker build -t $DOCKER_TAG .
    - docker tag $DOCKER_TAG registry.rassk.work/community/$DOCKER_TAG
    - docker push registry.rassk.work/community/$DOCKER_TAG
    - curl --request POST $DEPLOY_WEBHOOK
  only:
    - tags

Mes questions, que je ne sais pas comment le résoudre:

  • Quand j'ai les 2, j'ai 2 différents déployer webhooks à partir de laquelle j'ai besoin d'appeler une après déployer, parce que je ne veux pas redémarrer les services. Comment faire pour déterminer lequel? Comment mettre en œuvre une sorte de comptoir, si cette déployer est à "alfa" ou "beta" de service? Dois-je utiliser gitlab de l'api et de la mise à jour DEPLOY_WEBHOOK après chaque déploiement? Ou doit-je me débarrasser de cette gitlab CI/CD variable et utiliser certaines API sur les services qui me dira webhook url?
  • Comment mettre à jour les valeurs dans le redis? Dois-je mettre en œuvre des API pour cela?
  • Existe il une meilleure façon de réaliser cet objectif?

plus d'info: ne pas utiliser gitlab api de serviceses, parce que notre gitlab est auto-hébergé sur le domaine accessible qu'à partir de notre réseau privé.

1

La meilleure réponse

0

J'ai modifié mon AppController. Il y a 2 nouveaux points de terminaison maintenant, un pour identifier le service est en cours d'exécution, le second pour la valeur du commutateur dans le redis:

private serviceId:string = process.env.ID || 'alfa';

    @Get('running-service-id')
    info(){
        return this.serviceId
    }

    @Get('switch')
    switch(){
        const play = this.serviceId == 'alfa' ? `lb-status-beta` : `lb-status-alfa`;
        const stop = `lb-status-${this.serviceId}`;
        this.redisClient.set(play, '1', (err) => {
            if(!err){
                this.redisClient.set(stop, '0');
            }
        })
    }

après cela, j'ai modifié mon gitlab-ci.yml comme suit:

image: registry.rassk.work/pokec/pokec-nodejs-build-image:p1.0.1
services:
  - name: docker:dind

stages:
  - build
  - deploy
  - switch

variables:
  DOCKER_TAG: platform-websocket:$CI_COMMIT_TAG

test:
  stage: build
  allow_failure: true
  tags:
    - dtm-builder
  script:
    - npm set registry http://some-private-npm-registry-url.sk
    - npm install
    - npm run test

build:
  stage: build
  tags:
    - dtm-builder
  environment:
    name: $CI_COMMIT_TAG
  script:
    - if [ "$ENV_CONFIG" ]; then cp $ENV_CONFIG $PWD/.env; fi
    - if [ "$PRIVATE_KEY" ]; then cp $PRIVATE_KEY $PWD/privateKey.pem; fi
    - if [ "$PUBLIC_KEY" ]; then cp $PUBLIC_KEY $PWD/publicKey.pem; fi
    - docker build -t $DOCKER_TAG .
    - docker tag $DOCKER_TAG registry.rassk.work/community/$DOCKER_TAG
    - docker push registry.rassk.work/community/$DOCKER_TAG
  only:
    - tags

deploy:
  stage: deploy
  needs: [build, test]
  environment:
    name: $CI_COMMIT_TAG
  script:
    - 'SERVICE_RUNNING=$(curl --request GET http://172.17.101.125/running-service-id)'
    - echo $SERVICE_RUNNING
    - if [ "$SERVICE_RUNNING" == "1" ]; then curl --request POST $DEPLOY_WEBHOOK_2; fi
    - if [ "$SERVICE_RUNNING" == "2" ]; then curl --request POST $DEPLOY_WEBHOOK_1; fi
  only:
    - tags

switch:
  stage: switch
  needs: [deploy]
  environment:
    name: $CI_COMMIT_TAG
  script:
    - sleep 10
    - curl --request GET http://172.17.101.125/switch
  only:
    - tags

Dans la tâche de construire le support de l'image est à construire. Après que les pistes de travail déployer, ce qui en fait la demande à /en cours d'exécution-service-id et identifie, dont le service est en cours d'exécution. Puis déployez l'image de l'arrêté du service. La dernière est emploi de l'interrupteur, ce qui permettra de faire une demande pour /commutateur de route, qui change les valeurs dans le redis.

Cela fonctionne bien. La dernière chose dont j'ai besoin pour mettre en œuvre est une sorte de secret pour cette deux voies (jwt par exemple)

2021-12-02 07:39:41

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................