【发布时间】:2022-01-01 17:54:59
【问题描述】:
我有使用 websockets 的 webservice,需要实现零停机部署。因为我不想在部署时删除现有连接,所以我决定实施蓝/绿部署。我的实际解决方案如下:
- 我在 portainer 中创建了两个相同的服务,监听不同的端口。每个服务都在节点环境中设置了一些标识符,例如
alfa和beta - 这两个服务都隐藏在负载均衡器后面,并且均衡器会定期检查每个服务的状态。如果服务在特定路由(/balancer-keepalive-check)上响应字符串“OK”,则该服务处于活动状态,并且平衡器可以路由到该服务。如果服务响应字符串“STOP”,平衡器将此服务标记为不可访问,但将保留活动连接
- 哪个服务处于活动状态,哪个服务已停止通过 redis 同步。在 redis 中有键
lb.service.alfa和lb.service.beta可以包含值 1 表示活动和 0 表示非活动。 Nestjs中实现/balancer-keepalive-check路由的例子:
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>`;
})
}
}
- 在 gitlab CI 中,在提交时创建按标签标记的 docker 映像,并重新启动服务调用 portainer webhook 以获取特定服务。这适用于 1 个服务,但不知道如何使用 2 个不同的 DEPLOY_WEBHOOK CI 变量并在它们之间切换。
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
我不知道如何解决的问题是:
- 当我有 2 个服务时,我有 2 个不同的部署 webhook,我需要在部署后调用其中一个,因为我不想重新启动这两个服务。如何确定是哪一个?如果此部署是针对“alfa”或“beta”服务,如何实现某种计数器?每次部署后我应该使用gitlab api and updateDEPLOY_WEBHOOK 吗?或者我应该摆脱这个 gitlab CI/CD 变量并在服务上使用一些 API 来告诉我 webhook url?
- 如何更新redis中的值?我应该为此实现自定义 API 吗?
- 是否有更好的方法来实现这一目标?
附加信息:无法使用服务中的 gitlab api,因为我们的 gitlab 是自托管在只能从我们的专用网络访问的域上。
【问题讨论】:
-
1.阅读负载均衡器,无需发明轮子。 2.如果您坚持自己实施,例如因为只有你有一个遗留系统,其中只允许 1 个实例处于活动状态,最好在 Redis 中保存一个处于活动状态的值而不是多个标志,以减少竞争条件并使用键上的 TTL 来确保一个已启动例如implementation here
-
这与负载平衡器无关。这部分我有工作。试着再读一遍我的问题。这是关于从gitlab CI/CD部署后如何找到需要重启的服务
标签: architecture microservices gitlab-ci continuous-deployment blue-green-deployment