专栏首页用户3749098的专栏Docker网络——实现容器间通信、容器与外网通信以及容器的跨主机访问

Docker网络——实现容器间通信、容器与外网通信以及容器的跨主机访问

前言

  • 建议使用自定义的网桥来控制哪些容器可以相互通信,还可以自动DNS解析容器名称到IP地址。Docker提供了创建这些网络的默认网络驱动程序,你可以创建一个新的Bridge网络,Overlay或Macvlan网络。你还可以创建一个网络插件或远程网络进行完整的自定义和控制。
  • 你可以根据需要创建任意数量的网络,并且可以在任何给定时间将容器连接到这些网络中的零个或多个网络。此外,您可以连接并断开网络中的运行容器,而无需重新启动容器。当容器连接到多个网络时,其外部连接通过第一个非内部网络以词法顺序提供。

容器间通信

  • 1.创建一个bridge模式的网络
[root@server1 ~]# docker network create --driver bridge my_net1
[root@server1 ~]# docker network ls 

由上图我们可以看到创建的网络ID为4554d78082da ,使用ip addr查看本机网络:

查看docker自定义网络如下图,当我们创建好自定义网络后,自定义为其分配IP网段和网关。

docker的bridge自定义网络之间默认是有域名解析的;

docker的bridge自定义网络与系统自带的网桥之间默认是有解析的;

但是docker的系统自带的网桥之间默认是没有解析的。

  • 再创建一个bridge的网络,自定义ip和网关

[root@server1 ~]# docker network create --driver bridge --subnet 172.20.0.0/24 --gateway 172.20.0.1 my_net2

