暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

K8S:基础篇之Docker(Docker Network篇)

原创 清酒和歌 2020-08-14
1984

概述

这是一个Kubernetes系列文章,主要将我所学过,所使用过的经验、使用方法等记录在此。将会持续更新。
Docker中共有四种网络模式,根据环境,选择自己适合的网络模式。Docker默认选择的是Bridge模式。

介绍

Bridge模式

首先,我们用命令来查看一下当前已有的Docker网络模式:

[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE a7336e98946f bridge bridge local 6472a50c6393 host host local 121cb88b53e3 none null local [root@localhost ~]#
复制

可以看到,在Docker安装之后,默认就会有这三种模式,分别是:Bridge、Host、None。另外还有一种模式,是比较特别的Container模式,这个会在后面讲到,这里先关注Bridge模式。
在Docker进程启动时,默认会在主机上创建一个名为docker0的虚拟网桥:

[root@localhost ~]# ifconfig docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:83ff:fe2c:6758 prefixlen 64 scopeid 0x20<link> ether 02:42:83:2c:67:58 txqueuelen 0 (Ethernet) RX packets 7798 bytes 372151 (363.4 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8806 bytes 135618786 (129.3 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
复制

此后、在此主机上启动的所有Docker容器会默认连接到这个虚拟网桥上。
虚拟网桥的工作方式与交换机类似,主机上的所有Docker容器通过交换机连接到一个二层网络中,从docker0的子网中,分配出一个IP给容器使用,并将docker0的IP地址设置为容器的默认网关,这样,每个容器之间就可以相互通信。
在容器启动时,会在主机上创建一个名称叫veth开头的虚拟网卡,Docker将这个网卡的一端放到新创建的容器当中,并且在新创建的容器中,创建一个命名为eth0的网卡。另一端放到主机上,叫做以veth开头的名字,并将这个网络设备加入到docker0的网桥中。
网络拓补图示例:
image.png
Docker在运行容器时,默认会把容器的网络模式绑定到Bridge模式上,我们来演示一下:
image.png
可以看到,我现在的主机上只有四个网卡:br*、docker0、ens33、lo,现在,让我们启动一个docker容器,不显示指定网络模式,看看是否可以对应上那个网络拓补图:

[root@localhost ~]# docker run -itd nginx:v1 a80418ee697dcb827ffaff771581c0d28b00ec6b799c34624b1acc99d74d1bf7 [root@localhost ~]#
复制

image.png
多了一个veth开头的虚拟网卡,现在让我们来进入容器内部查看容器内的网卡:

[root@localhost ~]# docker exec -it a80418ee697d /bin/bash [root@a80418ee697d /]# 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 4343: eth0@if4344: <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 [root@a80418ee697d /]# [root@a80418ee697d /]# route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 172.17.0.1 0.0.0.0 UG 0 0 0 eth0 172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 eth0 [root@a80418ee697d /]#
复制

通过路由表看到,发送的数据都发送到了172.17.0.1的网关,对应到主机上的docker0虚拟网卡。

Host模式

这种模式下,容器将会和宿主机共用一个Network Namespace,不会有自己独立的Network Namespace。容器不会虚拟出自己的网卡,也不会有单独的IP等,而是使用宿主机的网卡。换而言之,除了网络之外,文件系统、进程空间等还是与宿主机隔离的。
网络拓补图如下:
image.png
现在,让我们来演示一下,以host模式启动两个容器:

[root@localhost ~]# docker run -it --net=host --name nginx -d nginx:v1 de41a1af0f5dfc06354cb48b02059ecb580bf079e9e752d6aca721c6b08d27e0 [root@localhost ~]# docker run -it --net=host --name tomcat -d tomcat 72d8b6bf9ed6b75d2d1f24791f89d25ccbe7fd36f65efd3a0127ee516ff6576a [root@localhost ~]# ifconfig br-b6e2c93e6f81: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.18.0.1 netmask 255.255.0.0 broadcast 172.18.255.255 inet6 fe80::42:f1ff:fe81:31b6 prefixlen 64 scopeid 0x20<link> ether 02:42:f1:81:31:b6 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:83ff:fe2c:6758 prefixlen 64 scopeid 0x20<link> ether 02:42:83:2c:67:58 txqueuelen 0 (Ethernet) RX packets 7988 bytes 380292 (371.3 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 9051 bytes 135964484 (129.6 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.16.150.133 netmask 255.255.255.0 broadcast 172.16.150.255 inet6 fe80::b261:851b:b79:b6c6 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:5a:08:25 txqueuelen 1000 (Ethernet) RX packets 1458873 bytes 1919983181 (1.7 GiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 447439 bytes 248363596 (236.8 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1000 (Local Loopback) RX packets 208420 bytes 131887610 (125.7 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 208420 bytes 131887610 (125.7 MiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 [root@localhost ~]# [root@localhost ~]# netstat -lntup Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 51075/nginx: master tcp 0 0 0.0.0.0:20019 0.0.0.0:* LISTEN 7107/mongod tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1006/sshd tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1430/master tcp 0 0 0.0.0.0:514 0.0.0.0:* LISTEN 79057/rsyslogd tcp6 0 0 127.0.0.1:8005 :::* LISTEN 51285/java tcp6 0 0 :::3307 :::* LISTEN 3958/mysqld tcp6 0 0 :::8080 :::* LISTEN 51285/java tcp6 0 0 :::80 :::* LISTEN 51075/nginx: master tcp6 0 0 :::22 :::* LISTEN 1006/sshd tcp6 0 0 ::1:25 :::* LISTEN 1430/master tcp6 0 0 :::514 :::* LISTEN 79057/rsyslogd udp 0 0 0.0.0.0:68 0.0.0.0:* 92584/dhclient udp 0 0 127.0.0.1:323 0.0.0.0:* 659/chronyd udp6 0 0 ::1:323 :::* 659/chronyd [root@localhost ~]#
复制

启动两个hast模式的容器后,主机上的虚拟网卡并不会增加或减少,并且在宿主机上,出现了两个全新的端口:80和8080,分别对应到两个容器:nginx和tomcat默认端口,现在,进入Nginx容器内部查看:

[root@localhost ~]# docker exec -it 90364f9a34e5 /bin/bash [root@localhost /]# 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:5a:08:25 brd ff:ff:ff:ff:ff:ff inet 172.16.150.133/24 brd 172.16.150.255 scope global dynamic noprefixroute ens33 valid_lft 1526sec preferred_lft 1526sec inet6 fe80::b261:851b:b79:b6c6/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:83:2c:67:58 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:83ff:fe2c:6758/64 scope link valid_lft forever preferred_lft forever 50: br-b6e2c93e6f81: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:f1:81:31:b6 brd ff:ff:ff:ff:ff:ff inet 172.18.0.1/16 brd 172.18.255.255 scope global br-b6e2c93e6f81 valid_lft forever preferred_lft forever inet6 fe80::42:f1ff:fe81:31b6/64 scope link valid_lft forever preferred_lft forever [root@localhost /]# exit exit [root@localhost ~]#
复制

然后再进入tomcat容器内查看:

[root@localhost ~]# docker exec -it 0b8a3d00f6f1 /bin/bash root@localhost:/usr/local/tomcat# 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 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:5a:08:25 brd ff:ff:ff:ff:ff:ff inet 172.16.150.133/24 brd 172.16.150.255 scope global dynamic noprefixroute ens33 valid_lft 1465sec preferred_lft 1465sec inet6 fe80::b261:851b:b79:b6c6/64 scope link noprefixroute valid_lft forever preferred_lft forever 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:83:2c:67:58 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:83ff:fe2c:6758/64 scope link valid_lft forever preferred_lft forever 50: br-b6e2c93e6f81: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:f1:81:31:b6 brd ff:ff:ff:ff:ff:ff inet 172.18.0.1/16 brd 172.18.255.255 scope global br-b6e2c93e6f81 valid_lft forever preferred_lft forever inet6 fe80::42:f1ff:fe81:31b6/64 scope link valid_lft forever preferred_lft forever root@localhost:/usr/local/tomcat# exit exit [root@localhost ~]#
复制

可以看到,容器内的网络,完全使用了宿主机的网络,这和刚才的描述完全相同。

None模式

none模式在使用时,Docker容器会拥有自己独立的Network Namespace,但是,并不会为Docker容器进行任何网络配置。也就是说,容器内没有网卡等信息,需要自己手动配置网卡信息。
网络拓补图示例:
image.png
现在,启动一个网络模式为none的容器,然后进入内部查看网卡:

[root@localhost ~]# docker run -it --net=none --name nginx -d nginx:v1 47b1690fb96050d51cbb69360b36367a04aed22c14ada4e2e9e32abe9e66dab2 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 47b1690fb960 nginx:v1 "/usr/sbin/nginx -g …" 3 seconds ago Up 2 seconds nginx [root@localhost ~]# docker exec -it 47b1690fb960 /bin/bash [root@47b1690fb960 /]# 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 [root@47b1690fb960 /]# cat /etc/sysconfig/network-scripts/ifcfg-ens3 # Generated by dracut initrd NAME="ens3" DEVICE="ens3" ONBOOT="yes" NETBOOT="yes" UUID="82eebe16-4fc7-4de7-aff9-dafc78e97773" IPV6INIT="yes" BOOTPROTO="dhcp" TYPE="Ethernet" PROXY_METHOD="none" BROWSER_ONLY="no" DEFROUTE="yes" IPV4_FAILURE_FATAL="no" IPV6_AUTOCONF="yes" IPV6_DEFROUTE="yes" IPV6_FAILURE_FATAL="no" [root@47b1690fb960 /]# exit exit [root@localhost ~]#
复制

这里的网卡信息需要自己配置。

Container模式

Container模式没有在docker network ls中体现,这也是Docker的一种网络模式。
这种模式下,需要指定新创建的容器和已有容器共享一个Network Namespace,而不是共享宿主机的网络信息。
新创建的容器不会有自己的网卡,也不会有自己独立的IP,而是和指定的容器共享网卡信息,IP、端口等。
两个容器,除网络方面,其他都是完全独立存在的,两个容器可以通过lo网卡进行通信,全部指向localhost。
Container模式示意图:
image.png
首先启动一个容器:nginx,网络模式为Bridge,然后启动一个新容器:tomcat,执行tomcat的网络模式为container,并且和nginx共用网络:

[root@localhost ~]# docker run -it --name nginx -d nginx:v1 cc9813ead22b8f055140d5f3fe7316e99ed1c59461dc0af0b0e629edbe7a0aa1 [root@localhost ~]# docker run -it --net=container:nginx --name tomcat -d tomcat 02ca200c8e88552aeb9e4cf50868764882e2857847ef6435ae2acf9e8e279758 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 02ca200c8e88 tomcat "catalina.sh run" 3 seconds ago Up 2 seconds tomcat cc9813ead22b nginx:v1 "/usr/sbin/nginx -g …" 10 seconds ago Up 9 seconds nginx ---查看nginx的网卡 [root@localhost ~]# docker exec -it cc9813ead22b /bin/bash [root@cc9813ead22b /]# 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 4345: eth0@if4346: <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 [root@cc9813ead22b /]# exit exit ---查看tomcat容器的网卡 [root@localhost ~]# docker exec -it 02ca200c8e88 /bin/bash root@cc9813ead22b:/usr/local/tomcat# 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 4345: eth0@if4346: <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 root@cc9813ead22b:/usr/local/tomcat# exit exit [root@localhost ~]#
复制

从上面可以看出,新建的tomcat容器确实使用了nginx容器的网卡,网卡名称都为eth0@if4346,IP也是相同的。

docker内网络互通

上面介绍了docker的四种网络模式,最常用的是Bridge模式,这也是默认模式。
以前想要将两个或多个容器网络想通,需要使用–link参数,这也会导致容器体积越来越大。
现在,我们可以通过docker network命令,创建一个属于自己自定义的网络,然后让需要相互通信的容器加入到这个自定义网络中。现在来介绍一下使用方法:

[root@localhost ~]# docker network --help Usage: docker network COMMAND Manage networks Commands: connect Connect a container to a network create Create a network disconnect Disconnect a container from a network inspect Display detailed information on one or more networks ls List networks prune Remove all unused networks rm Remove one or more networks Run 'docker network COMMAND --help' for more information on a command. [root@localhost ~]# [root@localhost ~]# docker network create -d bridge my-net 0da9ae43e44455a8460197809b656394b530937522984ef4ce42f9f693497d27 [root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE a7336e98946f bridge bridge local b6e2c93e6f81 harbor_harbor bridge local 6472a50c6393 host host local 0da9ae43e444 my-net bridge local 121cb88b53e3 none null local [root@localhost ~]#
复制

这里我们创建了一个名字叫做my-net的网络,网络模式为Bridge,在以后新建容器,都可以使用–net=my-net加入到这个网络当中,实现容器间的相互通信。
当然,容器间的相互通信也不止这一种,还有一种更为整体的方法,就是docker swarm集群模式,这个我会在后篇中讲述。
至此,Docker网络篇结束。

最后修改时间:2020-08-15 10:08:11
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论

目录
  • 概述
  • 介绍
    • Bridge模式
    • Host模式
    • None模式
    • Container模式
  • docker内网络互通