Docker之网络管理(容器间通信的配置)

博文大纲:

  • 一、Bridge模式(同一台Docker服务器上容器间的通信)
  • 二、部署consul服务实现Docker容器跨主机通信

前言:

当你开始大规模使用Docker时,你会发现需要了解很多关于网络的知识。Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理。然而,Docker同样有着很多不完善的地方,网络方面就是Docker比较薄弱的部分。因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求。本文首先介绍了Docker自身的4种网络工作方式,然后介绍一些自定义网络模式。


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

  • host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
  • None:该模式关闭了容器的网络功能,相当于一个回环网络。
  • Bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个叫docker0的虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
[[email protected] ~]# docker network ls    #执行该命令查看docker创建的网络

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

  • 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上。

在生产环境中,应用的最多的就是Bridge模式和overlay模式了。这篇博文将围绕着这两个模式进行介绍。

一、Bridge模式

当Docker server启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器就会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中,一般Docker会使用172.17.0.0/16这个网段,并将这个网段分配给docker0网桥使用(在主机上使用ifconfig命令可以看到docker0),然后为容器分配一个同网段的IP地址。

单机环境下的网络拓扑如下(主机地址是10.10.0.186/24):

Docker 完成以上网络配置的过程大致是这样的:

  • 在主机上创建一对虚拟网卡veth pair设备。veth设备总是成对出现的,它们组成了一个数据的通道,数据从一个设备进入,就会从另一个设备出来。因此,veth设备常用来连接两个网络设备。
  • Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0。另一端放在主机中,以veth65f9这样类似的名字命名,并将这个网络设备加入到docker0网桥中,可以通过brctl show命令查看。
  • 从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。

当所有的容器都是基于默认的docker0进行创建的,那么抛开防火墙、IPtables等相关的设置外,理论上,各个容器是可以相互通信的,但是docker0这个网络是系统自带的,有些功能不能够实现,并且不够灵活。

其实我们也是可以自定义创建网络的,并且可以指定其具体属于哪个网段等。这是docker 0无法实现的,那么,如果各个容器,不是基于同一个网络(如Docker0)创建的话,那么?如何使它们互通呢?

下面来一段配置,来看一下Bridge的工作模式。

实现的效果如下:

  • 基于docker0(docker的驱动名称使bridge)网络创建2个容器,分别是box1、box2。
  • 创建自定义网络,网络类型为bridge,名称为my_net1.基于此网络创建两个容器box3,box4(若不指定网段,会使用172.18.0.0/16这个网段,基于docker0增加一个网络位)
  • 创建自定义网络,网络类型为bridge,名称为my_net2,指定网段为172.20.18.0/24,基于此网络创建两个容器box5(ip为172.20.18.6),box6(IP为172.20.18.8)。
  • 配置实现box2能够和box3相互通信,box4和box5可以相互通信。
