上篇文章讲述了有关docker的资源控制,主要是三个方面:CPU、内存以及IO。本文将讲述docker的4中网络模式。docker
可能,对于许多接触Linux操做系统的朋友而言,起初都是经过虚拟机软件进行层层深刻的学习。而对于其中一种软件——VMware软件的网络链接可能就是初学者的一个难题。可能一直都并不了解所提供的三种网络模式的原理和意义。那么本小节将简单讲述一下有关VMware的三种网络模式:Bridged(桥接模式)、NAT(网络地址转换模式)、Host-Only(仅主机模式)。而此三种分别对应于网卡设备中的VMnet0、VMnet1(或者后期新增建立的)、VMnet8(NAT网卡也只能有一个)shell
概念:桥接模式就是一种将主机(比如是你的笔记本上的)的网卡与虚拟机的网卡利用虚拟网桥进行通讯。centos
原理理解:对这种模式的理解能够认为是将物理机虚拟为一个交换机,全部桥接设置的虚拟机链接到这个交换机的一个接口上,固然物理机也同样须要链接到这个交换机,也就是说桥接模式下的全部网卡都是交换模式,相互能够访问并且互不干扰。bash
典型特征:虚拟机的IP地址须要与主机在同一网段,若是须要联网则网关与DNS须要与主机网卡一致。服务器
具体能够再经过下面的图示理解:网络
NAT模式的话相对来讲应该是最熟悉的了。网络地址转换,既然有地址转换,确定是发生了转变了。NAT模式就比较适合于IP资源紧缺,并且但愿虚拟机能够联网的状况。ide
NAT模式借助的是虚拟的NAT设备以及虚拟的DHCP服务器,从而使得虚拟机能够联网。以下图所示:oop
仅主机模式呢,其实说白了就是没有NAT设备的网络模式,仅使用的是VMnet1虚拟网卡与虚拟交换机链接,从而与虚拟机通讯,而这种模式就实现了虚拟机与外网的隔离,即独立的一台服务器,只与主机互相通讯。以下图所示:性能
好的,如今大概了解了VMware中三种网络模式的原理了吧,如今继续来聊聊在docker中的网络模式。学习
docker使用Linux桥接的方式,即在宿主机虚拟一个docker容器网桥(docker0),docker启动一个 容器时会根据docker网桥的网段分配给容器一个IP地址,这个地址就是容器ip,同时docker就是每一个容器的默认网关。所以,同一个宿主机内的容器就能够经过容器ip地址直接通讯。
通常状况下,咱们在安装和启动docker服务以后使用ifconfig命令便可查看到这个docker0的虚拟网桥设备:
[root@localhost ~]# ifconfig | head -7 docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:58:71:c9:ba 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
从上面显示的结果来看,默认的容器网关地址为172.17.0.1/16哈!固然loopback网卡是回环网卡,测试验证(TCP/IP链接),virtual bridge则是虚拟网桥(想一想KVM【云原生】)
固然,docker网桥是宿主机虚拟出来的,并非真实存在的网络设备,外部网络是没法经过ip地址直接寻址的,这就代表咱们须要经过其余的方式来使外部网络能够访问容器,通常会经过访问宿主机ip结合容器的端口(而且端口通常是进行了端口映射,以后会讲述)进行容器的访问。
下面直接经过下面的表格来区分理解一下docker的四种网络模式
docker网络模式 | 配置 | 说明 |
---|---|---|
host | 容器和宿主机共享Network namespace | |
container模式 | 容器和另一个容器共享Network namespace | |
none模式 | 容器有独立的Network namespace,但并无对其进行任何网络设置,如分配veth pair 和网桥链接,配置IP等 | |
bridge模式 | 默认的模式 |
其实启动docker服务以后,可使用docker network相关命令控制管理网络,下面咱们查看一下网络列表:(默认存在下面三个)下面逐一介绍(结合第一小节的内容来理解docker 中的网络原理)
[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 3763f78eb404 bridge bridge local 3bb2f50eb211 host host local e12cd7b98c54 none null local
host模式结合VMware中的仅主机模式便可理解,经过下图表示一下:
从上图能够看出,若是在启动容器后使用的是host模式,那么这个容器将不会得到一个独立的Network Namespace(网络命名空间),而是和宿主机系统共用一个Network Namespace。而且这就意味着容器将不会虚拟出本身的网卡以及配置本身的ip等,而是使用宿主机的ip以及端口。不过呢,在其余方面例如文件系统等仍是与之隔离的。
这种方式最大优点在于网络性能比较好可是缺点也很明显——网络的隔离性很弱。
这个模式正如上述表格中的说明通常,是表示指定新建立的容器和已经存在的一个容器共享一个Network Namespace。固然这也表示新建的这个容器不会建立本身的网卡等相关操做,而是和与指定的容器共享这些资源。
这种模式也和上述的host差很少,除了网络方面,其文件系统、进程列表等都是隔离的。
参照下图:
使用none模式,Docker容器拥有本身的Network Namespace,可是,不会对Docker容器进行任何的网络配置。这就代表这个Docker容器没有网卡、IP、路由等信息。须要咱们本身为Docker容器添加网卡、配置IP等。这种方式网络的隔离性最为完全,即代表关闭了容器的网络功能,也没法访问这个容器。
示意图以下:
该模式就是咱们在启动docker服务后默认的docker网络模式,其会在主机上建立一个名为docker0的虚拟网桥,这个主机上的全部启动的容器就会链接到这个虚拟网桥上。结合VMware中网桥模式原理,想一想物理交换机的原理,就不难理解了。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上建立一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新建立的容器中(这个veth对咱们在OpenStack中见过,笔者以为能够将之理解为一个桥梁,创建桥两岸的关系而存在的一种虚拟设备),并命名为eth0(容器的网卡),另外一端放在主机中,以vethxxx这样相似的名字命名,并将这个网络设备加入到docker0网桥中。
使用docker run -p 命令时,docker实际是在防火墙作了DNAT规则,实现端口转发的功能。
下面经过一个节点的服务器结构图来理解:
固然,这四种模式都不须要手动配置,真正须要配置的是自定义网络。
上面已经给出了对应docker网络控制的命令docker network,下面具体看一下这个命令的具体说明:
docker network的命令用法: 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
咱们经过尝试、排错和验证的方式来配置docker网络。
由于须要NAT地址转换功能,因此须要开启防火墙,可是核心防御仍是关了吧。
[root@localhost ~]# systemctl start firewalld.service [root@localhost ~]# systemctl status firewalld.service ● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) Active: active (running) since 一 2020-04-06 10:18:40 CST; 2s ago Docs: man:firewalld(1) Main PID: 65611 (firewalld) ...
初始化环境:(后面会返回到这个环境状态)
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE [root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
咱们尝试经过docker网桥方式(桥接)给一个容器设置一个ip地址(自定义的),下面看一下命令执行的结果:
[root@localhost ~]# docker run -itd --name test --network bridge --ip 172.17.0.10 centos:7 /bin/bash Unable to find image 'centos:7' locally 7: Pulling from library/centos ab5ef0e58194: Pull complete Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c Status: Downloaded newer image for centos:7 29f9e9cbb398085d7c89bed2982d626bfb7e564371a76a6cb693cffa68b917af docker: Error response from daemon: user specified IP address is supported on user defined networks only.
首先,因为没有改镜像,因此会先拉取镜像以后建立以及尝试运行容器,可是会遇到报错,报错缘由是由于用户本身设置的ip地址只适合于他们本身定义的网络。可是这并不影响镜像的获取与建立,咱们尝试运行看看结果:
[root@localhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE centos 7 5e35e350aded 4 months ago 203MB [root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 29f9e9cbb398 centos:7 "/bin/bash" About a minute ago Created test [root@localhost ~]# docker start 29f9e9cbb398 Error response from daemon: user specified IP address is supported on user defined networks only Error: failed to start containers: 29f9e9cbb398
很显然,结果告诉咱们仍是上述的缘由致使了这个问题,好吧只能删除这个容器了。索性还原为初始化环境吧(其实能够去掉--network bridge就不会报错,可是设置的ip地址会不生效,能够自行尝试一下),咱们不指定ip地址来试一下,顺便验证一下不加这个参数试试,最后还原为初始化状态后咱们再经过自定义的方式来设置ip地址吧。
[root@localhost ~]# docker run -itd --name demo centos:7 /bin/bash 984545df8ebf2c30f4ccf3f5f4699ed67bd2a93cbc068f2ace4865a828b4a4d1 [root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 984545df8ebf centos:7 "/bin/bash" 8 seconds ago Up 6 seconds demo
进入容器查看ip地址
[root@localhost ~]# docker exec -it 984545df8ebf /bin/bash [root@984545df8ebf /]# yum install -y net-tools Loaded plugins: fastestmirror, ovl Determining fastest mirrors [root@984545df8ebf /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255 ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet) RX packets 2201 bytes 15042254 (14.3 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1999 bytes 111171 (108.5 KiB) 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 loop txqueuelen 1000 (Local Loopback) 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
那么首先咱们须要建立一个自定义的子网段,而且给他一个名称,经过这个网段给对应的容器设置固定的ip地址。
[root@localhost ~]# docker network create --subnet=172.18.0.0/24 mynetwork Error response from daemon: Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br-4cd28c051bec -j RETURN: iptables: No chain/target/match by that name. (exit status 1))
看来很不幸啊,又error了,不要慌,咱们看看是什么缘由致使的,这个报错的根源看似是防火墙,说是没法跳过DNAT(目标网络地址转换)规则,其实致使这个问题的缘由是咱们刚刚开启了防火墙,却没有重启docker服务,就有点相似更改了配置文件没有重启服务。
[root@localhost ~]# systemctl restart docker [root@localhost ~]# docker network create --subnet=172.18.0.0/24 mynetwork 723d0fd514eb219d57667f72c3eb75fc4864af0cd94c21b6c70e868fb8d520a1
[root@localhost ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 00008a1e778b bridge bridge local 3bb2f50eb211 host host local 723d0fd514eb mynetwork bridge local e12cd7b98c54 none null local [root@localhost ~]#
此时进行验证自定义设置一个容器的固定IP地址的测试:
[root@localhost ~]# docker run -itd --name test2 --network mynetwork --ip 172.18.0.10 centos:7 /bin/bash Unable to find image 'centos:7' locally 7: Pulling from library/centos ab5ef0e58194: Pull complete Digest: sha256:4a701376d03f6b39b8c2a8f4a8e499441b0d567f9ab9d58e4991de4472fb813c Status: Downloaded newer image for centos:7 683ad76f7789b5c16f251577047a288a3a4a00777128a216adfee15985b94c04
查看容器的状态,进入容器查看ip地址
[root@localhost ~]# docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 683ad76f7789 centos:7 "/bin/bash" 23 seconds ago Up 22 seconds test2 [root@localhost ~]# docker exec -it 683ad76f7789 /bin/bash [root@683ad76f7789 /]# yum install -y net-tools Loaded plugins: fastestmirror, ovl ... [root@683ad76f7789 /]# ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.18.0.10 netmask 255.255.255.0 broadcast 172.18.0.255 ether 02:42:ac:12:00:0a txqueuelen 0 (Ethernet) RX packets 2302 bytes 15050471 (14.3 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 2049 bytes 113777 (111.1 KiB) 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 loop txqueuelen 1000 (Local Loopback) RX packets 62 bytes 7019 (6.8 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 62 bytes 7019 (6.8 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
此时发现自定义的网络设置容器ip地址成功了。
本文经过对VMware软件中的三种网络模式工做的原理,层层递进深刻讲解docker的各类网络模式,而且经过案例结合排障思路详细介绍了有关docker网桥模式是如何配置容器ip地址的,有默认模式以及自定义模式。
最后,须要注意的是命令仍是须要多记多敲多练,谢谢阅读!