本节内容:

  • Docker容器跨主机通信方案
  • 环境信息
  • 升级内核
  • 安装docker
  • 防火墙设置和开启内核转发
  • 安装启动consul
  • 启动Docker
  • 创建overlay network
  • 创建容器
  • 测试容器跨主机通信
  • 网络拓扑
  • 抓包分析

一、Docker容器跨主机通信方案

实现跨主机的容器通信有很多种方案,需要看实际的网络状况,是云上环境,私有云环境,还是混合云环境;是否有SDN对网络做特殊控制等等。网络状况不一样,适用的方案也会不一样。比如有的环境可以使用路由的方案,有的却不能使用。不考虑网络模型的话,基本是两个派别:overlay和路由方案。

Docker 1.12中把swarmkit集成到了docker中,本篇博客使用的版本是docker 1.11版本,这是我以前做的一个方案,采用的是overlay方案,现整理出来。

二、环境信息

主机名 操作系统版本 IP地址 Docker版本
node1 CentOS 7.0 172.16.7.151 1.11.0
node2 CentOS 7.0 172.16.7.152 1.11.0

三、升级内核

默认内核:

[root@node1 ~]# uname -r
3.10.-.el7.x86_64

1.升级内核需要使用 elrepo 的yum 源
首先我们导入 elrepo 的key

[root@node1 ~]# rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org

2.安装 elrepo 源

[root@node1 ~]# rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm

3.在yum的ELRepo源中,mainline 为最新版本的内核
安装 ml 的内核

[root@node1 ~]# yum --enablerepo=elrepo-kernel install  kernel-ml-devel kernel-ml -y

4.修改内核启动顺序,默认启动的顺序应该为1,升级以后内核是往前面插入,为0

由于CentOS 7使用grub2作为引导程序 ,所以和CentOS 6有所不同,并不是修改/etc/grub.conf来修改启动项,需要如下操作:

[root@node1 ~]# cat /boot/grub2/grub.cfg |grep menuentry   #查看有哪些内核选项

[root@node1 ~]# grub2-editenv list

[root@node1 ~]# grub2-set-default 

5.重启系统

[root@node1 ~]# shutdown -r now

6.查看内核版本

[root@node1 ~]# uname -r
4.5.-.el7.elrepo.x86_64

四、安装docker

[root@node1 ~]# vim /etc/yum.repos.d/docker.repo
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/$releasever/
enabled=
gpgcheck=
gpgkey=https://yum.dockerproject.org/gpg [root@node1 ~]# yum install -y docker-engine

如果后面升级:

[root@node1 ~]# yum update docker-engine

卸载:


[root@node1 ~]# yum remove docker-engine

五、防火墙设置和开启内核转发

停止firewalld,安装iptables-services

[root@node1 ~]# systemctl stop firewalld.service
[root@node1 ~]# systemctl disable firewalld.service
[root@node1 ~]# yum install -y iptables-services

修改防火墙策略:

[root@node1 ~]# vim /etc/sysconfig/iptables

[root@node1 ~]# systemctl start iptables.service
[root@node1 ~]# systemctl enable iptables.service

开启内核转发,在/etc/sysctl.conf中添加一行配置:

[root@node1 ~]# vim /etc/sysctl.conf 
net.ipv4.ip_forward=

运行下面的命令使内核修改生效:

[root@node1 ~]# sysctl -p

六、安装启动consul

overlay一般需要一个全局的KV存储(sdn controller、etcd、consul)来存储各个主机节点在overlay网络中的配置信息。

# wget https://releases.hashicorp.com/consul/0.6.4/consul_0.6.4_linux_amd64.zip
# unzip -oq consul_0..4_linux_amd64.zip
# mv consul /usr/local/bin/

启动consul:

host-1 Start Consul as a server in bootstrap mode:

[root@node1 ~]# nohup consul agent -server -bootstrap -data-dir /tmp/consul -bind=172.16.7.151 &

host-2 Start the Consul agent:

[root@node2 ~]# nohup consul agent -data-dir /tmp/consul -bind=172.16.7.152 &
[root@node2 ~]# consul join 172.16.7.151
Successfully joined cluster by contacting  nodes.

七、启动Docker

1. 修改docker daemon配置

# cp /usr/lib/systemd/system/docker.service /etc/systemd/system/
# vim /etc/systemd/system/docker.service

在ExecStart那行加上如下的选项,其中ens32是网卡名字:

--cluster-store=consul://localhost:8500 --cluster-advertise=ens32:2376

其中--cluster-store是指向key-value存储的地址,我这里就是consul的地址,consul里保存着整个overlay网络配置和节点信息。--cluster-advertise中是Host1和Host2互通的端口。

2. 启动Docker

执行systemctl daemon-reload使配置生效,然后执行systemctl start docker.service启动docker服务。

# systemctl daemon-reload
# systemctl start docker.service

加入开机自启动:

# systemctl enable docker.service

八、创建overlay network

1. vxlan简介

