Docker网络管理之docker跨主机通讯

前言

因为docker技术的火爆,致使如今愈来愈多的企业都在使用docker这种虚拟化技术。企业中使用docker这种虚拟化技术,其目的就是为了让docker中的容器对外提供服务。所以,咱们必须深刻了解一下docker的网络知识,以知足更高的网络需求。linux

咱们安装Docker时,它会自动建立三个网络,bridge(建立容器默认链接到此网络)、 none 、host。

* host:容器将不会虚拟出本身的网卡,配置本身的IP等,而是使用宿主机的IP和端口。
* None:该模式关闭了容器的网络功能,至关于一个回环网络。
* Bridge:此模式会为每个容器分配、设置IP等,并将容器链接到一个叫docker0的虚拟网桥,经过docker0网桥以及Iptables nat表配置与宿主机通讯。
[root@docker ~]# docker network  ls          //执行该命令查看docker建立的网络
NETWORK ID          NAME                DRIVER              SCOPE
2edf7ef4f9fa        bridge              bridge              local
217d2e9a4785        host                host                local
c0bea73a8e1a        none                null                local

关于上述提到的三个网络解释以下:web

  • Host:至关于Vmware中的桥接模式,与宿主机在同一个网络中,但没有独立的IP地址。众所周知,Docker使用了Linux的Namespaces技术来进行资源隔离,如PID Namespace隔离进程,Mount Namespace隔离文件系统,Network Namespace隔离网络等。一个Network Namespace提供了一份独立的网络环境,包括网卡、路由、Iptable规则等都与其余的Network Namespace隔离。一个Docker容器通常会分配一个独立的Network Namespace。但若是启动容器的时候使用host模式,那么这个容器将不会得到一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出本身的网卡,配置本身的IP等,而是使用宿主机的IP和端口。基于Host模式启动的容器,在容器内执行ifconfig时,看到的都是宿主机上的信息。该模式不够灵活,容易出现端口冲突问题。
  • None:该模式将容器放置在它本身的网络栈中,可是并不进行任何配置。实际上,该模式关闭了容器的网络功能,相似于会换地址,在如下两种状况下是有用的:容器并不须要网络(例如只须要写磁盘卷的批处理任务)。
  • overlay:顾名思义:覆盖,但它又不是覆盖,它的做用就是在容器原有的网络基础之上,再添加一块网卡,并为其分配一个IP地址,能够将全部的docker容器关联到同一个局域网中,适用于容器与容器是跨主机进行通讯的场景。
  • Bridge:至关于Vmware中的NAT模式,容器使用独立的network Namespace,而且链接到docker0虚拟网卡(默认模式)。经过docker网桥以及IPtables nat表配置与宿主机通讯;Bridge模式是Docker默认的网络设置,此模式会为每个容器分配一个Network nameSpace、设置IP等,并将一个主机上的Docker容器链接到一个虚拟网桥docker0上

虽然docker模式提供三种网络模式,但实际上是有四种网络模式的!
注:今天只介绍Overlay网络,Macvlan网络,想了解其他三种网络模式请参考:http://www.javashuo.com/article/p-rajoxwmu-nr.htmldocker

1、Overlay网络

使用overlay网络需事先部署好consul服务!bootstrap

consul:是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,并且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特色是:服务发现、健康检查、键值存储、安全服务通讯、多数据中心。vim

经过一个实验案例来验证consul服务的特性!
1.案例环境浏览器

系统版本: Centos 7.3
Docker版本: 18.09.0
主机名IP地址:
docekr01:192.16.45.129  
docekr02:192.16.45.141   
docekr03:192.16.45.142

二、准备工做:安全

* 必须安装key-value存储服务,如consul;
* 宿主机已经安装docker engine;
* 宿主机的hostname必须不一样 ,避免发生冲突 ;                                       
* 关闭防火墙与SELinux(实验环境;

三、案例实施
1)docker01
服务器

