自动化运维之docker下——docker网络

目录

一、docker网络

1、Docker原生网络

(1)bridge桥接模式——和宿主机的网卡之间搭建一个“桥”

(2)host模式——直接使用宿主机的网卡

(3)none模式——无网络模式

2、Docker自定义网络

(1)自定义网桥的自动解析功能

(2)自定义网桥的自定义参数与网络隔离/互通

3、Docker容器通信

(1)同一网桥上的不同容器通信

(2)Joined容器——容器的网络被其他容器共享

(3)<--link>用来链接2个容器(也可以提供自动解析)

4、跨主机容器网络

(1)跨主机网络解决方案

(2)CNM(容器网络模型)介绍

(3) macvlan网络方案实现

(4)macvlan的网络扩展

(5)macvlan网络间的隔离和连通

macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。


一、docker网络

1、Docker原生网络

docker的镜像是令人称道的地方,但网络功能还是相对薄弱的部分。

docker安装后会自动创建3种网络:bridge(桥接)、host(主机网络)、none(禁用)    

(1)bridge桥接模式——和宿主机的网卡之间搭建一个“桥”

查看docker网络可以使用以下命令查看:

docker network ls             #查看docker的当前网络

装好docker后,会在网络管理看到一个“docker网桥”,如下所示。这个docker网桥和宿主机上的bridge是一个意思.

先启动一个demo,通过网桥管理工具查看其网络。可以看到容器的网关为<172.17.0.1>,这个IP就是“docker0网桥”的IP。

#查看容器网关
[root@server1 ~]# docker inspect demo | grep Gateway
            "Gateway": "172.17.0.1",
            "IPv6Gateway": "",
                    "Gateway": "172.17.0.1",
                    "IPv6Gateway": "",
#显示docker0网桥信息
[root@server1 ~]# ip addr  show docker0 
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:da:84:49:53 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:daff:fe84:4953/64 scope link 
       valid_lft forever preferred_lft forever