overlay network这种方式一般也是只需要三层可达,容器就能互通。overlay模式容器有独立IP,不同overlay方案之间的性能差别也是很大的。我这里采用的的vxlan技术。

vxlan(virtual Extensible LAN)虚拟可扩展局域网,是一种overlay的网络技术,使用MAC in UDP的方法进 行封装,共50字节的封装报文头。

用于对VXLAN报文进行封装/解封装,包括ARP请求报文和正常的VXLAN数据报文,在一段封装报文 后通过隧道向另一端VTEP发送封装报文,另一端VTEP接收到封装的报文解封装后根据封装的MAC地址进行转发。VTEP可由支持VXLAN的硬件设备或软件来实现。

从封装的结构上来看,VXLAN提供了将二层网络overlay在三层网络上的能力。

2. 创建overlay network

默认情况下,docker启动后初始化3种网络,这3种都是不能删除的。

# docker network ls
NETWORK ID NAME DRIVER
5944745e7d6d bridge bridge
ce5d1ba0be32 host host
244bb9a34016 none null

在node1主机上创建overlay network:

[root@node1 ~]# docker network create -d overlay --subnet=10.10.10.0/ net1
ca0c50dd3a49e028c3323024b9d6e8f837f4b76889b8d5848046ec0a5948ee2d
[root@node1 ~]# docker network ls
NETWORK ID NAME DRIVER
5944745e7d6d bridge bridge
ce5d1ba0be32 host host
ca0c50dd3a49 net1 overlay
244bb9a34016 none null

在其他主机上执行docker network ls,也会看到新建的这个名字叫net1的overlay网络。

九、创建容器

node1主机创建容器:

[root@node1 ~]# docker run -it --net=net1 --name=contain1 --hostname=test1 --ip=10.10.10.3 --add-host test2:10.10.10.4 centos:centos7
[root@test1 /]# yum install -y iproute net-tools

node2上创建容器:

[root@node2 ~]# docker run -it --net=net1 --name=contain2 --hostname=test2 --ip=10.10.10.4 --add-host test1:10.10.10.3 centos:centos7
[root@test2 /]# yum install -y iproute net-tools

十、测试容器跨主机通信

十一、网络拓扑

容器内部有两个网络接口eth0、eth1。实际上,eth1连接到docker_gwbridge,这可以从ip就能看出。eth0即为overlay network的接口。

十二、抓包分析

在node2主机上使用tcpdump抓包,然后在windows上用wireshark分析。

1. container1容器里ping container2的ip地址:

2. node2主机上抓包

[root@node2 ~]# tcpdump -i ens32 -s  -X -nnn -vvv -w /tmp/package.pcap

3. 把package.pcap传下来放到wireshark上分析

以在container1中ping container2,分析数据包流向:

①container1(10.10.10.3)中ping container2(10.10.10.4),根据container1的路由表,数据包可通过直连网络到达container2。于是arp请求获取container2的MAC地址(在xvlan上的arp这里不详述),得到mac地址后,封包,从eth0发出;

②eth0桥接在net ns 1-ca0c50dd3a中的br0上,这个br0是个网桥(交换机)虚拟设备,需要将来自eth0的包转发出去,于是包转给了vxlan设备;这个可以通过arp -a看到一些端倪:

[root@node1 ~]# ip netns exec -ca0c50dd3a arp -a

③vxlan是个特殊设备,收到包后,由vxlan设备创建时注册的设备处理程序对包进行处理,即进行VXLAN封包(这期间会查询consul中存储的net1信息),将ICMP包整体作为UDP包的payload封装起来,并将UDP包通过宿主机的eth0发送出去。

④152宿主机收到UDP包后,发现是VXLAN包,根据VXLAN包中的相关信息(比如Vxlan Network Identifier,VNI=256)找到vxlan设备,并转给该vxlan设备处理。vxlan设备的处理程序进行解包,并将UDP中的payload取出,整体通过br0转给veth口,net1c2从eth0收到ICMP数据包,回复icmp reply。

从这个通信过程中来看,跨主机通信过程中的步骤如下:

  1. 容器的网络命名空间与overlay网络的网络命名空间通过一对veth pair连接起来,当容器对外通信时,veth pair起到网线的作用,将流量发送到overlay网络的网络命名空间中。
  2. 容器的veth pair对端eth2与vxlan设备通过br0这个Linux bridge桥接在一起,br0在同一宿主机上起到虚拟机交换机的作用,如果目标地址在同一宿主机上,则直接通信,如果不再则通过设置在vxlan1这个vxlan设备进行跨主机通信。
  3. vxlan1设备上会在创建时,由docker daemon为其分配vxlan隧道ID,起到网络隔离的作用。
  4. docker主机集群通过key/value存储共享数据,在7946端口上,相互之间通过gossip协议学习各个宿主机上运行了哪些容器。守护进程根据这些数据来在vxlan1设备上生成静态MAC转发表。
  5. 根据静态MAC转发表的设置,通过UDP端口4789,将流量转发到对端宿主机的网卡上。 根据流量包中的vxlan隧道ID,将流量转发到对端宿主机的overlay网络的网络命名空间中。
  6. 对端宿主机的overlay网络的网络命名空间中br0网桥,起到虚拟交换机的作用,将流量根据MAC地址转发到对应容器内部。

