zoukankan      html  css  js  c++  java
  • overlay实现容器跨主机通信

    本节内容:

    • 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.0-229.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 0

    5.重启系统

    [root@node1 ~]# shutdown -r now

    6.查看内核版本

    [root@node1 ~]# uname -r
    4.5.2-1.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=1
    gpgcheck=1
    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=1

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

    [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.6.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 1 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/24 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 0 -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 1-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地址转发到对应容器内部。
  • 相关阅读:
    在可变字符串类型varchar建立索引时有什么要注意的吗?
    单表行数多少时适合分库分表?
    存储字符串时怎么设计或者考量那?
    小数类型选择float、double正确吗?
    解决mysql java.sql.SQLException: The server time zone value‘XXXXXX' is unrecognized or represents...
    阿里云 Windows Server 2012 密码过期设置
    规则引擎 drools
    day-06
    微信小程序前端开发踩坑(一)
    CornerStone使用跳坑总结(陆续更新)
  • 原文地址:https://www.cnblogs.com/zhaojiankai/p/7801109.html
Copyright © 2011-2022 走看看