[root@docker01 ~]#  docker pull progrium/consul     //下载consul镜像
[root@docker01 ~]#  docker run -d -p 8500:8500 -h consul --name consul  --restart=always progrium/consul -server -bootstrap
//-d:后台运行;              
//-p:将容器中的8500端口映射到宿主机的8500端口;
//-h:表示consul容器的主机名;
//--name:表示运行的容器名;
//--restart=always:随docker服务的启动而启动;
//-server -bootstrap:添加这两个选项,则表示在群集环境中可使其以master的身份出现;
[root@docker01 ~]# netstat -anpt | grep 8500
tcp6       0      0 :::8500                 :::*                    LISTEN      3725/docker-proxy   
//肯定其8500端口正在监听
[root@docker01 ~]# vim /usr/lib/systemd/system/docker.service     //更改一下docker的主配置文件
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.45.129:8500 --cluster-advertise=ens33:2376
//在第13行上本来的基础添加以上内容,各个配置项含义以下:
# /var/run/docker.sock:Docker的一个套接字;
# “ -H tcp://0.0.0.0:2376 ” :使用本机的tcp2376端口;
# “ --cluster-store=consul://192.168.45.129:8500”:指定运行着consul服务的docker服务器IP及端口;
# “ --cluster-advertise=ens33:2376”:从本机的ens33网卡经过2376端口搜集网络信息,存储在consul上
[root@docker01 ~]# systemctl  daemon-reload 
[root@docker01 ~]# systemctl  restart docker.servic     //从新启动docker服务

使用浏览器访问consul服务的web页面
Docker网络管理之docker跨主机通讯
Docker网络管理之docker跨主机通讯
Docker网络管理之docker跨主机通讯
2)docker02网络

[root@docker02 ~]# vim /usr/lib/systemd/system/docker.service 
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.45.129:8500 --cluster-advertise=ens33:2376
//在第13行上本来的基础添加以上内容,各个配置项含义以下:
# /var/run/docker.sock:Docker的一个套接字;
# “ -H tcp://0.0.0.0:2376 ” :使用本机的tcp2376端口;
# “ --cluster-store=consul://192.168.45.129:8500”:指定运行着consul服务的docker服务器IP及端口;
# “ --cluster-advertise=ens33:2376”:从本机的ens33网卡经过2376端口搜集网络信息,存储在consul上
[root@docker02 ~]# systemctl  daemon-reload 
    [root@docker02 ~]# systemctl  restart docker.service    //从新启动docker服务

访问浏览器刷新浏览器页面
Docker网络管理之docker跨主机通讯
3)Docker3tcp

Docker3与Docker2的操做就是如出一辙的,因此这里就很少作解释了!

[root@docker03 ~]# vim /usr/lib/systemd/system/docker.service 
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.45.129:8500 --cluster-advertise=ens33:2376
//在第13行上本来的基础添加以上内容,各个配置项含义以下:
# /var/run/docker.sock:Docker的一个套接字;
# “ -H tcp://0.0.0.0:2376 ” :使用本机的tcp2376端口;
# “ --cluster-store=consul://192.168.45.129:8500”:指定运行着consul服务的docker服务器IP及端口;
# “ --cluster-advertise=ens33:2376”:从本机的ens33网卡经过2376端口搜集网络信息,存储在consul上
[root@docker03 ~]# systemctl  daemon-reload 
[root@docker03 ~]# systemctl  restart docker.service    //从新启动docker服务

Docker网络管理之docker跨主机通讯
注:若是在此过程当中,访问web页面若是出现“500”的错误页面,将运行consul服务的容器删除从新创新便可!
4)建立一个 overlay网络
docker01:

[root@docker01 ~]# docker network create -d overlay my_olay
//建立一个名为my_olay的voerlay网络 
//以上操做无论在那台docker主机上操做均可以
[root@docker01 ~]#  docker network create -d overlay --subnet 200.0.0.0/24 --gateway 200.0.0.1 lv_olay
//也能够在建立overlay网卡时,指定其IP网段及网关
[root@docker01 ~]# docker network ls          //查看docker所支持的网络