#查看网桥信息
[root@server1 ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.0242da844953	no		vethd8486ce

 查看宿主机的火墙,显示将所有<172.17.0.0>网段的数据做个NAT转发出去。

也就是说,容器每次启动时都会获得一个IP,且IP地址是递增的。某个容器停止后会释放该IP地址,因此存在一个问题:某个容器停止后重新启动,获得的IP和之前的不一样,即容器IP是动态的。

bridge桥接模式示意图:

因此docker网络的基本结构是:容器运行时获得一个IP<例如:172.17.0.3>,且容器的数据通过网关转发<例如:172.17.0.1>,宿主机的火墙将此网段的数据<例如:172.17.0.0>做一个地址伪装转发出去,与宿主机的网络<例如:172.25.254.1>进行数据交换。

 

这种桥接方式的特点bridge模式下容器没有一个公有ip,只有宿主机可以直接访问,外部主机是不可见的。容器通过宿主机的NAT规则后可以访问外网。

(2)host模式——直接使用宿主机的网卡

host模式连接示意图:

host模式特点:可以让容器共享宿主机网络栈,这样的好处是外部主机与容器直接通信,但是容器的网络缺少隔离性。

新建一个容器demo2,网络模式设置为host,查看网桥信息,并没有这个

#新建demo2,网络模式为host
docker run -d --name demo2 --network host nginx

#查看网桥
brctl show
        bridge name	bridge id		STP enabled	interfaces
        docker0		8000.0242da844953	no		vethd8486ce

#查看demo2的网络信息
docker inspect demo2  |tail -n 20

容器demo2的网络信息里,没有任何IP信息。

但是容器demo2会创建一个新的虚拟网卡,用于共享主机的IP

进入容器验证:

#前台运行一个demo容器并设置网络模式为host
docker run -it --name demo --network host busybox

查看容器的网络信息,和宿主机的IP是一样的。也就是说,访问宿主机的IP地址就可以访问到这个容器。 

(3)none模式——无网络模式

none模式是指禁用网络功能,只有lo接口,在容器创建时使用。

一般用于没有必要联网的容器。

 

2、Docker自定义网络

自定义网络模式中,docker提供了三种自定义网络驱动: bridge 、overlay 、macvlan。

bridge驱动类似默认的bridge网络模式,但增加了一些新的功能;

overlay和macvlan是用于创建跨主机网络。

建议使用自定义的网络来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。

(1)自定义网桥的自动解析功能

要将所有的容器都接入到自定义网桥上

第一步:创建docker网桥“mynet1”

#创建网桥mynet1
[root@server1 ~]# docker network create mynet1
    589b73ba7f509b987c894f24e9fadbe4efa61f99bfdebce75167e7240621a172

#显示doker所有网络
[root@server1 ~]# docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    0ed20a2c714a   bridge    bridge    local
    0c3ce8c7cca6   host      host      local
    589b73ba7f50   mynet1    bridge    local
    887bac06fb39   none      null      local

第二步:正常启动一个容器,命名为demo1,根据IP递增原则,demo1的IP地址为<172.14.0.2>。

第三步:再进入另一个容器busybox,IP被分配为<172.17.0.3>,可以直接ping通demo1的IP地址,但是无法ping通demo1域名。

第四步:重启一个demo1容器,但是将其网络设置为“mynet1”网桥。进入另一个容器bubybox中(也是同样的网桥),可以直接ping通域名而不需要知道demo1的IP。

#启动容器demo1,并设置网络模式为”--network mynet1“
[root@server1 ~]# docker run -d --name demo1 --network mynet1 nginx 


[root@server1 ~]# brctl show
    bridge name	bridge id		STP enabled	interfaces
    br-589b73ba7f50		8000.0242148d3277	no		veth488fc01
    docker0		8000.0242da844953	no		

#启动容器,并设置网络模式为”--network mynet1“
[root@server1 ~]# docker run -it --rm --network mynet1 busybox
    / # ping demo1
    PING demo1 (172.18.0.2): 56 data bytes
    64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.115 ms
    64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.114 ms

第五步:自动解析的应用

先启动demo1,测得IP为<172.18.0.2>。当demo1故障时,启动demo2后,测得demo2的IP为<172.18.0.2>这是因为demo1挂掉后IP被释放;接着demo1恢复正常,测得demo1的IP为<172.18.0.3>。

因此无论容器的IP为多少,只需要容器的名字就可以访问容器。 

 

(2)自定义网桥的自定义参数网络隔离/互通

第一步:删除上一步中创建的容器demo1和demo2。删除网桥。

#删除docker网桥mynet1
[root@server1 ~]# docker network rm mynet1 
    mynet1

#查看docker的网络列表
[root@server1 ~]# docker network ls
    NETWORK ID     NAME      DRIVER    SCOPE
    0ed20a2c714a   bridge    bridge    local
    0c3ce8c7cca6   host      host      local
    887bac06fb39   none      null      local

第二步:创建网桥时指定参数

#创建docker网桥并指定网关和子网
docker network create --subnet 172.20.0.0/24 --gateway 172.20.0.1 mynet1

#查看docker网桥信息
docker network inspect mynet1 
            "Subnet": "172.20.0.0/24",
            "Gateway": "172.20.0.1"

第三步:创建容器时指定容器IP

创建容器demo1时指定IP(--ip参数可以手动指定IP),通过curl测试,可以连接demo1。

#创建容器demo1并指定IP为<172.20.0.111>
docker run -d --name demo1 --network mynet1 --ip 172.20.0.111 nginx

#测试容器demo1的IP 
curl 172.20.0.111
    <!DOCTYPE html>
    <html>
    <head>
    <title>Welcome to nginx!</title>

第四步:创建不同网段的mynet2

#创建自定义参数docker网桥mynet2
docker network create --subnet 172.30.0.0/24 --gateway 172.30.0.1 mynet2

#创建mynet2网段下的容器demo2
docker run -d --name demo2 --network mynet2 --ip 172.30.0.111 nginx

#查看网桥,不同的网段连在不同网桥
[root@server1 ~]# brctl show
    bridge name	bridge id		STP enabled	interfaces
    br-67c9e18787ca		8000.0242c07abce9	no		vethc43fc6d
    br-eb5283bda938		8000.02424180a480	no		veth7546f60

第五步:测试网络隔离

进入容器busybox中,指定的是mynet1的网桥,因此可以连接同一网桥上的容器,而不能连接另一网桥mynet2上的容器

第六步:测试网桥互通

网桥互通原理图:

 

不同网段的网桥自然会隔离,但是如果有需求让不同网桥之间通信,就需要设置网桥互通。

接着上一步实验。按<Ctrl>+<p>+<q>将busybox容器打入后台后,查看其进程信息。该容器原本是属于“mynet1网桥”,向该容器中添加“mynet2网桥”(添加网桥命令如下),添加完成后,再次进入该容器。测试后可以连接mynet2网段的主机了。

本质上是,向容器中添加了一个虚拟网卡,两个网卡连接不同网段,实现数据互通。

#显示正在进行的容器
docker ps -a
    CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS              PORTS     NAMES
    8f0dc0391906   busybox   "sh"                     3 minutes ago    Up 3 minutes              cranky_wright

#向该容器中添加另一网段的网桥,可以是容器ID也可以是容器名称
docker network connect mynet2 cranky_wright

#重新进入该容器
docker attach cranky_wright

3、Docker容器通信

(1)同一网桥上的不同容器通信

容器之间除了使用ip通信外,还可以使用容器名称通信。

docker 1.10开始,内嵌了一个DNS server。 dns解析功能必须在自定义网络中使用。 启动容器时使用 --name 参数指定容器名称。

(2)Joined容器——容器的网络被其他容器共享

和之前的host模型很相似,host模式下,容器共享主机的网络;此模式下,容器共享容器的网络。

处于这个模式下的 Docker 容器会共享一个网络栈,这样两个容器之间可以使用localhost高效快速通信。

Joined容器一种较为特别的网络模式。在容器创建时使用--network=container:vm1指定。(vm1指定的是运行的容器名)

[root@server1 ~]# docker run --rm -it --network container:demo1 busybox
/ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
142: eth0@if143: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:14:00:6f brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.111/24 brd 172.20.0.255 scope global eth0
       valid_lft forever preferred_lft forever

注意:这种情况下,两个容器之间的监听端口不能有冲突。比如demo1启用nginx时监听的是80端口,如果共享网络时启动的容器监听的也是80端口,那么就会报错!!!

(3)<--link>用来链接2个容器(也可以提供自动解析)

--link的格式: --link <name or id>:alias,其中name和id是源容器的name和id,alias是源容器在link下的别名。

实际上是在容器内部对<--link>设置的别名做了一个解析。

[root@server1 ~]# docker run -d --name demo1 nginx
    373242dc7da15c2a27a83ad5dbd3f28a04eed30389035985e1234b71272dad69
[root@server1 ~]# docker ps -a
    CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS             PORTS     NAMES
    373242dc7da1   nginx     "/docker-entrypoint.…"   3 seconds ago   Up 2 seconds   80/tcp    demo1
[root@server1 ~]# 
[root@server1 ~]# docker run --rm -it --link demo1:webserver busybox
    / # 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.2	webserver 373242dc7da1 demo1
    172.17.0.3	b72c55a4b53e

(4)容器间通信

已知容器数据出去时,用到的是火墙策略的SNAT模式:

容器数据进来时,即外网访问容器用到了docker-proxy和iptables DNAT:

宿主机访问本机容器使用的是iptables DNAT

外部主机访问容器或容器之间的访问是docker-proxy实现

原理图如下所示:

测试:

启动一个容器demo1,并将宿主机80端口和容器80端口做映射。做好映射后,查看宿主机的火墙策略,发现已经新加了一个DNAT策略。那么外部网络就可以通过访问宿主机的80端口直接访问容器内部。

docker-proxy和iptables的双重网络机制:

外网访问容器有docker-proxy和iptables两种方式,只要其中任意一种方式存在,外网都可以访问容器内部。(也就是双层保险)

以下以iptables失效为例。

清除掉iptables中的火墙策略后,通过外网还可以访问。

这是因为docker网络除了DNAT之外还有docker-proxy机制,接下来强制结束docker-proxy进程,外部网络再次访问时无法访问。

4、跨主机容器网络

以上都只是介绍了同一宿主机下的不同docker之间的通信。在实际生产环境中,需要不同主机之间的容器进行通信。

(1)跨主机网络解决方案

**跨主机网络解决方案:

(1)docker原生的overlay和macvlan

(2)第三方的flannel、weave、calico

**众多网络方案是如何与docker集成在一起的:

libnetwork     docker容器网络库

CNM (Container Network Model)这个模型对容器网络进行了抽象

(2)CNM(容器网络模型)介绍

CNM(容器网络模型)分三类组件:

(1)Sandbox:容器网络栈,包含容器接口、dns、路由表。(namespace)

(2)Endpoint:作用是将sandbox接入network (veth pair)

(3)Network:包含一组endpoint,同一network的endpoint可以通信。

(3) macvlan网络方案实现

定义:Linux kernel提供的一种网卡虚拟化技术。

优点:无需Linux bridge,直接使用物理接口,性能极好。

第一步:准备两台虚拟机,并清除docker中不用的network网络

docker network prune             #清除docker不用的网桥

第二步:启用eht0网卡的混杂模式

两台虚拟机都要打开网卡混杂模式。

ip link set eth0 promisc on                 #打开网卡混杂模式

第三步:创建macvlan网卡

在两台虚拟机上都执行以下命令,都在eth0上创建macvlan。

注意:两台虚拟机上创建的macvlan的子网和网关必须一样(在同一网段)

docker network create -d macvlan --subnet 172.20.0.0/24 --gateway 172.20.0.1 -o parent=eth0 mynet1
# 创建网卡; -d 指定macvlan模式; -o 指定此macvlan的父级为eth0(即直接跟此网卡通信); 网卡名为mynet1

 第四步:分别启动容器并测试

为容器设置IP时需要管理员手动设置,不会自动分配。便于管理!!!

在server1中:IP设置为<172.20.0.111>

root@server1 ~]# docker run -it --name demo1 --network mynet1 --ip 172.20.0.111 busybox
    / # ip addr 
    185: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:14:00:6f brd ff:ff:ff:ff:ff:ff
    inet 172.20.0.111/24 brd 172.20.0.255 scope global eth0