[[email protected] ~]# docker run -itd --name box1 --network bridge busybox
#创建一个容器box1,--network选项可以省略,默认就是bridge,这里只是为了展示命令
[[email protected] ~]# docker run -itd --name box2 --network bridge busybox   #同上,这里创建一个容器box2
[[email protected] ~]# docker network create -d bridge my_net1    #创建一个桥接网络,名称为my_net1
[[email protected] ~]# docker run -tid --name box3 --network my_net1 busybox    #基于my_net1创建容器box3
[[email protected] ~]# docker run -tid --name box4 --network my_net1 busybox   #同上,创建box4
[[email protected] ~]# docker network create -d bridge --subnet 172.20.18.0/24 my_net2   #创建一个桥接网络my_net2,并指定其网段
[[email protected] ~]# docker run -tid --name box5 --network my_net2 --ip 172.20.18.6 busybox
#基于my_net2网络,创建一个容器box5,并且指定其IP地址
[[email protected] ~]# docker run -tid --name box6 --network my_net2 --ip 172.20.18.8 busybox    #同上
[[email protected] ~]# docker network connect my_net1 box2      #将box2连接到my_net1这个网络
[[email protected] ~]# docker exec box2 ping box3   #进行ping测试,可以发现box2可以ping通box3了。
#而如果没有将box2连接到网络my_net1,是绝对不会ping通的。
PING box3 (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: seq=0 ttl=64 time=0.069 ms
64 bytes from 172.18.0.2: seq=1 ttl=64 time=0.076 ms
[[email protected] ~]# docker network connect my_net2 box4   #将box4连接到my_net2网络
#同box2和box3的ping测试,若没有将box4连接到box5所在的网络,是不可能ping通的。
[[email protected] ~]# docker exec box5 ip a    #查看box5的IP地址
         .......................#省略部分内容
16: [email protected]: <BROADCAST,MULTICAST,UP,LO500 qdisc noqueue
    link/ether 02:42:ac:14:12:06 brd ff:ff:ff:ff:ff:ff
    inet 172.20.18.6/24 brd 172.20.18.255 scope global eth0     #确认其IP
       valid_lft forever preferred_lft forever
[[email protected] ~]# docker exec box4 ping 172.20.18.6   #在box4容器上对box5的IP进行ping测试,可以ping通
PING box5 (172.20.18.6): 56 data bytes
64 bytes from 172.20.18.6: seq=0 ttl=64 time=0.090 ms
64 bytes from 172.20.18.6: seq=1 ttl=64 time=0.130 ms

经过以上配置,已经实现了最终的效果,需要注意的是,我们完全可以将创建的my_net1、my_net2网络驱动理解为一个交换机,而执行命令docker network connect my_net1 box2,则相当于将box2这个容器添加了一块网卡,然后连接到了my_net1这个交换机,然后这个容器就多了一块网卡,并且拥有my_net1这个交换机中IP地址。在上述的配置中,box2不但可以和box3进行通信,也是可以和box4进行通信的,因为它们都是连接在了my_net1这个“交换机”上。

注意:

  • 容器之间可以使用容器名进行通信,但前提使用的是自定义的网络,如上面的my_net1、my_net2;
  • 如果在创建自定义网络的同时,指定了该网络的网段,那么,使用此网络的容器也可以指定容器的IP地址,若没有指定该网络的网段,则不可以指定容器的IP地址。

二、部署consul服务实现Docker容器跨主机通信

consul:数据中心的含义,可以将其当做数据库来理解,类似于Redis等非关系型数据库,采用的是键-值对的方式,存放着各个容器的IP及端口信息。

我对consul服务的了解也不是太多,若想要详细了解此服务,还是参考其他文档吧,若以后有机会,我会详细写下来consul这个服务。

consul的功能很强大,可以以群集的方式运行,并且具备健康监测等功能。

下面开始配置consul服务。

1、环境准备如下:

  • Docker服务器三台,我这里的docker版本为18.09.0;
  • 第一台Docker服务器的IP是192.168.20.7,其运行consul服务;
  • 后两台为测试端,只需要有docker环境即可。

若需要安装部署Docker服务器,可以参考博文:Docker的安装详细配置

2、第一台Docker服务器配置如下:

[[email protected] ~]# docker pull progrium/consul          #下载consul镜像
[[email protected] ~]# docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap
#运行consul容器,该服务的默认端口是8500,“-p”:表示将容器的8500端口映射到宿主机的8500端口
#“-h”:表示consul的主机名;“--name consul”表示为该容器名;“--restart=always”表示可以随着docker服务的启动而启动;
#“-serve -bootstarp”:表示当在群集中,加上这两个选项可以使其以master的身份出现
[[email protected] ~]# netstat -anput | grep 8500   #确定8500端口在监听
tcp6       0      0 :::8500                 :::* 

OK,至此,单节点的consul服务就完成了,现在切换至第二台Docker服务器。

3、第二台Docker服务器配置如下:

[[email protected] ~]# vim /usr/lib/systemd/system/docker.service  #编辑docker主配置文件
         ..............#省略部分内容,搜索“Start”定位到下面配置行,修改如下:
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://192.168.20.7:8500 --cluster-advertise=ens33:2376
#各项解释如下:
#/var/run/docker.sock:Docker的一个编程接口
# “ -H tcp://0.0.0.0:2376 ” :使用本机的tcp2376端口;
# “ --cluster-store=consul://192.168.20.7:8500”:指定运行着consul服务的第一台docker服务器IP及端口;
# “ --cluster-advertise=ens33:2376”:从本机的ens33网卡通过2376端口搜集网络信息,存储在consul上
#修改完成后,保存退出即可。
[[email protected] ~]# systemctl daemon-reload    #重新加载配置文件
[[email protected] ~]# systemctl restart docker    #重启docker服务

4、然后在第三台docker服务器上,进行与第二台Docker服务器一样的配置操作,主要是为了指定consul服务的监听端口。(自行配置,这里就不写了,记得更改完成后,重启docker服务)

5、现在使用浏览器访问consul服务的web页面(访问:192.168.20.7:8500),如下:

即可看到用来测试的那两台docker服务器IP等相关信息,如下:

6、回到第二台Docker服务器上,创建一个overlay网络:

[[email protected] ~]# docker network create -d overlay my_olay         #创建一个名字为my_olay的voerlay网络 

7、切换至第三台Docker服务器上,发现可以看到刚刚在第二台Docker服务器上创建的overlay网络:

[[email protected] ~]# docker network ls     #查看docker03的网络,发现其不但有overlay网络,
#而且其SCOPE(范围)是global(全局的)
NETWORK ID          NAME                DRIVER              SCOPE
8d5b00cf07ab        bridge              bridge              local
17c053a80f5a        host                host                local
c428fc28bb11        my_olay             overlay             global
323935eaa5c3        none                null                local

其实,现在在第二台Docker服务器上基于刚刚创建的overlay网络运行一个容器,在第三台Docker服务器上也基于这个overlay网络运行一个容器,这两个在不同主机上的容器是可以互通的,如下:

##################第二台Docker服务器上配置如下:###########################
[[email protected] ~]# docker run -tid --name web01 --network my_olay busybox    #基于网络my_olay运行一个容器web01
[[email protected] ~]# docker exec web01 ip a         #查看其IP信息,发现其除了回环地址,还有两个IP
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    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
8: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
    link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.2/24 brd 10.0.0.255 scope global eth0     #这个地址就是my_olay给的
       valid_lft forever preferred_lft forever
11: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1
       valid_lft forever preferred_lft forever
##################第三台Docker服务器上配置如下:###########################
[[email protected] ~]# docker run -tid --name web02 --network my_olay busybox     #基于网络my_olay运行一个容器web02
[[email protected] ~]# docker exec web02 ip a     #查看web02的IP
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1
    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
8: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue
    link/ether 02:42:0a:00:00:03 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.3/24 brd 10.0.0.255 scope global eth0            #这个地址就是my_olay给的
       valid_lft forever preferred_lft forever
11: [email protected]: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1
       valid_lft forever preferred_lft forever
#########在第二台Docker服务器上对第三台Docker服务器上的容器进行ping测试##########
[[email protected] ~]# docker exec web01 ping web02      #确定可以ping通
PING web02 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=1.091 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=1.007 ms

———————— 本文至此结束,感谢阅读 ————————

原文地址:https://blog.51cto.com/14154700/2443760

时间: 2024-10-29 03:53:56

Docker之网络管理(容器间通信的配置)的相关文章

docker的网络、端口映射和容器间通信

docker作为服务器内部的一个容器单位,对外的通信也就有了困难.这里提供了一些几个解决方案. 1.Docker独立IP 简单说就是配置独立的网桥,分配给docker IP cd /etc/sysconfig/network-scripts/ vi ifcfg-eth0 DEVICE=eth0 BOOTPROTO=none ONBOOT=yes TYPE=Ethernet BRIDGE="br0" BOOTPROTO=static vi ifcfg-br0 DEVICE="b

容器间通信的三种方式 - 每天5分钟玩转 Docker 容器技术(35)

容器之间可通过 IP,Docker DNS Server 或 joined 容器三种方式通信. IP 通信 从上一节的例子可以得出这样一个结论:两个容器要能通信,必须要有属于同一个网络的网卡. 满足这个条件后,容器就可以通过 IP 交互了.具体做法是在容器创建时通过 --network 指定相应的网络,或者通过 docker network connect 将现有容器加入到指定网络.可参考上一节 httpd 和 busybox 的例子,这里不再赘述. Docker DNS Server 通过 I

10: docker 跨主机的容器间通信(macvlan / overlay )

docker 跨主机的容器间通信(macvlan) 作用: 虚拟多个mac地址,虚拟出多个网卡给容器用. #创建macvlan网络 docker network create --driver macvlan(要创建的网络类型) --subnet  子网IP段  --gateway 本机网关 -o parent=本机网卡  创建的macvlan网络名称 [[email protected] ~]# docker network create --driver macvlan --subnet 1

Docker网络和容器的通信

Docker的本地网络实现其实就是利用了Linux上的网络命名空间和虚拟网络设备(特别是veth pair). 基本原理 直观上看,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)与外界相通,并可以收发数据包:此外,如果不同子网之间要进行通信,需要额外的路由机制. Docker中的网络接口默认都是虚拟的接口.虚拟接口的最大优势就是转发效率极高.这是因为Linux通过在内核中进行数据复制来实现虚拟接口之间的数据转发,即发送接口的发送缓存中的数据包将被直接复制到接收接口的接收缓存中,而

