Niebieskie/zielone wdrożenie w portainer z wykorzystaniem gitlab CI/CD

0

Pytanie

Mam serwis internetowy, który korzysta z websockets, i muszę zrealizować wdrożenie z zerowym czasem oczekiwania. Ponieważ nie chcę usuwać istniejące połączenia podczas wdrażania, postanowiłem zrealizować wdrożenie niebieskiego/zielonego koloru. Moje rzeczywiste rozwiązanie wygląda tak:

  1. Stworzyłem dwie identyczne usługi w portainer, które wykrywają różne porty. Każda usługa ustaliła w środowiskach węzłów jakiś identyfikator, np. alfa i beta
  2. Obie usługi są ukryte za балансировщиком obciążenia, i oficjalne okresowo sprawdzić stan każdej usługi. Jeśli usługa odpowiada na określoną trasę (/biblioteka-sprawdzanie aktywności) ciąg "OK", ta usługa jest aktywna, a biblioteka może wykonać trasowanie do tej usługi. Jeśli usługa odpowiada ciąg znaków "STOP", biblioteka oznacza tę usługę jako niedostępnej, ale aktywne połączenia zostaną zapisane
  3. jaka usługa jest aktywna, a jaka jest zatrzymana, synchronizacja przez redis. W redis ma klucze lb.service.alfa i lb.service.beta który może zawierać wartości 1 do aktywnego i 0 dla nieaktywnych. Przykład realizacji /biblioteka-keepalive-sprawdzenie trasy w 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. w gitlab CI utwórz obraz docker oznaczone tagiem podczas zatwierdzenia, a następnie ponownie uruchom usługę, która wywołała webhook portainer dla danej usługi. To działa dobrze dla 1 usługi, ale nie wiem, jak korzystać z 2 różnych zmiennych CI DEPLOY_WEBHOOK i przełączać się między nimi.
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

Moje pytania, na które nie wiem jak rozwiązać, są to:

  • Gdy mam 2 usługi, mam 2 różne witryny wdrażania, z których muszę wywołać jeden po wdrożeniu, bo nie chcę ponownie uruchomić obie usługi. Jak ustalić, jaki dokładnie? Jak zrealizować jakiś licznik, jeśli to wdrożenie odnosi się do serwisu "alfa" lub "beta"? Czy muszę korzystać z api gitlab i aktualizować DEPLOY_WEBHOOK po każdym wdrażania? Czy muszę pozbyć się tej zmiennej gitlab CI/CD i użyć jakiegoś API w usługach, który poda mi adres URL-adres strony-haka?
  • Jak zaktualizować wartości w redis? Czy muszę zrealizować użytkownika API do tego?
  • Czy istnieje lepszy sposób aby to osiągnąć?

dodatkowe informacje: Nie mogę korzystać z api gitlab z usług, ponieważ nasz gitlab zamieszczona na domenie, dostępnym tylko z naszej sieci prywatnej.

1

Najlepsza odpowiedź

0

Zmieniłem swój AppController. Teraz są 2 nowe punkty końcowe, jedna dla określenia uruchomionej usługi, druga dla wartości przełącznika w 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');
            }
        })
    }

po tym zmieniłem swój gitlab-ci.yml w następujący sposób:

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

W złożeniu zadania tworzony jest obraz nudziarz z niego, co. Po tym uruchamia się wdrożenie zadania, które sprawia, że żądanie /running-service-id oraz określa, jaka usługa jest uruchomiona. Następnie rozwiń obraz zatrzymaną w służbie. Ostatni z nich-przełącznik zadań, który poprosi o /zmieniać trasę, która będzie zmieniać wartości w redis.

Działa to dobrze. Ostatnie, czego mi trzeba zrealizować, to jakiś sekret dla tych dwóch tras (np. jwt).

2021-12-02 07:39:41

W innych językach

Ta strona jest w innych językach

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