Docker---网络模式详解与用户自定义网络使用

目录

 

一.docker网络实现原理

二.docker的四类网络模式

三.docker用户自定义网络使用命令


一.docker网络实现原理

虚拟机平台的网卡分析

  • 我们使用ifconfig命令查看安装docker-ce的虚拟机平台有,如下信息
[root@localhost ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:24:fe:93:22  txqueuelen 0  (Ethernet)
        RX packets 2652  bytes 139971 (136.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3407  bytes 15146807 (14.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.43.101  netmask 255.255.255.0  broadcast 192.168.43.255
        inet6 fe80::ba30:ef5e:b59f:4f1c  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:ce:5f:24  txqueuelen 1000  (Ethernet)
        RX packets 45  bytes 5797 (5.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 92  bytes 12139 (11.8 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
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1  (Local Loopback)
        RX packets 68  bytes 5916 (5.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 68  bytes 5916 (5.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

virbr0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 192.168.122.1  netmask 255.255.255.0  broadcast 192.168.122.255
        ether 52:54:00:7a:bf:df  txqueuelen 1000  (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

[root@localhost ~]# 
  • 其中eth0是真实存在的适配器,用来连接物理机网卡;
  • 而lo则是虚拟出来的回环网卡,用来检测tcp/ip协议是否生效;
  • 对于virbr0虚拟桥接网卡,linux自身集成了一个虚拟化功能,被镶嵌在内核当中

docker0网桥分析

  • docker使用linux桥接,在宿主机虚拟一个容器网——docker 0,Docker启动一个容器时会根据docker网桥的网段分配给容器一个IP地址,称为Container-IP。
  • 同时Docker网桥也是每个容器的默认网关。因为在同一个宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的container-IP直接通信。
  • Docker网桥是宿主机虚拟出来的,并不是真实存在的网络设备,外部网络是无法寻址到的,意味着外部网络无法直接通过Container-IP访问到容器。如果容器希望外部访问能够访问到,可以通过映射容器端口到宿主主机(端口映射)。

虚拟机平台容器网络架构图

  • 启动docker 0和ens33之间通过NAT地址转换技术,使得后面的容器IP映射到ens33的地址,再通过不同的端口映射区分不同的容器。

二.docker的四类网络模式

  • 安装docker时,docker会自动创建三个网络,bridge(bridge创建容器默认连接到此网络)、none、host
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
b1e4b6deb58f        none                null                local
[root@cloud ~]# 

host模式

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

container模式

  • container模式指定新创建的容器和已经存在的容器共享一个Network NameSpace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的IP地址,而是和指定的一个容器共享IP地址、端口范围。同样,两个容器除了网络方面,其他如文件系统,进程列表等还是隔离的。两个容器的进程可以通过lo网卡设备通信。

none模式

  • 使用none模式,docker容器拥有自己的network namesapce,但是,并不为docker容器进行任何网络配置。也就是说,这个docker容器没有网卡、Ip、路由等信息。需要我们自己为docker容器添加网卡、配置IP地址等
  • 在none模式下容器只有lo回环网络,没有其他网卡。none模式可以在容器创建时通过 --network=none来指定。这种网络没有办法联网。封闭的网络能够很好的保证容器的安全性。

 

bridge模式

  • 当docker进程启动时,会在主机上创建一个名为docker 0的虚拟网桥,此主机上启动的docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就可以通过交换机连在一个二层网络中。
  • 从docker 0子网中分配一个给容器使用,并且设置docker 0的IP地址位容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,docker将veth pair设备的一端放在新创建的容器中,并且命名为eth0(容器的网卡),另外一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker 0网桥中。可以通过brctl show命令查看。
  • bridge模式是docker的默认网络模式。不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL 查看。

 

当我们使用多个node时,我们可以使用k8s,进行多节点容器管理

上述四种网络模式的配置说明

docker网络模式配置说明
host模式-net=host容器和宿主机共享network namespace
container模式-net=container:NAME_or_ID容器和另外一个容器共享Network namespace。kubernetes中的pod就是多个容器共享一个network namespace
none模式-net=none容器有独立的network namespace,但是并没有对其进行任何网络设置,如分配veth pair和网桥连接,配置IP等
bridge模式-net=bridge(默认为该模式)

三.docker用户自定义网络使用命令

自定义网络

  • 除了默认的名为docker 0的bridge网络,还可以创建自己的bridge网络或overlay网络。
  • bridge网络用于在本机内容器之间的互通
  • overlay网络用于不同主机内容的容器之间的互通
  • 本文主要对bridge网络说明,overlay网络在搭建k8s管理多节点时会详细说明

注:当我们使用如下命令,创建一个bridge网络下的指定IP地址的容器时,会发现使用bridge无法支持指定IP

docker run -itd --name test1 --network bridge --ip 172.17.0.10 centos:7 /bin/bash

  • 一个bridge类型的网络
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
b1e4b6deb58f        none                null                local
[root@cloud ~]# docker network create -d bridge my-net
ae3d32337feb2daea7c51b47020323a43c946ef041a664296438f594d66265a8
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
ae3d32337feb        my-net              bridge              local
b1e4b6deb58f        none                null                local
[root@cloud ~]# 


##docker network ls列出docker的网络类型
##docker network create -d指定要创建什么类型的网络 ,后面在加自定义的网络名称
##假如不使用-d参数,会创建bridge网络
docker network create -d bridge my-net 等同于 docker network create my-net
  • 查看自定义网络的源数据
[root@cloud ~]# docker network inspect my-net         ##使用inspect查看详细信息
[
    {
        "Name": "my-net",
        "Id": "ae3d32337feb2daea7c51b47020323a43c946ef041a664296438f594d66265a8",
        "Created": "2020-04-16T09:42:28.530895411+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",     ##此处docker为该网卡分配了一个子网
                    "Gateway": "172.19.0.1"        ##定义了网关
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
[root@cloud ~]# 
  • 创建一个bridge网络并且指定子网
##创建一个bridge类型的网络,定义子网段,定义网络名称
[root@cloud ~]# docker network create --subnet=172.20.0.0/16 my-net_172_20
cd3c2d0fcfde4ab138944078bffcfec9265abc5ed3894a033b20828addc6d7af
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
ae3d32337feb        my-net              bridge              local
cd3c2d0fcfde        my-net_172_20       bridge              local
b1e4b6deb58f        none                null                local

##查看该网络的源信息
[root@cloud ~]# docker network inspect my-net_172_20 
[
    {
        "Name": "my-net_172_20",
        "Id": "cd3c2d0fcfde4ab138944078bffcfec9265abc5ed3894a033b20828addc6d7af",
        "Created": "2020-04-16T09:49:08.7236899+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.0.0/16"        ##子网段成功设置
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
[root@cloud ~]# 
  • 创建一个网络时,可以使用--label添加元数据
#在创建一个网络时使用--label,为此网络指定一些元数据信息
#如下
[root@cloud ~]# docker network create \
> --label network_name=my-net_label \    ##指定网络名称元数据
> --label project=LB_nginx \        ##指定项目名称元数据
> my-net_label
1db0bc5d23308fa582dea32c044ec910e23e5f6c7012dd9a51751dd1a0ef3e5d
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
ae3d32337feb        my-net              bridge              local
cd3c2d0fcfde        my-net_172_20       bridge              local
1db0bc5d2330        my-net_label        bridge              local
b1e4b6deb58f        none                null                local
[root@cloud ~]# docker network inspect my-net_label 
[
    {
        "Name": "my-net_label",
        "Id": "1db0bc5d23308fa582dea32c044ec910e23e5f6c7012dd9a51751dd1a0ef3e5d",
        "Created": "2020-04-16T09:57:10.419307733+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.21.0.0/16",
                    "Gateway": "172.21.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {                        ##此处是我们指定label信息
            "network_name": "my-net_label",        
            "project": "LB_nginx"
        }
    }
]
[root@cloud ~]# 

  • 删除自定网络
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
ae3d32337feb        my-net              bridge              local
cd3c2d0fcfde        my-net_172_20       bridge              local
1db0bc5d2330        my-net_label        bridge              local
b1e4b6deb58f        none                null                local
[root@cloud ~]# docker network rm my-net        ##使用docker network rm + 自定义网络名称删除
my-net
[root@cloud ~]# docker network rm my-net_172_20 
my-net_172_20
[root@cloud ~]# docker network rm my-net_label 
my-net_label
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
b1e4b6deb58f        none                null                local
[root@cloud ~]# 

定义容器网络并且通信

  • 我们可以将现有的容器连接到一个或者多个网络。容器可以连接到使用不同网络驱动程序的网络,比如连接到bridge网络或者overlay网络。连接后,容器可以使用其他容器的IP地址或名称进行通信。

上图中表明的意思是,在一台docker主机docker host上有三个容器,且三个容器分别连接到两个不同的网络中

容器container1连接到默认的桥接网络bridge

容器container2连接到默认的网络的bridge,同时它还连接到自定义的桥接网络my-net中

容器container3连接到自定义的桥接网络my-net中

  • 先创建并且运行两个容器container1和container2
[root@cloud ~]# docker run -itd --name=container1 centos:7
499930b14be84a6307e1e539d1c1f9d7c10c8cc7a01ebe3228d27388d4bd3732
[root@cloud ~]# docker run -itd --name=container2 centos:7
52c71b93d4cc6a2f5898b3147043a5becf0bdd79e2198b563b52273ee44031c4
[root@cloud ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
52c71b93d4cc        centos:7            "/bin/bash"         4 seconds ago       Up 3 seconds                            container2
499930b14be8        centos:7            "/bin/bash"         12 seconds ago      Up 11 seconds                           container1
[root@cloud ~]# 
  • 创建一个隔离的桥接网络my-net
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
b1e4b6deb58f        none                null                local

//--subnet指定子网
[root@cloud ~]# docker network create -d bridge --subnet 172.20.0.0/16 my-net
7b4bef68576ca21991dfb132a96c8db458beaeb84a7fa084b5fe88055aa90644
[root@cloud ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
9c7af129bb18        bridge              bridge              local
6679de44fc2e        host                host                local
7b4bef68576c        my-net              bridge              local
b1e4b6deb58f        none                null                local
[root@cloud ~]# 
  • 将容器container2假如my-net网络中
##使用connect连接网络
[root@cloud ~]# docker network connect my-net container2
[root@cloud ~]# docker network inspect my-net 
[
    {
        "Name": "my-net",
        "Id": "7b4bef68576ca21991dfb132a96c8db458beaeb84a7fa084b5fe88055aa90644",
        "Created": "2020-04-16T11:03:46.664703847+08:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.20.0.0/16"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "52c71b93d4cc6a2f5898b3147043a5becf0bdd79e2198b563b52273ee44031c4": {
                "Name": "container2",            ##此处信息显示添加成功
                "EndpointID": "f3d6b544d66216f1e914cffae302f895b8b816bc348fefbfe88bb6549e20d4d4",
                "MacAddress": "02:42:ac:14:00:02",
                "IPv4Address": "172.20.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {}
    }
]
[root@cloud ~]# 
  • 创建并且运行container3容器并且指定网络
[root@cloud ~]# docker run -itd --name=container3 --network=my-net --ip=172.20.0.100 centos:7
77565a1449d2095d75b02698445364cb4aaaeeb99d18384305980b58758c9e12

##--network指定网络类型
##--ip指定固定的IP地址
  • 进入container2容器查看网卡信息
[root@cloud ~]# docker exec -it container2 /bin/bash
[root@52c71b93d4cc /]# yum install net-tools -y        ##下载网络命令工具

[root@52c71b93d4cc /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.3  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:03  txqueuelen 0  (Ethernet)
        RX packets 6214  bytes 15333342 (14.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4405  bytes 302412 (295.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.20.0.2  netmask 255.255.0.0  broadcast 172.20.255.255
        ether 02:42:ac:14:00:02  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

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 61  bytes 5883 (5.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 61  bytes 5883 (5.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@52c71b93d4cc /]# 

在container2中可以看到eth0和eth1两张虚拟网卡信息

这是因为,我们一开始运行这个容器的时候,被连接到默认的网络上,后来我们又执行了 docker network connect 命令,把它连接到了 my-net 网络上了,所以这使其有两个网络,并且有两个网卡。

  • 容器间的通信
[root@cloud ~]# docker exec -it container1 /bin/bash
[root@499930b14be8 /]# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.2  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:02  txqueuelen 0  (Ethernet)
        RX packets 6816  bytes 15372396 (14.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4508  bytes 302345 (295.2 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

[root@499930b14be8 /]# ping 172.18.0.3
PING 172.18.0.3 (172.18.0.3) 56(84) bytes of data.
64 bytes from 172.18.0.3: icmp_seq=1 ttl=64 time=0.073 ms
^C
--- 172.18.0.3 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.073/0.073/0.073/0.000 ms
[root@499930b14be8 /]# ping 172.20.0.100
PING 172.20.0.100 (172.20.0.100) 56(84) bytes of data.
^C
--- 172.20.0.100 ping statistics ---
7 packets transmitted, 0 received, 100% packet loss, time 5999ms

[root@499930b14be8 /]# 

上面我们进入container1容器,container1可以ping通container2,但是ping不同container3。

因为 container3 和 container1 并没有任何共同的网络,所以他们是无法通信的。

  • 从网络中断开一个容器的连接
docker network disconnect 网络名 容器名

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值