在server2中:IP设置为<172.20.0.222>

[root@server2 ~]# docker run -it --name demo1 --network mynet1 --ip 172.20.0.222 busybox
    / # ip addr
    25: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
        link/ether 02:42:ac:14:00:de brd ff:ff:ff:ff:ff:ff
        inet 172.20.0.222/24 brd 172.20.0.255 scope global eth0
 
    / # ping 172.20.0.111
    PING 172.20.0.111 (172.20.0.111): 56 data bytes
    64 bytes from 172.20.0.111: seq=0 ttl=64 time=0.613 ms
    64 bytes from 172.20.0.111: seq=1 ttl=64 time=0.477 ms

测试结果显示:不同宿主机下的不同容器实现了互通 

(4)macvlan的网络扩展

优点:

一、没有新建linux bridge

二、容器的接口直接与主机网卡连接,无需NAT或端口映射。

局限性:

macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络

vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094。

解决方法1——新建多个网卡

每个macvlan的子网都会独占一个网卡。因此在实际生产环境中,会有成千上万台设备,如果只是增加网卡的话,在硬件层面不现实。

ip link set eth1 up                    #激活eth1网卡
ip link set eth1 promisc on            #打开eth1混杂模式

docker network create -d macvlan --subnet 172.30.0.0/24 --gateway 172.30.0.1 -o parent=eth1 mynet2
#在eht1上创建macvlan模式网卡mynet2,并指定子网和网关为<172.30.0.0>

解决方法2——vlan子接口

也就是说在每个网卡上开启多个vlan子接口,每个接口用于一个子网。

#创建mynet3,父级网卡为eth1.1,子网为<172.40.0.0>
docker network create -d macvlan --subnet 172.40.0.0/24 --gateway 172.40.0.1 -o parent=eth1.1 mynet3

#创建mynet4,父级网卡为eth1.2,子网为<172.40.0.0>
docker network create -d macvlan --subnet 172.50.0.0/24 --gateway 172.50.0.1 -o parent=eth1.2 mynet4

#创建mynet5,父级网卡为eth1.3,子网为<172.40.0.0>
docker network create -d macvlan --subnet 172.60.0.0/24 --gateway 172.60.0.1 -o parent=eth1.3 mynet5

查看宿主机网卡信息,在eth1上出现很多子接口。

 

(5)macvlan网络间的隔离和连通

macvlan网络在二层上是隔离的,所以不同macvlan网络的容器是不能通信的。

可以在三层上通过网关将macvlan网络连通起来。(也就是之前提到过的不同docker之间的通信:<docker network connect mynet2 cranky_wright>)

docker本身不做任何限制,像传统vlan网络那样管理即可。 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值