当前位置: 首页 > news >正文

【Docker】Docker-Compose内置DNS负载均衡失效问题

在这里插入图片描述

Docker Compose实现负载均衡

还是对前面的例子docker-compose.yml稍微修改:

version: "3.8"services:flask-demo:build:context: .dockerfile: Dockerfileimage: flask-demo:latestenvironment:- REDIS_HOST=redis-server- REDIS_PASS=${REDIS_PASS}healthcheck:test: ["CMD", "curl", "-f", "http://localhost:5000"]interval: 30stimeout: 3sretries: 3start_period: 40sdepends_on:- redis-serverdeploy:replicas: 3networks:- backend- frontendredis-server:image: redis:latestcommand: redis-server --requirepass ${REDIS_PASS}networks:- backendnginx:image: nginx:stable-alpineports:- 8000:80depends_on:flask-demo:condition: service_healthyvolumes:- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro- ./log/nginx:/var/log/nginxnetworks:- frontendnetworks:backend:frontend:

主要是修改flask-demo启动3个容器。

nginx.conf文件的内容如下:

server {listen  80 default_server;location / {proxy_pass http://flask-demo:5000;}
}

启动服务:

$ docker-compose up -d
Creating network "app8_backend" with the default driver
Creating network "app8_frontend" with the default driver
Creating app8_redis-server_1 ... done
Creating app8_flask-demo_1   ... done
Creating app8_flask-demo_2   ... done
Creating app8_flask-demo_3   ... done
Creating app8_nginx_1        ... done$ docker-compose psName                      Command                  State                      Ports
----------------------------------------------------------------------------------------------------------
app8_flask-demo_1     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_flask-demo_2     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_flask-demo_3     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_nginx_1          /docker-entrypoint.sh ngin ...   Up             0.0.0.0:8000->80/tcp,:::8000->80/tcp
app8_redis-server_1   docker-entrypoint.sh redis ...   Up             6379/tcp

访问服务:

$ curl localhost:8000
Hello Container World! I have been seen 4 times and my hostname is 448b5d70d3d8.$ curl localhost:8000
Hello Container World! I have been seen 5 times and my hostname is 77b2a2314533.$ curl localhost:8000
Hello Container World! I have been seen 9 times and my hostname is 4eee9c8d54f1.

从运行结果可以发现我们可以根据service的名称访问容器,Docker会使用内置的DNS服务器将service的名称解析成IP,如果service对应的容器有多个,nginx会进行负载均衡。

Docker带有一个内置的DNS服务器。默认情况下,可以通过127.0.0.11:53访问服务器。这个DNS的IP可以通过进入容器内部查看/etc/resolv.conf获得:

$ docker-compose exec nginx cat /etc/resolv.conf
nameserver 127.0.0.11
options ndots:0

负载均衡的实现

在上面的例子中我们将flask-demo容器的个数提高到6个:

$ docker-compose up -d --scale flask-demo=6
app8_redis-server_1 is up-to-date
Creating app8_flask-demo_4 ... done
Creating app8_flask-demo_5 ... done
Creating app8_flask-demo_6 ... done
app8_nginx_1 is up-to-date$ docker-compose psName                      Command                  State                      Ports
----------------------------------------------------------------------------------------------------------
app8_flask-demo_1     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_flask-demo_2     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_flask-demo_3     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_flask-demo_4     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_flask-demo_5     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_flask-demo_6     flask run -h 0.0.0.0             Up (healthy)   5000/tcp
app8_nginx_1          /docker-entrypoint.sh ngin ...   Up             0.0.0.0:8000->80/tcp,:::8000->80/tcp
app8_redis-server_1   docker-entrypoint.sh redis ...   Up             6379/tcp$ docker container ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS                    PORTSNAMES
6e1494379165   flask-demo:latest     "flask run -h 0.0.0.0"   53 seconds ago   Up 51 seconds (healthy)   5000/tcpapp8_flask-demo_6
62733bdccdb8   flask-demo:latest     "flask run -h 0.0.0.0"   53 seconds ago   Up 51 seconds (healthy)   5000/tcpapp8_flask-demo_5
77e74622fa4e   flask-demo:latest     "flask run -h 0.0.0.0"   53 seconds ago   Up 51 seconds (healthy)   5000/tcpapp8_flask-demo_4
b67132189d90   nginx:stable-alpine   "/docker-entrypoint.…"   2 minutes ago    Up 2 minutes              0.0.0.0:8000->80/tcp, :::8000->80/tcp   app8_nginx_1
448b5d70d3d8   flask-demo:latest     "flask run -h 0.0.0.0"   2 minutes ago    Up 2 minutes (healthy)    5000/tcpapp8_flask-demo_1
4eee9c8d54f1   flask-demo:latest     "flask run -h 0.0.0.0"   2 minutes ago    Up 2 minutes (healthy)    5000/tcpapp8_flask-demo_2
77b2a2314533   flask-demo:latest     "flask run -h 0.0.0.0"   2 minutes ago    Up 2 minutes (healthy)    5000/tcpapp8_flask-demo_3
215beaad114a   redis:latest          "docker-entrypoint.s…"   2 minutes ago    Up 2 minutes              6379/tcpapp8_redis-server_1

再次访问我们的服务:

$ curl localhost:8000
Hello Container World! I have been seen 28 times and my hostname is 448b5d70d3d8.$ curl localhost:8000
Hello Container World! I have been seen 29 times and my hostname is 77b2a2314533.$ curl localhost:8000
Hello Container World! I have been seen 30 times and my hostname is 4eee9c8d54f1.$ curl localhost:8000
Hello Container World! I have been seen 31 times and my hostname is 448b5d70d3d8.$ curl localhost:8000
Hello Container World! I have been seen 32 times and my hostname is 77b2a2314533.$ curl localhost:8000
Hello Container World! I have been seen 33 times and my hostname is 4eee9c8d54f1.

连续访问6次之后发现请求并没有转发到我们新启动的3个容器中,这是为什么呢?

负载均衡失效原因分析

初步怀疑是DNS解析失效,我们进入nginx容器查看DNS在解析flask-demo时解析出哪些IP:

$ docker-compose exec nginx sh
/ # apk update
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/main/x86_64/APKINDEX.tar.gz
fetch https://dl-cdn.alpinelinux.org/alpine/v3.14/community/x86_64/APKINDEX.tar.gz
v3.14.10-47-g7553b19fe26 [https://dl-cdn.alpinelinux.org/alpine/v3.14/main]
v3.14.10-42-gd8ce7b89082 [https://dl-cdn.alpinelinux.org/alpine/v3.14/community]
OK: 14983 distinct packages available/ # apk add bind-tools
(1/11) Installing fstrm (0.6.1-r0)
(2/11) Installing krb5-conf (1.0-r2)
(3/11) Installing libcom_err (1.46.2-r1)
(4/11) Installing keyutils-libs (1.6.3-r0)
(5/11) Installing libverto (0.3.2-r0)
(6/11) Installing krb5-libs (1.18.5-r0)
(7/11) Installing json-c (0.15-r1)
(8/11) Installing protobuf-c (1.3.3-r6)
(9/11) Installing libuv (1.41.0-r0)
(10/11) Installing bind-libs (9.16.39-r0)
(11/11) Installing bind-tools (9.16.39-r0)
Executing busybox-1.33.1-r6.trigger
OK: 31 MiB in 53 packages
/ # dig flask-demo; <<>> DiG 9.16.39 <<>> flask-demo
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 55582
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0;; QUESTION SECTION:
;flask-demo.                    IN      A;; ANSWER SECTION:
flask-demo.             600     IN      A       192.168.96.7
flask-demo.             600     IN      A       192.168.96.2
flask-demo.             600     IN      A       192.168.96.3
flask-demo.             600     IN      A       192.168.96.4
flask-demo.             600     IN      A       192.168.96.8
flask-demo.             600     IN      A       192.168.96.6;; Query time: 0 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Tue Oct 10 08:45:53 UTC 2023
;; MSG SIZE  rcvd: 184

发现DNS解析出了6个IP,然后我们在nginx容器中访问flask-demo

/ # curl flask-demo:5000
Hello Container World! I have been seen 281 times and my hostname is 77e74622fa4e./ # curl flask-demo:5000
Hello Container World! I have been seen 282 times and my hostname is 4eee9c8d54f1./ # curl flask-demo:5000
Hello Container World! I have been seen 283 times and my hostname is 62733bdccdb8./ # curl flask-demo:5000
Hello Container World! I have been seen 284 times and my hostname is 448b5d70d3d8./ # curl flask-demo:5000
Hello Container World! I have been seen 285 times and my hostname is 6e1494379165./ # curl flask-demo:5000
Hello Container World! I have been seen 289 times and my hostname is 77b2a2314533.

在nginx容器内访问就能访问到6个节点,那就说明nginx容器中DNS的解析没有问题,问题出在Nginx服务上。

Nginx在启动的时候会将代理服务器域名解析的ip地址缓存起来,后续不会再更新这个缓存,除非重启。

我们可以给nginx的缓存设置一个失效事件来解决这个问题,nginx.conf配置修改如下:

server {listen  80 default_server;location / {resolver 127.0.0.11 valid=1s; #设置dns服务器,缓存时间改为1sset $backend http://web:5000proxy_pass $backend;}
}

然后再让nginx重新加载配置,再访问服务,发现已经生效了:

$ docker-compose exec nginx nginx -s reload$ curl localhost:8000
Hello Container World! I have been seen 414 times and my hostname is 77b2a2314533.$ curl localhost:8000
Hello Container World! I have been seen 415 times and my hostname is 448b5d70d3d8.$ curl localhost:8000
Hello Container World! I have been seen 417 times and my hostname is 4eee9c8d54f1.$ curl localhost:8000
Hello Container World! I have been seen 420 times and my hostname is 77e74622fa4e.$ curl localhost:8000
Hello Container World! I have been seen 421 times and my hostname is 6e1494379165.$ curl localhost:8000
Hello Container World! I have been seen 422 times and my hostname is 62733bdccdb8.

docker compose参考例子

  • 投票app练习:https://github.com/dockersamples/example-voting-app
  • docker-compose example:https://github.com/docker/awesome-compose
http://www.lryc.cn/news/208296.html

相关文章:

  • [Python]Selenium-自动化测试
  • 高效管理文件夹名称:如何批量修改指定多样化的文件夹名称
  • c 读取音频协议WAV文件头(再生成wav文件)
  • Prompt设计与大语言模型微调
  • 修复VS2015没有代码提示的问题【已解决】
  • DeepSpeed: 大模型训练框架 | 京东云技术团队
  • 暄桐推荐|学书法的必读书目
  • 2023年赋能更多的人
  • 量子计算与量子密码(入门级)
  • 将安全作为首要目标 — Venus 的现状和前景展望
  • 『第七章』翩翩起舞的雨燕:顺序与并发执行
  • c语言进制的转换10进制转换16进制
  • js中的Formdata数据结构
  • Spring MVC 执行流程
  • JAVA毕业设计104—基于Java+Springboot+Vue的医院预约挂号小程序(源码+数据库)
  • 一文了解独立站黑科技:clock斗篷技术
  • Java IDEA controller导出CSV,excel
  • FFmpeg编译安装(windows环境)以及在vs2022中调用
  • gRPC之gateway集成swagger
  • Pytorch从零开始实战07
  • 大数据知识扫盲
  • 使用Ubuntu虚拟机离线部署RKE2高可用集群
  • 记一次任意文件下载到Getshell
  • java异常处理
  • 递归为什么这么难?一篇文章带你了解递归
  • X86(32位)汇编指令与机器码转换原理
  • ES 全字段模糊检索时分词方式对检索结果的影响
  • 基于Python Django 的微博舆论、微博情感分析可视化系统(V2.0)
  • python读取Excel到mysql
  • C++八股文面经