兄弟们晚上好:
现在我这边使用docker swarm 遇到了一个非常棘手的问题,
我们使用docker swarm 搭建集群跑的java容器。
在做滚动更新的时候。总是有请求进来,结果nginx那边报了一堆502。因为我们每台机器上面都跑了一个nginx然后在通过nginx的upstream来转发给本地机器的容器进程的。
upstream web {
server localhost:18081;
keepalive 300;
理论上docker swarm 集群在做滚动更新的时候。会先把集群内部的负载均衡里面摘掉既然废弃的容器进程,切断流量。然后停止这个容器,进而拉起一个容器。接着通过健康检测判断这个容器是否启动完毕。启动完毕之后,就会把这个容器进程加入到负载均衡里面的。这么下来就完成了滚动更新,毕竟集群会先在负载均衡摘掉流量的,所以不可能还有有流量打入这个即将废弃的容器进程了。可是现在我们每次发布更新总会伴着1000多条502的记录。
通过docker file 生成镜像的,而健康检测也是写到了docker file 里面的。
健康检测设置如下:
HEALTHCHECK --interval=20s --timeout=10s --retries=10 CMD wget --quiet --tries=1 --spider http://localhost:$service_port/healthCheck || exit 1
我们尝试过优雅关闭,设置过了--stop-signal 为30s 甚至60s 发现还是一样,发布过程中会出现502,现在两个方向。不确定这些502是由于流量打到了旧容器而导致的,还是流量打到新容器而导致的,新容器这个是怀疑我们的健康检测设置不合理,也就是容器进程还没有能够对外提供服务,健康检测却通过了,认为这个新容器进程是启动完毕了,加入了负载均衡有部分流量打到了新容器进程去。
k8s 巧巧很好的处理了这个问题,比如他们配置了preStop等这种策略。能够完美解决这个问题,但是docker swarm 目前,不敢相信会有这种问题。毕竟按照docker swarm 的滚动发布流程,是不可能有这种问题的。它是先摘除流量的。现在非常的头疼,不知道从何下手了。而一时之间我们也不能断然的上k8s集群。毕竟体量也很少,暂时不考虑。各位在使用docker swarm的时候是否遇见过这样的问题。请教,万分感谢,提前祝大家新年快乐~~
补充一下:我们的nginx 部署的网络是host模式,而应用是专门创建了一个overlay网络在里面跑的
NETWORK ID NAME DRIVER SCOPE
wqpezy5g2pjl bobo-network overlay swarm (这是我们后端应用跑的网络命名空间)
b4f0b8c4ef4d bridge bridge local
59347c5dfa7a docker_gwbridge bridge local
4079bbadea8b host host local
2cw5xft9mtyj ingress overlay swarm
cadc70451b26 none null local
efmpcxfd7yv1 portainer-agent_portainer_agent overlay swarm
从 upstream 的配置看,nginx 的部署有问题,nginx 应该通过 service name 访问 upstream
nginx 应该作为一个 service 与应用容器部署在同一网络
version: '3.4'
services:
public:
image: proxy_public:${IMAGE_VERSION}
ports:
- 80:80
deploy:
mode: global
update_config:
order: start-first
placement:
constraints: [node.role == worker]
networks:
public:
networks:
public:
external: true
nginx 配置 proxy_public.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80 default_server;
access_log off;
return 200 'Hello, World! - nginx\n';
}
server {
listen 80;
server_name ~^(staging-)?(?<app>[^.]+)\.cnblogs\.com$;
access_log off;
location / {
resolver 127.0.0.11;
proxy_set_header Host $host;
proxy_pass http://${app}_web;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
nginx proxy_public 镜像的 dockerfile
FROM nginx
COPY nginx.conf /etc/nginx
COPY proxy_public.conf /etc/nginx/conf.d
HEALTHCHECK --interval=5s --timeout=20s \
CMD curl -fs -o /dev/null localhost || exit 1
我们的生产环境在使用 k8s 之前用的是 docker swarm,staging 环境还在使用 docker swarm,没有遇到你所说的问题。
另外,即使体量小,生产环境还是建议使用 k8s。
好的,我尝试一下调整nginx