阅读 1615

如何实现多容器互联?

背景

同一宿主机上运行多个容器,每个容器对应不同的服务,当服务之间需要进行通信时(比如:http通信)就涉及到容器之间互联的问题,根据以往的经验给出几种实现的方式

ip

容器之间通过ip地址进行通信。 缺点很明显,容器的ip地址不是一成不变的,容器重启或者迁移都会造成ip地址的变化,从而导致服务之间通信失败。

network=container:xxx

[root@t32 ~]# docker run -itd --name myapp docker.io/ikubernetes/myapp:v2
cfb3370a23e314ad407f0a5e98db5aecd445e94774b41f5f6cbab8a847af74b0
[root@t32 ~]# docker run -it --network=container:myapp --name test centos:7.5.1804 bash
[root@cfb3370a23e3 /]# curl localhost:80
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@cfb3370a23e3 /]# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.10	cfb3370a23e3
复制代码

容器myapp与容器test在同一个network namespace,因此在容器test下可以使用localhost

link

[root@t32 ~]# docker run -it --link=myapp --name test centos:7.5.1804 bash 
[root@b41364a8bdc4 /]# curl localhost:80
curl: (7) Failed connect to localhost:80; Connection refused
[root@b41364a8bdc4 /]# curl myapp:80
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@b41364a8bdc4 /]# cat /etc/hosts
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.17.0.10	myapp cfb3370a23e3
172.17.0.11	b41364a8bdc4
复制代码

容器myapp与容器test不在同一个network namespace下,但是test连接myapp之后,会将myapp以及对应ip地址写入到test下的/etc/hosts下,从而可以通过containerName:port通信

network=container:xxxlink的方法在多个容器需要互相通信的情况下,会导致启动命令过于复杂,维护性差

network=host

network=host是docker标准网络形式之一,指定容器与宿主机共享同一个network namespace。

多个容器共享host的network,容器之间可以通过localhost完成通信。

但是,这种方式的缺点十分明显,不能够充分发挥容器的便捷性,比如部署两个mysql数据库,如果都采用host网络,则会有一个mysql容器启动失败(因为5432端口已经被占用)

bridge

最后出场的,也是最推崇的办法,即创建一个bridge,多个容器链接到同一个bridge上面,从而通过containerName:port通信。

[root@t32 ~]# docker network create my-net2
7135ba540b5fd164b16c7f85629d53df5de9d014378b9984a641a8d0f3fddb18

[root@t32 ~]# docker network ls |grep my-net2
7135ba540b5f        my-net2             bridge              local

[root@t32 ~]# docker run -itd --name myapp --network=my-net2 docker.io/ikubernetes/myapp:v2
85011452d8df633642224e1b1dd5b91ca0d408774296010ff808eb9227b90379

[root@t32 ~]# docker run -itd --name myapp1 --network=my-net2 docker.io/ikubernetes/myapp:v3
048e70a79e65f064e21c0ef48b26e3142280b627dedf5864b28dc76d269cc857

[root@t32 ~]# docker run -it --name test --network=my-net2 centos:7.5.1804 bash 

[root@f6cd7182338f /]# cat /etc/hosts 
127.0.0.1	localhost
::1	localhost ip6-localhost ip6-loopback
fe00::0	ip6-localnet
ff00::0	ip6-mcastprefix
ff02::1	ip6-allnodes
ff02::2	ip6-allrouters
172.21.0.4	f6cd7182338f

[root@f6cd7182338f /]# cat /etc/resolv.conf 
nameserver 127.0.0.11
options ndots:0

[root@f6cd7182338f /]# curl myapp
Hello MyApp | Version: v2 | <a href="hostname.html">Pod Name</a>
[root@f6cd7182338f /]# curl myapp1
Hello MyApp | Version: v3 | <a href="hostname.html">Pod Name</a>
复制代码
  • bridge方式中的/etc/resolv.conf与其他方法不同,其他方法共享宿主机上的/etc/resolve.conf(即dns解析),而bridge则使用自己的dns解析信息
  • 多个容器全部使用bridge,可以便于多容器互联
查看bridge的信息
[root@t32 ~]# docker inspect my-net2
[
    {
        "Name": "my-net2",
        "Id": "7135ba540b5fd164b16c7f85629d53df5de9d014378b9984a641a8d0f3fddb18",
        "Created": "2020-10-14T21:11:04.941285678+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.21.0.0/16",
                    "Gateway": "172.21.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Containers": {
            "048e70a79e65f064e21c0ef48b26e3142280b627dedf5864b28dc76d269cc857": {
                "Name": "myapp1",
                "EndpointID": "31ad488d3c0b94a4b223fd6026e8e59586ac7214b2a4319a7b17c050eeb95f28",
                "MacAddress": "02:42:ac:15:00:03",
                "IPv4Address": "172.21.0.3/16",
                "IPv6Address": ""
            },
            "85011452d8df633642224e1b1dd5b91ca0d408774296010ff808eb9227b90379": {
                "Name": "myapp",
                "EndpointID": "c8cb27609c1ac8d5bc6ed717f5be7945e0db2f1cd387cc12ba230125e1c544a0",
                "MacAddress": "02:42:ac:15:00:02",
                "IPv4Address": "172.21.0.2/16",
                "IPv6Address": ""
            },
            "9a1526e9d2fe2c07081c1f1e3b08e564468d9d908e1b0965095e90e94e6de914": {
                "Name": "test",
                "EndpointID": "1e013be5fd8307400999501c28a2d43871d75c2c306e0cb180d3938a1b6d4fcf",
                "MacAddress": "02:42:ac:15:00:04",
                "IPv4Address": "172.21.0.4/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
复制代码
  • 能够查看挂载在my-net2上面的容器
  • 不同的bridge分配不同的网段,多个容器在同一个网段下。
文章分类
后端
文章标签