overlay实现容器跨主机通信的更多相关文章

  1. 第 8 章 容器网络 - 052 - overlay 如何实现跨主机通信?

    overlay 如何实现跨主机通信? 在 host2 中运行容器 bbox2: docker run -itd --name bbox2 --network ov_net1 busybox bbox2 ...

  2. Docker 网络管理及容器跨主机通信

    1.网络模式 docker支持四种网络模式,使用--net选项指定: host,--net=host,如果指定此模式,容器将不会获得一个独立的network namespace,而是和宿主机共用一个. ...

  3. overlay 如何实现跨主机通信?- 每天5分钟玩转 Docker 容器技术(52)

    上一节我们在 host1 中运行了容器 bbox1,今天将详细讨论 overlay 网络跨主机通信的原理. 在 host2 中运行容器 bbox2: bbox2 IP 为 10.0.0.3,可以直接 ...

  4. Docker容器跨主机通信

    默认情况下Docker容器需要跨主机通信两个主机节点都需要在同一个网段下,这时只要两个Docker容器的宿主机能相互通信并且该容器使用net网络模式,改实现方式为网桥模式通信: 除此之外我们还可以通过 ...

  5. 052、overlay如何实现跨主机通信?(2019-03-19 周二)

    参考https://www.cnblogs.com/CloudMan6/p/7305989.html   今天开始学习 overlay 网络跨主机通信的原理   root@host01:~# ufw ...

  6. Docker-Docker容器跨主机通信

    Docker默认的网络环境下,单台主机上的Docker容器可以通过docker0网桥直接通信,而不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信.这种端口映射方式对很多集群应用来说极 ...

  7. Docker:macvlan实现容器跨主机通信 [十四]

    一.什么是macvlan 1.macvlan 本身是 linux kernel 模块,其功能是允许在同一个物理网卡上配置多个 MAC 地址, 2.即多个 interface,每个 interface ...

  8. Docker容器跨主机通信之:直接路由方式

    一.Docker网络基本原理 直观上看,要实现网络通信,机器需要至少一个网络接口(物理接口或虚拟接口)与外界相通,并可以收发数据包:此外,如果不同子网之间要进行通信,需要额外的路由机制. Docker ...

  9. Docker容器跨主机通信--overlay网络

    一.Docker主机间容器通信的解决方案 Docker网络驱动 Overlay: 基于VXLAN封装实现Docker原生Overlay网络 Macvlan: Docker主机网卡接口逻辑上分为多个子接 ...

随机推荐

  1. 「Vue」Vue cli3中引用mui-ui问题及解决办法

    1.引用mui.js无效,top-bar划动,numbox点击无效等问题 解决办法: -main.js中import mui from './lib/mui/js/mui.js' Vue.protot ...

  2. CF916E Jamie and Tree

    CF916E Jamie and Tree 题意翻译 有一棵n个节点的有根树,标号为1-n,你需要维护以下三种操作 1.给定一个点v,将整颗树的根变为v 2.给定两个点u, v,将lca(u, v)所 ...

  3. SpringBoot(十一):Spring boot 中 mongodb 的使用

    原文出处: 纯洁的微笑 mongodb是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多.由于很多公司使用了云服务,服务器默认都开放了外网地址,导致前一阵子大批 ...

  4. 【测试笔记】Redis学习笔记(十二)性能测试

    http://blog.csdn.net/yangcs2009/article/details/50781530 Redis测试服务器一 redis_version:2.8.4 www@iZ23s8a ...

  5. What Does “Neurons that Fire Together Wire Together” Mean?

    What Does “Neurons that Fire Together Wire Together” Mean? I’ve heard the phrase “neurons that fire ...

  6. spring boot(三):spring data jpa的使用

    @RequestMapping("/queryUserListByPageNativeQuery") public String queryUserListByPageNative ...

  7. 10个好用的JQuery代码片段收集

    1.预加载图片 (function($) { var cache = []; // Arguments are image paths relative to the current page. $. ...

  8. 网页制作中最有用的免费Ajax和JavaScript代码库

    网上看到的一篇小文,挺有用的,收藏在这. 本文中,我整理了12个免费的Ajax和JavaScript代码库,可以帮助Web开发人员将应用程序提升到一个新水平. Ajax Instant Messeng ...

  9. 20145226夏艺华 《Java程序设计》第6周学习总结

    教材学习内容总结 学习目标 理解流与IO 理解InputStream/OutPutStream的继承架构 理解Reader/Writer继承架构 会使用装饰类 会使用多线程进行并发程序设计 第十章 输 ...

  10. iphone清除数字链接

    <meta name="format-detection" content="telephone=no">