Docker网络管理之docker跨主机通讯
注:

  • 并且在另外两台docker服务器上也可看到,自行验证!

  • 在docker 1上建立的网络,能够看到其SPOCE(范围)定义的是global(全局),那么这就意味着加入consul这个服务群集的其余docker服务器也能够看到这张网卡!

  • 若是在建立网卡时,没有指定其网段,则默认是10.0.0.0网段,因为是自定义网络,因此知足自定义网络的特征(好比支持容器之间的通讯)!
    5)在不一样的docker服务器各自建立一个容器,验证是否能够通讯!

    [root@docker01 ~]# docker run -itd --name t1 --network lv_olay --ip 200.0.0.10 busybox:latest
    //在docker1服务器上建立一个名为t1的容器并指定其IP地址
    [root@docker02 ~]#  docker run -itd --name t2 --network lv_olay --ip 200.0.0.20 busybox:latest
    //在docker2上建立一个容器并指定IP地址
    [root@docker03 ~]# docker run -itd --name t3 --network lv_olay --ip 200.0.0.30 busybox:latest
    //在docker3上建立一个容器并指定IP地址
    [root@docker01 ~]# docker exec -it t1 /bin/sh
    //随便在一台docker服务器上进入其建立的容器中,进行测试
    / # ping  -c 2  t2
    PING t2 (200.0.0.20): 56 data bytes
    64 bytes from 200.0.0.20: seq=0 ttl=64 time=1.053 ms
    64 bytes from 200.0.0.20: seq=1 ttl=64 time=1.052 ms
    / # ping  -c 2  t3
    PING t3 (200.0.0.30): 56 data bytes
    64 bytes from 200.0.0.20: seq=0 ttl=64 time=1.053 ms
    64 bytes from 200.0.0.20: seq=1 ttl=64 time=1.052 ms

    注:能够看出IP地址,不一样docker host上容器通讯是没有问题的;

    2、Macvlan网络

    Macvlan是linux kernel比较新的特性,能够经过如下方法判断当前系统是否支持:

    [root@localhost ~]# modprobe macvlan        
    [root@localhost ~]# lsmod | grep macvlan
    macvlan                19239  0

    若是是第一个命令报错,或者第二个命令没有返回信息,则说明当前系统不支持macvlan,须要升级内核。

    [root@docker01 ~]# modprobe 8021q         //加载内核模块
    [root@docker01 ~]# modinfo 8021q           //若是有信息返回则表示开启8021q模块,若是没有使用上条命令

    这两组命令所支持的效果同样!

  • 以上命令主要验证Linux内核是否支持macvlan功能!

  • macvlan容许在主机的一个网络接口上配置多个虚拟的网络接口,这些网络接口有本身独立的mac地址,也能够配置IP地址进行通讯。macvlan下的虚拟机或者容器网络和主机在同一网段中,共享一个广播域。macvlan和bridge比较类似,但由于它省去了bridge的存在,因此在配置和调试时比较简单,并且效率较高。除此以外,macvlan自身也完美支持VLAN。

  • 若是但愿容器或者虚拟机放在主机相同的网络中,享受已经存在网络栈的各类优点,能够考虑macvlan。

  • macvlan和overlay网络不一样,overlay的做用范围是global;而macvlan的做用范围是local。global类型的网络其做用于一组docker daemon集群,local类型的网络只做用于单一主机。

  • 每台主机建立的macvlan网络是独立的,A机器行建立的macvlan网络并不影响B机器上的网络。

  • 两台主机在网卡配置混杂模式、两台主机上macvlan存在overlap、两个macvlan网络没有分配过一样的IP,以上三个条件知足后,一样能够实现跨主机通讯!
    一、实验环境要求
    docker版本:18.09.0
    docker01:192.168.45.129/24
    docker02:192.168.45.143/24
    (1)关闭Linux防火墙和SELinux;
    (2)修改主机名;

    二、案例实施

    一)、macvlan的单网络通讯

    1)打开网卡的混杂模式

