目录 Docker网络大揭秘 一、计算机网络模型 二、Linux中网卡 1. 查看网卡[网络接口] 信息解读 配置文件 给网卡添加ip地址 网卡的启动与关闭 Network Namespace namespace实战 Container的NS 深入分析container网络-Bridge docker0默认Bridge 创建自己的network 深入分析Container网络-Host&None Host None 端口映射及折腾 端口映射 折腾
Docker网络大揭秘
Docker网络官方
一、计算机网络模型
二、Linux中网卡 1. 查看网卡[网络接口] 1 2 3 4 查看网卡得三种的方式: ip link show (所有网卡,不包含ip信息) ls /sys/class/net (仅显示网卡名) ip a (所有网卡的全部信息)
信息解读
信息说明:lo为本地网卡,eth0为本机与互联网通信的网卡,eth1为本机与宿主机通信的网卡
网卡状态类型:UP/DOWN/UNKOWN
Mac地址:link/ether
绑定的IP:inet
配置文件 1 2 在Linux中网卡对应的起始就是文件,所以找到对应的网卡文件即可。 比如:cat /etc/sysconfig/network-scripts/ifcfg-eth0
给网卡添加ip地址
当然,这块可以直接修改ifcfg-*文件,但是我们通过命令添加实施
1 2 ip addr add 192.168.0.100/24 dev eth0 //添加ip地址 ip addr delete 191.168.0.100/24 dev eth0 //删除ip地址
网卡的启动与关闭 1 2 3 重启网卡: service network restart / systemctl restart network 启动/关闭某个网卡:ifup/ifdown eth0 ip link set eth0 up/down
Network Namespace
在Linux上,网络的隔离是通过network namespace来管理的,不同的network namespace是相互隔离的
ip netns list: 查看当前机器上的network namespace
network namespace的管理
ip netns list //查看
ip netns add ns // 添加
ip netns delete ns1 //删除
namespace实战 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 创建一个network namespace ip netns add ns1 查看该namespace下网卡的情况 ip netns exec ns1 ip a 启动ns1上的lo网卡 ip netns exec ns1 ifup lo ip netns exec ns1 ip link set lo up 再次查看,可以发现state编程了UNKOWN ip netns exec ns ip a 再次创建一个network namespace ip netns add ns2
1 2 此时想让连个namespace网络连通起来,使用veth-pair技术 veth pair: Virtual Ethernet Pair,是一个成对的端口,可以实现上述功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 创建一对link, 也就是接下来要通过veth pair链接link ip link add veth-ns1 type veth peer name veth-ns2 查看link情况 ip link 将veth-ns1 加入ns1中,将veth-ns2加入ns2中 ip link set veth-ns1 netns ns1 ip link set veth-ns2 netns ns2 查看宿主机和ns1,ns2的link情况 ip link ip netns exec ns1 ip link ip netns exec ns2 ip link 此时veht-ns1和veth-ns2还没有ip地址,显然通信还缺少点条件 ip netns exec ns1 ip addr add 192.168.0.11/24 dev veth-ns1 ip netns exec ns2 ip addr add 192.168.0.12/24 dev veth-ns2 再次查看,发现state是DOWN, 并且还是没有IP地址 ip netns exec ns1 ip link ip netns exec ns2 ip link 启动veth-ns1和veth-ns2 ip netns exec ns1 ip link set veth-ns1 up ip netns exec ns2 ip link set veth-ns2 up 再次查看,发现state是UP,同时有IP ip netns exec ns1 ip a ip netns exec ns2 ip a 此时两个network namespace互相ping以下,发现是可以ping通的 ip netns exec ns1 ping 192.168.0.12 ip netns exec ns2 ping 192.168.0.11
Container的NS
按照上面的描述,实际上每个container,都会有自己的network namespace,并且是独立的,我们可以进入到容器中进行验证。
1 2 3 4 5 6 7 8 9 10 不妨创建两个container看看 docker run -d --name tomcat01 -p 8081:8080 tomcat docker run -d --name tomcat02 -p 8082:8080 tomcat 进入到两个容器中,并且查看ip docker exec -it tomcat01 ip a docker exec -it tomcat01 ip a 互相ping以下是可以ping通的 值得我们思考的是,此时tomcat01和tomcat02属于两个network namespace,是如何能够ping通的?有些小火炮可能回想,不就跟上面的namespace实战一样吗?注意这里并没有veth-pair技术
深入分析container网络-Bridge docker0默认Bridge 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 查看centos的网络:ip a,可以发现 4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:43:7b:1b:bd 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:43ff:fe7b:1bbd/64 scope link valid_lft forever preferred_lft forever 8: veth3b72761@if7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 22:a3:13:4d:7f:29 brd ff:ff:ff:ff:ff:ff link-netnsid 2 inet6 fe80::20a3:13ff:fe4d:7f29/64 scope link valid_lft forever preferred_lft forever 查看容器tomcat01的网络:docker exec -it tomcat01 ip a,可以发现 [root@bogon ~]# docker exec -it tomcat01 ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0 valid_lft forever preferred_lft forever 在centos中ping以下tomcat01的网络,发现可以ping通 ping 172.17.0.2 [root@bogon ~]# ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.120 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.060 ms 64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.056 ms 既然可以ping通,而且centos和tomcat1又属于不同的network namespace,是怎么连接的? 很显然,跟之前的实战是一样的。 也就是说,在tomcat01中有一个eth0和centos的docker0中有一个veth3是成对的,类似于之前实战中的veth-ns1和veth-ns2,不妨再通过一个命令确认下:brctl 安装一下:yum install bridge-utils brctl show 那么为什么tomcat01和tomcat02能ping通呢?不多说,直接上图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 这种网络连接方法我们称之为Bridge,起始也可以通过命令查看docker中的网络模式:docker network is bridge也是docker中默认的网路模式 不妨检查以下bridge:docker network inspect bridge "Containers": { "6ad312b32f62b48935f3c95c58ae061df710bfebbd3d721b467507b9516eeb81": { "Name": "tomcat02", "EndpointID": "aa9c612c79f867e874d0cae1aab45374373b61e9cdbe79925d07ae2e89a1cca0", "MacAddress": "02:42:ac:11:00:03", "IPv4Address": "172.17.0.3/16", "IPv6Address": "" }, "f49fc396d8e04f2b330163d91bb5d1482715202b4e2fd0c7f42833722787742a": { "Name": "tomcat01", "EndpointID": "c5440b063e8fc0c9c44f3f61bf68f577283417eb23cfa9a361d37973d01a8ba5", "MacAddress": "02:42:ac:11:00:02", "IPv4Address": "172.17.0.2/16", "IPv6Address": "" } } 在tomcat01容器中可以访问互联网的,顺便把这张图画一下,NAT是通过iptables实现的。
创建自己的network 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 创建爱你一个network,类型为bridge docker network create tomcat-net or docker network create --subnet=172.18.0.0/24 tomcat-net 查看已有的network:docker network ls NETWORK ID NAME DRIVER SCOPE d90c3e7f2fb7 bridge bridge local 0bf771565d91 host host local 67a3ef88b178 none null local 查看tomcat-net详情信息:docker network inspect tomcat-net 创建tomcat的容器,并且制定使用tocmat-net docker run -d --name custom-net-tomcat --network tomcat-cat tomcat 查看custom-net-tomcat的网络信息 docker exec -it custom-net-tomcat ip a 查看网卡信息 ip a 查看网卡接口 brctl show bridge name bridge id STP enabled interfaces br-3012e3afd264 8000.02429780e75d no vethf223a4b docker0 8000.0242437b1bbd no veth3b72761 此时在custom-net-tomcat容器中ping一下tomcat01的ip会如何?发现无法ping通 docker exec -it custom-net-tomcat ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. ^C --- 172.17.0.2 ping statistics --- 4 packets transmitted, 0 received, 100% packet loss, time 3000ms 查看tomcat-net网络,可以发现tomcat01这个容器也在其中 此时进入到tomcat01或者custom-net-tomcat中,不仅可以通过ip地址ping通,而且可以通过名字ping到,这时候因为都链接到了用户自定义的tomcat-net bridge上 docker exec -it tomcat01 bash
深入分析Container网络-Host&None Host 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 创建一个tomcat容器,并且制定网络为none docker run -d --name my-tomcat-host --network host tomcat 查看ip地址 docker exec -it my-tomcat-host ip a 可以发现和centos是一样 检查host网络 "Containers": { "e1f00d47db344b6688e99c0f5b393e232309fbe1a4d9c3fc3e1ce7c107f3312d": { "Name": "my-tomcat-host", "EndpointID": "f08456d9dca024cf6f911f8d32329ba2587ea89554c96b77c32698ace6998525", "MacAddress": "", "IPv4Address": "", "IPv6Address": "" } }
None 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 创建一个tomcat容器,并且制定网络为none docker run -d --name my-tomcat-none --network none tomcat 查看ip地址 docker exec -it my-tomcat-none ip a 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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 检查none网络 "Containers": { "bb3f0db4fa76a25b5377da9c3bbf087ac7ef0de0a3f9c37a4ae959983d33105c": { "Name": "my-tomcat-none", "EndpointID": "26055c08c968f9d6d03d10b3b66dfea004c35f5d2bd4067a2306566973e92f9e", "MacAddress": "", "IPv4Address": "", "IPv6Address": "" } }
端口映射及折腾 端口映射 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 创建一个tomcat容器,名称为port-tomcat docker run -d --name port-tomcat tomcat 思考一下要访问该tomcat怎么做?肯定是通过ip:port方式 docker exec -it port-tomcat bash curl localhost:8080 那如果要在centos7上访问呢? docker exec -it port-tomcat ip a ---->得到其ip地址,比如172.17.0.4 curl 172.17.0.4:8080 小结:之所以能访问成功,是因为centos上的docker0链接port-tomcat的network namespace 那如果要在centos7通过curl localhost方式访问呢?显然就压瓯江port-tomcat的8080端口映射到centos上 docker rm -f port-tomcat docker run -d --name port-tomcat -p 8090:8080 tomcat curl localhost:8090
折腾 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 centos7是运行在win10的虚拟机,如果想要在win10上通过ip:port方式访问呢? 此时需要cetnos和win10网络在同一个网段,所以在Vagrantfile文件中 这种方式等同于桥接网络,也可以给该网络指定使用物理机哪一块网卡,比如 #config.vm.network"public_network",:bridge==>‘en1:Wi-Fi(AirPort)’ config.vm.network"public_network" centos7:ip a ----->192.168.8.118 win10:浏览器访问 192.168.8.118:9080 如果也想把centos7上的8090映射到win10的某个端口呢?然后浏览器访问localhost:port 此时需要将centos7上的端口和win10上的端口做映射 config.vm.network"forwarded_port",guest:8090,host:8009 记得vagrant reload生效一下 win10:浏览器访问 localhost:8098