Docker网络管理(容器间通信)

一.前言 由于docker技术的火爆,导致现在越来越多的企业都在使用docker这种虚拟化技术.企业中使用docker这种虚拟化技术,其目的就是为了让docker中的容器对外提供服务.因此,我们必须深入了解一下docker的网络知识,以满足更高的网络需求. 二.Docker的原生网络 当你安装Docker时,它会自动创建三个网络.如下: [[email protected] ~]# docker network ls //查看docker的默认网络 NETWORK ID NAME DRIVER

使用docker搭建nfs实现容器间共享文件

首先介绍下今天的两个主角:nfs和docker nfs 是什么 NFS(Network File System)即网络文件系统,是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源.在NFS的应用中,本地NFS的客户端应用可以透明地读写位于远端NFS服务器上的文件,就像访问本地文件一样. 摘自百度百科 docker 是什么 这个就不多说了,近两年一个非常流行的东西哦. 主角介绍完毕,那么要说说为什么要使用docker来搭建nfs,其实本文标题已经说明,主要

wwwhy76888com理解容器间link通信机制199O8836661

一.什么是docker的link机制? 同一个宿主机上的多个docker容器之间如果想进行通信,可以通过使用容器的ip地址来通信,也可以通过宿主机的ip加上容器暴露出的端口号来通信,前者会导致ip地址的硬编码,不方便迁移,并且容器重启后ip地址会改变,除非使用固定的ip,后者的通信方式比较单一,只能依靠监听在暴露出的端口的进程来进行有限的通信.通过docker的link机制可以通过一个name来和另一个容器通信,link机制方便了容器去发现其它的容器并且可以安全的传递一些连接信息给其它的容器.其

如何使不同主机上的docker容器互相通信

docker启动时,会在宿主主机上创建一个名为docker0的虚拟网络接口,默认选择172.17.42.1/16,一个16位的子网掩码给容器提供了65534个IP地址.docker0只是一个在绑定到这上面的其他网卡间自动转发数据包的虚拟以太网桥,它可以使容器和主机相互通信,容器与容器间通信. 问题是,如何让位于不同主机上的docker容器可以通信? 最简单的思路,修改一台主机docker默认的虚拟网段,然后在各自主机上分别把对方的docker网段加入到路由表中,即可实现docker容器夸主机通信

docker数据卷管理及网络基础配置

数据卷 数据卷容器 数据卷迁移数据 端口映射 容器间通信 数据卷的管理 当需要查看容器内应用产生的数据或者把容器内数据备份及多个容器数据共享.有两种方式,数据卷以及数据卷容器. 数据卷 数据卷是一个可供容器使用的特殊目录,它绕过文件系统,特性如下: 数据卷可以在容器之间共享和重用 对数据卷的修改会立马生效 对数据卷的更新不会影响镜像 卷会一直存在,直到没有容器使用 其使用类似与mount操作. 在容器内创建一个数据卷 #docker run -d -P --name web -v /webapp