//须要在docker01和docker02上都进行操做。
[root@docker01 ~]# ip link set ens33 promisc on
[root@docker01 ~]# ip link show ens33
[root@docker01 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o parent=ens33 mac_net1   
//在docker01上建立macvlan网络
//PS: -o parent=绑定在哪张网卡之上
[root@docker01 ~]# docker run -itd --name bbox1 --ip 172.22.16.10 --network mac_net1 busybox
//基于建立的macvlan网络运行一个容器

在docker02上建立macvlan网络,注意与docker01上 的macvlan网络如出一辙

//须要在docker01和docker02上都进行操做。
[root@docker02 ~]# ip link set ens33 promisc on
[root@docker02 ~]# ip link show ens33
[root@docker02 ~]# docker network create -d macvlan --subnet 172.22.16.0/24 --gateway 172.22.16.1 -o parent=ens33 mac_net1
[root@docker02 ~]# docker run -itd --name bbox2 --network mac_net1 --ip 172.22.16.20 busybox

验证

[root@docker01 ~]# docker exec  -it bbox1 sh
/ # ping 172.22.16.20
PING 172.22.16.20 (172.22.16.20): 56 data bytes
64 bytes from 172.22.16.20: seq=0 ttl=64 time=0.884 ms
64 bytes from 172.22.16.20: seq=1 ttl=64 time=1.478 ms
64 bytes from 172.22.16.20: seq=2 ttl=64 time=1.182 ms

二)、macvlan多网络通讯

(1)开启网卡混杂模式
docker01:

[root@docker01 ~]# ip link  set  ens33  promisc on            //开启网卡的混杂模式
[root@docker01 ~]# ip link  show ens33                            //查询网卡已经支持PROMISC
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:33:22:73 brd ff:ff:ff:ff:ff:ff
[root@docker01 ~]# modprobe 8021q                  /加载8021q内核模块
[root@docker01~]# modinfo 8021q                   //有返回信息则表示支持8021q内核模块

(2)建立虚拟网卡

因为一个网卡最好建立出一个macvlan网卡,因此需建立虚拟网卡以知足要求!

