如何解決Docker-Compose內(nèi)置DNS負載均衡失效問題
Docker Compose實現(xiàn)負載均衡
- 還是對前面的例子
docker-compose.yml稍微修改:
version: "3.8"
services:
flask-demo:
build:
context: .
dockerfile: Dockerfile
image: flask-demo:latest
environment:
- REDIS_HOST=redis-server
- REDIS_PASS=${REDIS_PASS}
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000"]
interval: 30s
timeout: 3s
retries: 3
start_period: 40s
depends_on:
- redis-server
deploy:
replicas: 3
networks:
- backend
- frontend
redis-server:
image: redis:latest
command: redis-server --requirepass ${REDIS_PASS}
networks:
- backend
nginx:
image: nginx:stable-alpine
ports:
- 8000:80
depends_on:
flask-demo:
condition: service_healthy
volumes:
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
- ./log/nginx:/var/log/nginx
networks:
- frontend
networks:
backend:
frontend:主要是修改flask-demo啟動3個容器。
nginx.conf文件的內(nèi)容如下:
server {
listen 80 default_server;
location / {
proxy_pass http://flask-demo:5000;
}
}- 啟動服務(wù):
$ 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 ps
Name 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- 訪問服務(wù):
$ 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.
從運行結(jié)果可以發(fā)現(xiàn)我們可以根據(jù)service的名稱訪問容器,Docker會使用內(nèi)置的DNS服務(wù)器將service的名稱解析成IP,如果service對應(yīng)的容器有多個,nginx會進行負載均衡。
Docker帶有一個內(nèi)置的DNS服務(wù)器。默認情況下,可以通過127.0.0.11:53訪問服務(wù)器。
這個DNS的IP可以通過進入容器內(nèi)部查看/etc/resolv.conf獲得:
$ docker-compose exec nginx cat /etc/resolv.conf nameserver 127.0.0.11 options ndots:0
負載均衡的實現(xiàn)
- 在上面的例子中我們將
flask-demo容器的個數(shù)提高到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 ps
Name 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 PORTS
NAMES
6e1494379165 flask-demo:latest "flask run -h 0.0.0.0" 53 seconds ago Up 51 seconds (healthy) 5000/tcp
app8_flask-demo_6
62733bdccdb8 flask-demo:latest "flask run -h 0.0.0.0" 53 seconds ago Up 51 seconds (healthy) 5000/tcp
app8_flask-demo_5
77e74622fa4e flask-demo:latest "flask run -h 0.0.0.0" 53 seconds ago Up 51 seconds (healthy) 5000/tcp
app8_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/tcp
app8_flask-demo_1
4eee9c8d54f1 flask-demo:latest "flask run -h 0.0.0.0" 2 minutes ago Up 2 minutes (healthy) 5000/tcp
app8_flask-demo_2
77b2a2314533 flask-demo:latest "flask run -h 0.0.0.0" 2 minutes ago Up 2 minutes (healthy) 5000/tcp
app8_flask-demo_3
215beaad114a redis:latest "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 6379/tcp
app8_redis-server_1- 再次訪問我們的服務(wù):
$ 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.
連續(xù)訪問6次之后發(fā)現(xiàn)請求并沒有轉(zhuǎn)發(fā)到我們新啟動的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
- 發(fā)現(xiàn)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容器內(nèi)訪問就能訪問到6個節(jié)點,那就說明nginx容器中DNS的解析沒有問題,問題出在Nginx服務(wù)上。
Nginx在啟動的時候會將代理服務(wù)器域名解析的ip地址緩存起來,后續(xù)不會再更新這個緩存,除非重啟。
- 我們可以給nginx的緩存設(shè)置一個失效事件來解決這個問題,nginx.conf配置修改如下:
server {
listen 80 default_server;
location / {
resolver 127.0.0.11 valid=1s; #設(shè)置dns服務(wù)器,緩存時間改為1s
set $backend http://web:5000
proxy_pass $backend;
}
}- 然后再讓nginx重新加載配置,再訪問服務(wù),發(fā)現(xiàn)已經(jīng)生效了:
$ 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.
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解基于docker 如何部署surging分布式微服務(wù)引擎
這篇文章主要介紹了詳解基于docker 如何部署surging分布式微服務(wù)引擎,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
如何使用Docker部署Xxl-Job分布式任務(wù)調(diào)度中心
XXL-Job是一個開源的分布式任務(wù)調(diào)度中心,它提供了一個可視化的任務(wù)管理界面,可以方便地創(chuàng)建、編輯和監(jiān)控任務(wù),本文詳細的講解了如何使用Docker部署xxl-job分布式任務(wù)調(diào)度服務(wù),感興趣的朋友跟隨小編一起看看吧2024-03-03
Docker自定義JDK鏡像并拉取至阿里云鏡像倉庫超詳細攻略
Docker倉庫是集中存放鏡像的地方,分為公共倉庫和私有倉庫,這篇文章主要給大家介紹了關(guān)于Docker自定義JDK鏡像并拉取至阿里云鏡像倉庫的相關(guān)資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-08-08
docker沒有錯誤日志,鏡像服務(wù)卻啟動不成功的問題以及排查方式
這篇文章主要介紹了docker沒有錯誤日志,鏡像服務(wù)卻啟動不成功的問題以及排查方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
詳解Windows下運用Docker部署Node.js開發(fā)環(huán)境
這篇文章主要介紹了詳解Windows下運用Docker部署Node.js開發(fā)環(huán)境,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01