[root@server1 ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

f3aff7e4dad5 bridge bridge local

c5f20e91b8ca host host local

4554d78082da my_net1 bridge local

28b91234a14b my_net2 bridge local

0e8b7355d807 none null local

[root@server1 ~]# docker network inspect my_net2

"IPAM": {

"Driver": "default",

"Options": {},

"Config": [

{

"Subnet": "172.20.0.0/24",

"Gateway": "172.20.0.1"

}

]

},

  • ctrl+p+q,再创建一个容器,使用网络my_net2。

使用–ip参数可以指定容器ip地址,但必须是在自定义网桥上(自定义的ip地址和网关地址),

默认的bridge模式不支持,同一网桥上的容器是可以通信的

[root@server1 ~]# docker run -it --name vm2 --network=my_net2 --ip=172.20.0.10 ubuntu
root@a77dd40e0a04:/# ip a

  • 建立两个容器之间的连接。

[root@server1 ~]# docker ps

[root@server1 ~]# docker network connect my_net1 vm2

[root@server1 ~]# docker attach vm2

root@a77dd40e0a04:/# ip a

  • 测试:两个容器是否可以直接ping通

在容器vm2内(IP=172.20.0.10)ping vm1(IP=172.19.0.2)

root@a77dd40e0a04:/# ping 172.19.0.2

以上我们实现了:使用自定义网络实现容器间的通信

注意:

  • docker的bridge自定义网络之间:双方可以随便添加对方的网卡
  • docker的bridge自定义网络与系统自带的网桥之间:只能是,系统自带的网桥对应的容器 添加 bridge自定义网络对应的容器的网卡。而反过来会报错。
  • 但是docker的系统自带的网桥之间:是可以通信的,因为是在一个网络桥接上。
  • docker 1.10开始,内嵌了一个DNS server。dns解析功能必须在自定义网络中使用。

容器与外网通信

  • 容器如何访问外网是通过iptables的SNAT实现的?

外网如何访问容器?

  • 端口映射,-p指定对应端口

外网访问容器用到了docker-proxy和iptables DNAT

宿主机访问本机容器使用的是iptables DNAT

外部主机访问容器或容器之间的访问是docker-proxy实现

示例:

  • 查看当前iptable的nat表火墙策略
[root@server1 ~]# iptables -t nat -nL

  • 创建nginx的容器,配置端口映射。

[root@server1 ~]# docker run -d --name nginx -p 80:80 nginx

[root@server1 ~]# docker port nginx

80/tcp -> 0.0.0.0:80

[root@server1 ~]# netstat -ntpl | grep 80

tcp6 0 0 :::80 :::* LISTEN 3901/docker-proxy

[root@server1 ~]# iptables -t nat -nL

我们可以在nat表的最后一行看到使用了端口转发。

Docker的跨主机网络访问

跨主机网络解决方案

  • docker原生的overlay和macvlan
  • 第三方的flannel、weave、calico

众多网络方案是如何与docker集成在一起的?

  • libnetwork docker容器网络库
  • CNM (Container Network Model)这个模型对容器网络进行了抽象

CNM三类组件

组件

功能

Sandbox

容器网络栈,包含容器接口、dns、路由表。(namespace)

Endpoint

作用是将sandbox接入network (veth pair)

Network

包含一组endpoint,同一network的endpoint可以通信

macvlan网络方案的实现

  • Macvlan是一个新的尝试,是真正的网络虚拟化技术的转折点。Linux实现非常轻量级,因为与传统的Linux Bridge隔离相比,它们只是简单地与一个Linux以太网接口或子接口相关联,以实现网络之间的分离和与物理网络的连接。
  • Macvlan提供了许多独特的功能,并有充足的空间进一步创新与各种模式。这些方法的两个高级优点是绕过Linux网桥的正面性能以及移动部件少的简单性。删除传统上驻留在Docker主机NIC和容器接口之间的网桥留下了一个非常简单的设置,包括容器接口,直接连接到Docker主机接口。由于在这些情况下没有端口映射,因此可以轻松访问外部服务。
实验准备

(1)两台虚拟机

(2)两台虚拟机上添加两块虚拟网卡,并安装好相应的docker服务(因为我们模拟的时docker容器的跨主机访问)

  • 清除两台主机上之前有关网络的设置,并激活新添加的网卡eth1。

[root@server1 ~]# docker network prune

[root@server1 ~]# docker network rm my_net1 my_net2

[root@server1 ~]# docker network ls

NETWORK ID NAME DRIVER SCOPE

f3aff7e4dad5 bridge bridge local

c5f20e91b8ca host host local

0e8b7355d807 none null local

[root@server1 ~]# ip link set up eth1

[root@server1 ~]# ip add

macvlan本身是linxu kernel的模块,本质上是一种网卡虚拟化技术。其功能是允许在同一个物理网卡上虚拟出多个网卡,通过不同的MAC地址在数据链路层进行网络数据的转发,一块网卡上配置多个 MAC 地址(即多个 interface),每个interface可以配置自己的IP,Docker的macvlan网络实际上就是使用了Linux提供的macvlan驱 动。

因为多个MAC地址的网络数据包都是从同一块网卡上传输,所以需要打开网卡的混杂模式ip link set eth1 promisc on。

  • 打开server1和server2的eth1网卡的混杂模式
[root@server1 ~]# ip link set eth1 promisc on
[root@server1 ~]# ip addr show | grep eth1

注意:如果不开启混杂模式,会导致macvlan网络无法访问外界,具体在不使用vlan时,表现为无法ping通路由,无法ping通同一网络内其他主机。

  • 在两台主机上各创建macvlan网络

创建macvlan网络不同于桥接模式,需要指定网段和网关(因为要保证跨主机上网段和网关是相同的),并且都得是真实存在的。

server1:

[root@server1 ~]# docker network create -d macvlan mac1 --subnet=172.22.0.0/24 --gateway=172.22.0.1 -o parent=eth1

[root@server1 ~]# docker network ls

server2:

[root@server2 ~]# docker network create -d macvlan mac1 --subnet=172.22.0.0/24 --gateway 172.22.0.1 -o parent=eth1

[root@server2 ~]# docker network ls

macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络

vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094

  • 在两台主机上分别使用创建的macvlan1运行一个容器

server1:

[root@server1 ~]# docker run -it --name vm1 --network=mac1 --ip=172.22.0.10 ubuntu
root@12542041d9de:/# ip a

server2:

root@12542041d9de:/# ping 172.22.0.20

  • macvlan模式不依赖网桥,所以brctl show查看并没有创建新的bridge,但是查看容器的网络,会看到虚拟网卡对应了一个interface是17。

[root@server1 ~]# brctl show

bridge name bridge id STP enabled interfaces

docker0 8000.024290f2797b no

[root@server1 ~]# docker attach vm1

root@12542041d9de:/# ip a

  • 查看宿主机的网络,17正是虚机的eth1网卡
[root@server1 ~]# ip addr show eth1

可见,容器的 eth0 就是宿主机的eth1通过macvlan虚拟出来的interface。容器的interface直接与主机的网卡连接,这种方案使得容器无需通过NAT和端口映射就能与外网直接通信(只要有网关),在网络上看起来与其他独立主机没有区别。

macvlan会独占主机的网卡的解决方案

  • 前面说过macvlan会独占主机网卡,但可以使用vlan子接口实现多macvlan网络

vlan可以将物理二层网络划分为4094个逻辑网络,彼此隔离,vlan id取值为1~4094

我们只需要在创建容器时使用vlan子接口就可以i解决:

server1:

[root@server1 ~]# docker run -it --name vm4 --network=mac1 --ip=172.22.0.30 ubuntu
root@4ce2fc7c4a5f:/# ip a

测试是否能ping通server2上的vm2容器。

root@4ce2fc7c4a5f:/# ping 172.22.0.20

原文链接:https://blog.csdn.net/even160941/article/details/98523034?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-2.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-2.nonecase

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Docker 容器跨主机多网段通信解决方案

    一、MacVlan 实现Docker的跨主机网络通信的方案有很多,如之前博文中写到的通过部署 Consul服务实现Docker容器跨主机通信

    小手冰凉
  • 部署 Consul服务实现Docker容器跨主机通信

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

    小手冰凉
  • 『中级篇』overlay网络和etcd实现多机的容器通信(31)

    PS:本次通过第三方工具etcd分布式的方式完成2台机器,2个容器组件网络,实现相互的访问,这里只是通过ping的方式,如果按照上次说的 flask-redis...

    IT架构圈
  • 『中级篇』overlay网络和etcd实现多机的容器通信(31)

    PS:本次通过第三方工具etcd分布式的方式完成2台机器,2个容器组件网络,实现相互的访问,这里只是通过ping的方式,如果按照上次说的 flask-redis...

    IT架构圈
  • DCOS番外篇之Docker跨主机通信

    今天我们来聊一聊容器如何跨主机通信,总所周知的是docker有多种网络模式:HOST、BRIDGE、null等,从多主机通信的应用场景出发,来谈已有的的解决方案...

    zouyee
  • Docker容器学习梳理--容器间网络通信设置(Pipework和Open vSwitch)

    自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求。容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容...

    洗尽了浮华
  • Docker网络——单host网络

    前言 前面总结了Docker基础以及Docker存储相关知识,今天来总结一下Docker单主机网络的相关知识。毋庸置疑,网络绝对是任何系统的核心,他在Docke...

    魏守峰
  • Docker跨主机网络——overlay

    前言 在Docker网络——单host网络一文中,我为大家总结了Docker的单机网络相关知识和操作,单机网络比较容易。本文我为大家总结Docker跨主机通信相...

    魏守峰
  • Docker 入门到实战教程(四)容器链接

    在使用Docker容器时,我们需要访问容器的内部网络,或需要在容器间相互访问。Docker 容器默认不会开放任何端口,因此需要将容器与宿主机进行端口映射,使容器...

    小东啊
  • Docker 网络模型

    单机容器内的通信是通过 docker 自带的网桥连接互通的,如果是集群,那么做这些单机网络模型就行不通了,因为集群必然会将一个服务的多个任务需要分布到不同的机器...

    张乘辉
  • 理解Docker跨多主机容器网络

    将宿主机A的端口P映射到容器C的网络空间监听的端口P’上,仅提供四层及以上应用和服务使用。这样其他主机上的容器通过访问宿主机A的端口P实 现与容器C的通信。显然...

    Rainbond开源
  • 理解Docker跨多主机容器网络

    Rainbond开源
  • 花了三天时间终于搞懂 Docker 网络了

    容器网络实质上是由 Dokcer 为应用程序所创造的虚拟环境的一部分,它能让应用从宿主机操作系统的网络环境中独立出来,形成容器自有的网络设备、IP 协议栈、端口...

    syy
  • docker 学习资料收集

    docker镜像怎么迁移到其他的服务器 http://www.talkwithtrend.com/Question/123589

    用户1177503
  • Docker | Docker技术基础梳理(五) - Docker网络管理

    容器的网络默认与宿主机、与其他容器相互隔离,且容器中可以运行一些网络应用,比如nginx、web应用、数据库等,如果需要让外部也可以访问这些容器中运行的网络应用...

    咸鱼学Python
  • 容器化之路Docker网络核心知识小结,理清楚了吗?

      Docker网络是容器化中最难理解的一点也是整个容器化中最容易出问题又难以排查的地方,加上使用Kubernets后大部分人即使是专业运维如果没有扎实的网络知...

    欢醉
  • flannel跨主网络通信方案(UDP、VXLAN、HOST-GW)详解

    坚持看下去,文末送机械键盘一个 本文中,笔者主要结合自己使用flannel心得,以及flannel的技术演进,介绍下flannel网络实现方案。在没有介绍fla...

    用户5166556
  • 盘点Kubernetes网络问题的4种解决方案

    由于在企业中部署私有云的场景会更普遍,所以在私有云中运行Kubernetes + Docker集群之前,就需要自己搭建符合Kubernetes要求的网络环境。现...

    孙杰
  • docker bridge 到 k8s pod 跨节点网络通信机制演进

    2020 还没来得及品味就即将过去一个季度,愿剩下的时光不被辜负。进入正题,docker container是单进程模式,能够解决一些单一的问题,在现实中,我们...

    用户5166556

扫码关注云+社区

领取腾讯云代金券