[root@docker01 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33 
BOOTPROTO=manual     //将网络获取模式改成手动模式
[root@docker01 ~]# cd /etc/sysconfig/network-scripts/
[root@docker01 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.10
[root@docker01 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.20
[root@docker01 network-scripts]# vim ifcfg-ens33.10
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.1
NETMASK=255.255.255.0
GATEWAY=192.168.10.254
VLAN=yes
//保证和本来的物理网卡不在同一网段,而且打开vlan的支持模式
[root@docker01 network-scripts]# vim ifcfg-ens33.20
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.1
NETMASK=255.255.255.0
GATEWAY=192.168.20.254
VLAN=yes
[root@docker01 network-scripts]# ifup  ifcfg-ens33.10 
[root@docker01 network-scripts]# ifup  ifcfg-ens33.20
[root@docker01 network-scripts]# ifconfig ens33.10          
[root@docker01 network-scripts]# ifconfig ens33.20   //查看网卡是否生效

Docker网络管理之docker跨主机通讯
docker02主机上的操做与docker01主机上的操做一致(注意IP不同)!要保证两台docker主机的虚拟网卡能够通讯!
docker02:

[root@docker02 ~]#  ip link  set  ens33  promisc  on     //开启网卡的混杂模式
[root@docker02 ~]# ip link  show ens33                         //查询网卡已经支持PROMISC   
2: ens33: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
    link/ether 00:0c:29:06:84:51 brd ff:ff:ff:ff:ff:ff
[root@docker02 ~]# modprobe 8021q                  /加载8021q内核模块
[root@docker02 ~]# modinfo 8021q                   //有返回信息则表示支持8021q内核模块
[root@docker01 ~]# vim /etc/sysconfig/network-scripts/ifcfg-ens33 
BOOTPROTO=manual          //将网络获取模式改成手动模式
[root@docker02 ~]# cd /etc/sysconfig/network-scripts/
[root@docker02 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.10
[root@docker02 network-scripts]# cp -p ifcfg-ens33  ifcfg-ens33.20
[root@docker02 network-scripts]# vim ifcfg-ens33.10 
BOOTPROTO=none
NAME=ens33.10
DEVICE=ens33.10
ONBOOT=yes
IPADDR=192.168.10.2
NETMASK=255.255.255.0
GATEWAY=192.168.10.254
VLAN=yes 
[root@docker02 network-scripts]# vim ifcfg-ens33.20
BOOTPROTO=none
NAME=ens33.20
DEVICE=ens33.20
ONBOOT=yes
IPADDR=192.168.20.2
NETMASK=255.255.255.0
GATEWAY=192.168.20.254
VLAN=yes 
[root@docker01 network-scripts]# ifup  ifcfg-ens33.10 
[root@docker01 network-scripts]# ifup  ifcfg-ens33.20
[root@docker02 network-scripts]# ifconfig  ens33.10
[root@docker02 network-scripts]# ifconfig  ens33.20

Docker网络管理之docker跨主机通讯
(3)建立macvlan网卡

[root@docker01 ~]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1 -o parent=ens33.10 mac_net10
[root@docker01 ~]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1 -o parent=ens33.20 mac_net20
//建立虚拟网卡并针对其网段、网关
//-d:指令网卡驱动类型,-o parent:绑定在那张网卡上
[root@docker01 ~]# docker network ls

Docker网络管理之docker跨主机通讯
docker02主机上的建立虚拟网卡时,命令如出一辙,指定的网段、名称必须同样,由于要保证其经过虚拟网卡能够通讯!

[root@docker02 ~]# docker network create -d macvlan --subnet 172.16.10.0/24 --gateway 172.16.10.1 -o parent=ens33.10 mac_net10
[root@docker02 ~]# docker network create -d macvlan --subnet 172.16.20.0/24 --gateway 172.16.20.1 -o parent=ens33.20 mac_net20

(4)基于建立的macvlan网卡建立容器,验证是否能够通讯!

dockerA主机建立容器:

[root@docker01 ~]# docker run -itd --name box10 --network mac_net10 --ip 172.16.10.10 busybox
[root@docker01 ~]# docker run -itd --name box20 --network mac_net20 --ip 172.16.20.10 busybox

dockerB主机建立容器:

[root@docker02 ~]# docker run -itd --name box11 --network mac_net10 --ip 172.16.10.20 busybox
[root@docker02 ~]# docker run -itd --name box21 --network mac_net20 --ip 172.16.20.20 busybox

进入容器进行验证:

[root@docker01 ~]# docker exec -it box10 /bin/sh
/ # ping 172.16.10.20
PING 172.16.10.20 (172.16.10.20): 56 data bytes
64 bytes from 172.16.10.20: seq=0 ttl=64 time=0.653 ms
64 bytes from 172.16.10.20: seq=1 ttl=64 time=0.966 ms
[root@docker01 ~]# docker exec -it box20 /bin/sh/ # ping 172.16.20.20
PING 172.16.20.20 (172.16.20.20): 56 data bytes
64 bytes from 172.16.20.20: seq=0 ttl=64 time=0.734 ms
64 bytes from 172.16.20.20: seq=1 ttl=64 time=0.718 ms

注:如若出现不能通信的状况!请把实验环境两台docker虚拟机调制为桥接模式;
Docker网络管理之docker跨主机通讯

相关文章
相关标签/搜索