声明:所有的实验示例大部分来自《learn-docker-in-a-month-of-lunches》的作者Elton Stoneman,但运行结果并不都是照搬,大部分实验结果可能与原书不同
一、容器与容器之间是如何通信的
容器与容器之间当然也是借由IP来实现容器之间的容器,但是仅有IP也是不够的,Docker虽然可以把其他容器在虚拟网络中IP直接告诉指定容器,但是若是其他容器因为某些原因重新启动了,该指定容器将可能找不到其他的容器,因为容器在重新启动后,Docker会分配给他们新的IP。其实同样的问题,在现实网络中也有,那么现实的网络中用什么解决的呢?没错!DNS服务!Docker有着内置的DNS服务机制,而容器名便是域名,一个容器若是想要获得另外一个容器的IP,它会先去请求Docker的DNS服务,如果该容器存在(当然必须是和请求服务的容器在同一个虚拟网络中的容器),则Docker会返回该容器的IP,如果不存在Docker将会请求主机的DNS服务。
- 使用
nslookup
去容器中看一下Docker的dns服务运行的效果
$ cd diamol/ch07/exercises/image-of-the-day
$ docker-compose up -d
Creating image-of-the-day_accesslog_1 ... done
Creating image-of-the-day_iotd_1 ... done
Creating image-of-the-day_image-gallery_1 ... done
$ docker container exec -it image-of-the-day_accesslog_1 sh
/app # nslookup iotd
Name: iotd
Address 1: 172.20.0.2 image-of-the-day_iotd_1.nat
/app # nslookup image-gallery
Name: image-gallery
Address 1: 172.20.0.4 image-of-the-day_image-gallery_1.nat
/app # nslookup www.baidu.com
Name: www.baidu.com
Address 1: 180.101.49.12
Address 2: 180.101.49.11
二、简单实现拥有复数个实例的服务的负载均衡
如果某个服务需要有多个实例同时工作,那么对于访问这个服务的请求应该要有一个均衡负载的机制,在Docker中,这种机制可以简单的通过Docker的DNS服务返回的IP列表来实现。如果某个容器有多个实例比如"iotd"有3个实例,那么Docker的DNS在接到该解析"iotd"域名的请求后,将会返回一个包含这3个实例的IP列表,但是要注意的是,这个IP列表的顺序是随机的,所以我们也就正好可以利用这个特性,在取IP结果时只取列表中的第一个IP,这样一个简单负载均衡就实现了。
- 给"iotd"服务创建三个实例
$ docker-compose up -d --scale iotd=3
Creating image-of-the-day_accesslog_1 ... done
Creating image-of-the-day_iotd_1 ... done
Creating image-of-the-day_iotd_2 ... done
Creating image-of-the-day_iotd_3 ... done
Creating image-of-the-day_image-gallery_1 ... done
- 使用
nslookup iotd
解析"iotd"的域名
$ docker container exec -it image-of-the-day_accesslog_1 sh
/app # nslookup iotd
Name: iotd
Address 1: 172.20.0.5 image-of-the-day_iotd_1.nat
Address 2: 172.20.0.2 image-of-the-day_iotd_2.nat
Address 3: 172.20.0.4 image-of-the-day_iotd_3.nat
/app # nslookup iotd
Name: iotd
Address 1: 172.20.0.4 image-of-the-day_iotd_3.nat
Address 2: 172.20.0.2 image-of-the-day_iotd_2.nat
Address 3: 172.20.0.5 image-of-the-day_iotd_1.nat
可以看到返回的两次结果是不一样的
- 访问localhost:8010然后查看iotd的日志
$ docker-compose logs --tail 1 iotd
Attaching to image-of-the-day_iotd_2, image-of-the-day_iotd_3, image-of-the-day_iotd_1
iotd_1 | 2020-02-15 13:31:49.361 INFO 1 --- [ main] iotd.Application : Started Application in 27.564 seconds (JVM running for 32.212)
iotd_2 | 2020-02-15 13:31:49.226 INFO 1 --- [ main] iotd.Application : Started Application in 27.9 seconds (JVM running for 32.543)
iotd_3 | 2020-02-15 13:31:49.123 INFO 1 --- [ main] iotd.Application : Started Application in 27.366 seconds (JVM running for 32.024)
$ curl localhost:8010
$ docker-compose logs --tail 1 iotd
Attaching to image-of-the-day_iotd_2, image-of-the-day_iotd_3, image-of-the-day_iotd_1
iotd_2 | 2020-02-15 13:31:49.226 INFO 1 --- [ main] iotd.Application : Started Application in 27.9 seconds (JVM running for 32.543)
iotd_1 | 2020-02-15 13:39:34.778 INFO 1 --- [p-nio-80-exec-1] iotd.ImageController : Fetched new APOD image from NASA
iotd_3 | 2020-02-15 13:31:49.123 INFO 1 --- [ main] iotd.Application : Started Application in 27.366 seconds (JVM running for 32.024)
$ curl localhost:8010
$ docker-compose logs --tail 1 iotd
Attaching to image-of-the-day_iotd_2, image-of-the-day_iotd_3, image-of-the-day_iotd_1
iotd_2 | 2020-02-15 13:42:56.150 INFO 1 --- [p-nio-80-exec-1] iotd.ImageController : Fetched new APOD image from NASA
iotd_1 | 2020-02-15 13:39:34.778 INFO 1 --- [p-nio-80-exec-1] iotd.ImageController : Fetched new APOD image from NASA
iotd_3 | 2020-02-15 13:31:49.123 INFO 1 --- [ main] iotd.Application : Started Application in 27.366 seconds (JVM running for 32.024)
可以看到第一次访问的请求是由"iotd1"负责的,第二次请求是由"iotd2"负责的
参考文档:
[1] learn-docker-in-a-month-of-lunches
[2] 官方文档
附:
[1] Elton Stoneman的github项目
网友评论