企业 docker网络

docker 网络

bridge: 当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。bridge模式是docker的默认网络模式。

host: 如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
使用host模式的容器可以直接使用宿主机的IP地址与外界通信,容器内部的服务端口也可以使用宿主机的端口,不需要进行NAT,host最大的优势就是网络性能比较好,但是docker host上已经使用的端口就不能再用了,网络的隔离性不好。

none(禁用网络模式): 使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。
这种网络模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过–network=none来指定。这种类型的网络没有办法联网,封闭的网络能很好的保证容器的安全性。
有一些应用不需要连接外网,或者存放的数据是重要或秘密数据,可以使用 none 模式

[root@server1 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
5d62329b5a17        bridge              bridge              local
4647bd9edfdc        host                host                local
a08b5e2f1ec5        none                null                local

#网络的开启方式
docker run -d --name vm1 ubuntu	#默认开启的是桥接网络
docker run -it --name vm1 --network host ubuntu	#加参数host,开启host网络模式,可以查看到和宿主机一样的网络配置
docker run -it --name vm1 --network none ubuntu #加参数none,开启无网络模式,运行的容器里只能看到lo

docker 自定义网络

三种网络驱动:
1.bridge(自定义的 bridge 带 dns 解析功能,可以直接使用 vm1 vm2 这种名字去访问,不一定要使用 ip) ;
2.overlay ;3.macvlan,后面两种用于跨主机的网络,也就是集群等。

创建方式

[root@server1 ~]# docker network create -d bridge my_net1 #创建一个名为my_net1 的自定义网络

[root@server1 ~]# docker network ls
790a524e3bfe        my_net1             bridge              local
[root@server1 ~]# docker run  -it --name vm1 --network my_net1 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
7: eth0@if8: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0	
    #分配到的是172.18网段的ip,容器的 ip 是单调递增,网段也是
       valid_lft forever preferred_lft forever

自定义网络的网段子网和网关

[root@server1 ~]# docker network inspect my_net1	#查看网络的具体信息
 "Subnet": "172.18.0.0/16",	#里面有写网段、网关等信息
 "Gateway": "172.18.0.1"

 建立一个my_net2的网络定义网段网关
[root@server1 ~]# docker network  create -d bridge  --subnet 172.25.0.0/24 --gateway 172.25.0.1 my_net2	

[root@server1 ~]# docker network ls
3911c5c34448        my_net2             bridge              local

[root@server1 ~]# docker run  -it --name vm1 --network my_net2 busybox
/ # ip addr #使用my_net2运行后就会被分配到一个172.25.0网段的ip
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
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:19:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.25.0.2/24 brd 172.25.0.255 scope global eth0
       valid_lft forever preferred_lft forever

给运行的容器自定义ip

使用--ip参数自定义ip
[root@server1 docker run  -it --name vm2 --network my_net2 --ip 172.25.0.100 busybox
/ # ip a
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
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:19:00:64 brd ff:ff:ff:ff:ff:ff
    inet 172.25.0.100/24 brd 172.25.0.255 scope global eth0
       valid_lft forever preferred_lft forever

但是这个网段的桥接网络和docker0就不可以通信,桥接在不同网桥上的容器,彼此之间不能通信

docker网桥通信

在火墙里查看规则,可以看到规定了这些docker的桥接网络都是将发送的信息drop,所以互相不能通信

[root@server1 ~]# iptables -S

-A DOCKER-ISOLATION-STAGE-2 -o br-3911c5c34448 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-790a524e3bfe -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP

如何让不同的网桥互相通信呢?
开启vm1和vm2两个容器,vm1使用my_net1网络,vm2使用my_net2网络,然后将两个容器都放入后台运行

先给vm1上再桥接一个my_net2的网络
[root@server1 ~]# docker network connect my_net2 vm1
[root@server1 ~]# docker container attach vm1	#进入vm1
/ # ip a	#可以看到有两个网络ip
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
16: eth1@if17: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:19:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.25.0.2/24 brd 172.25.0.255 scope global eth1
       valid_lft forever preferred_lft forever

/ # ping vm2 #可以通信vm2,并且自带dns解析
PING 172.25.0.100 (172.25.0.100): 56 data bytes
64 bytes from 172.25.0.100: seq=0 ttl=64 time=0.076 ms
容器间的通信

如果不知道容器的ip,当处于统一网络下是,可以直接ping容器名进行通信,因为docker 在 1.10 以后,都会内嵌一个 DNS server,帮你解析容器的ip。

另一种一种方式是joined 方式,容器之间共享网络。类似host模式

运行vm1,然后放入后台
[root@server1 ~]# docker run -it --name vm1 --network my_net1 busybox

再运行vm2并将入vm1共享vm1的网络
[root@server1 ~]# docker run -it --name vm2 --network container:vm1 busybox
/ # ip a
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
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
/ # ping vm1
PING vm1 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.035 ms

这样两个容器之间可以使用 localhost(回环接口)进行快速通信,适用于 web 服务器和应用服务器。

还有一种方法使用–link 来链接两个容器:

开启一台容器
[root@server1 ~]# docker run -it --name vm1 busybox
/ # [root@server1 ~]# 	#放入后台

开启另一台容器,使用--link连接到vm1上,就可以通信了
[root@server1 ~]# docker run -it --name vm2 --link vm1 busybox
/ # ping vm1
PING vm1 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.081 ms

这样可以通信的原因是

1.容器里添加了解析
/ # cat /etc/hosts
172.17.0.3	vm1 87606680db28

2.环境变量里设置了相应的地址和 ip
/ # env
VM1_NAME=/vm1/web
VM1_PORT_80_TCP_PROTO=tcp
VM1_PORT_80_TCP_ADDR=172.17.0.3
LESSOPEN=| /usr/bin/lesspipe %s
VM1_PORT=tcp://172.17.0.2:80

如果这时我们先停止vm1,再去运行另一个容器,使vm1本来的ip本占领,再去开启vm1会发生什么?

[root@server1 ~]# docker stop vm1
[root@server1 ~]# docker run -d --name nginx nginx
[root@server1 ~]# docker start vm1
[root@server1 ~]# docker container attach vm2
/ # cat /etc/hosts
172.17.0.5	vm1 87606680db28	#原本的172.17.0.3变成了172.17.0.5,
172.17.0.4	42fb8ddc7b25

这是因为ie容器被停止后它所占用的资源也会被释放出来,并且还是可以连接外网的

/ # ping www.baidu.com
PING www.baidu.com (39.156.66.14): 56 data bytes
64 bytes from 39.156.66.14: seq=0 ttl=50 time=60.252 ms

这是因为容器访问外网是通过 iptables 的 SNAT 实现的,容器和 docker0 是桥接的方式,docker0 是容器的网关,到达 docker0 后,通过 linux 内核的路由功能(ip_forward),然后防火墙会做伪装,也就是 SNAT,然后通过物理网卡接口到外网,在iptable策略里也可以看出来,所有创立的docker桥接网络都会进行地址伪装和外界通信

[root@server1 ~]# iptables -t nat -S
-A POSTROUTING -s 172.25.0.0/24 ! -o br-3911c5c34448 -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o br-790a524e3bfe -j MASQUERADE
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
[root@server1 ~]# docker network prune 	#删除掉没有使用的网络
外网访问容器

开启容器进行端口映射

做端口映射(冒号后的是容器内部的端口,前是宿主机端口)
[root@server1 ~]# docker run -d --name vm1 -p 80:80 nginx

[root@server1 ~]# docker port vm1	#查看vm1开启的端口
80/tcp -> 0.0.0.0:80

[root@server1 ~]# iptables -t nat -S	#查看火墙策略
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.17.0.3:80

外部主机访问时,首先通过宿主机的网卡ip的80端口(172.25.254.1:80),再到DNAT, 最后访问到172.17.0.3(容器ip地址)
测试访问宿主机的网络域名可以看到nginx

[root@server1 ~]# curl 172.25.254.1
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>

[root@server1 ~]# netstat -ntlp	#并且可以看到本机上的80端口是docker-proxy开启的
tcp6       0      0 :::80                   :::*                    LISTEN      14287/docker-proxy  

每当运行一个映射端口的容器,就会开启一个 docker-proxy 进程

[root@server1 ~]# docker run -d --name vm2 -p 8080:80 nginx
[root@server1 ~]# netstat -ntlp
tcp6       0      0 :::8080                 :::*                    LISTEN      14545/docker-proxy  

[root@server1 ~]# ps ax |grep docker-proxy
14287 ?        Sl     0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 80 -container-ip 172.17.0.3 -container-port 80
14545 ?        Sl     0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 8080 -container-ip 172.17.0.4 -container-port 80

宿主机访问本机容器使用 iptables 的 DNAT,外部主机访问容器或者容器之间访问是docker-proxy 实现的。
访问的过程就是:外部主机 --> 宿主机的网卡eth0 --> 通过 docker-proxy --> docker的ip上 --> 容器里。

跨主机网络

docker的原生网络有两种方案:overly、macvlan
第三方的方案:flannel、weave、calico

这些方案通过libnetwork(docker容器网络库)里的CNM(Container Network Model)这个核心,它对容器网络进行抽象;

CNM 由 3 部分组成:

  1. Sandbox:容器的网络栈。包含容器的 interface、路由表和 DNS 等
  2. Endpoint:作用是将 Sandbox 接入 Network。(veth pair,虚拟网络对,相当于网线的两端)
  3. Network:包含一组 Endpoint,同一 Network 的 Endpoint 可以直接通信

这里来主要分一下macvlan网络方案的实现,macvlan使用的是linux内核虚拟化技术,不需要桥接网络,直接使用物理接口,性能极好
开启另一台虚拟机server2,清空server1上开启的容器并清除自定义的网络。
对server1和server2在虚拟机配置里各添加一块虚拟网卡
然后都打开网卡的混杂模式

[root@server1 ~]# ip link set up eth1 
[root@server1 ~]# ip link set eth1 promisc on

[root@server2 ~]# ip link set up eth1
[root@server2 ~]# ip link set eth1 promisc on

创建 macvlan 网络模型
在两台主机上都创建

[root@server1 ~]# docker network create -d macvlan --subnet 172.25.0.0/24 --gateway 172.25.0.1 -oparent=eth1 macvlan1
#-o parent 一定要加,因为macvlan 模型不走桥接,直接走物理接口,所以需要指定
[root@server2 ~]# docker network create -d macvlan --subnet 172.25.0.0/24 --gateway 172.25.0.1 -oparent=eth1 macvlan1
[root@server1 ~]# docker run -it --name vm1 --network macvlan1 --ip 172.25.0.10 busybox
#运行容器,macvlan 模型这里必须手动指定 ip 地址,如果不指定会自动分配,单调递增,可能会冲突

[root@server2 ~]# docker run -it --name vm2 --network macvlan1 --ip 172.25.0.11 busybox

容器接口直接与主机网卡相连,无需 NAT 或端口映射

可以查看桥接信息看到开启的容器接口没有桥接信息
[root@server1 ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.024274da362a	no		veth2ec124e

如果有很多的容器需要设置网络ip 的话,可以使用 vlan 子接口实现多 macvlan 网络,vlan 可以将物理二层网络划分为 4094 个逻辑网络,彼此隔离,取值为 1~4094。

[root@server1 ~]# docker network create -d macvlan  --subnet 172.26.0.0/24 --gateway 172.26.0.1 -o parent=eth1.1 macvlan2
[root@server2 ~]# docker network create -d macvlan  --subnet 172.26.0.0/24 --gateway 172.26.0.1 -o parent=eth1.1 macvlan2

[root@server2 ~]# ip addr #查看到创建的子接口
eth1.1@eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 52:54:00:f6:99:65 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::5054:ff:fef6:9965/64 scope link 
       valid_lft forever preferred_lft forever

使用子接口网络开启两个容器,也是可以相互ping通的

[root@server1 ~]# docker run -it --name vm3 --network macvlan2 --ip 172.26.0.10 busybox

[root@server2 ~]# docker run -it --name vm4 --network macvlan2 --ip 172.26.0.11 busybox

macvlan 网络在二层是隔离的,所以不同 macvlan 容器不能通信,可以在三层通过网关连接(加路由),docker 本身不做任何限制,像传统 vlan 那样管理即可。网络选型时如果对网络比较熟悉,选 macvlan 较好,因为只需要把网络设备调整好,docker 方面基本不用做什么调整

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Howei__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值