docker跨主机container网络互通 bridge/openvswitch

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了docker跨主机container网络互通 bridge/openvswitch相关的知识,希望对你有一定的参考价值。

参考技术A 实验部分参考官方文档
Use bridge networks 中的Configure the default bridge network部分

这里我用的是kvm虚拟的两个docker-server,virt-manager给两个docker-server分别添加一块网卡,要保证添加的两块网卡桥在宿主机上的同一块网卡上(可通二层帧)

启动docker-server

两台配置相同,docker-server-2 为192.168.200.222(其实这里不配ip也可)
重启网络服务

官方示例配置

这里我的配置为
docker-server

docker-server-2

说明:
bridge为要桥接的接口
fixed-cidr为“可变长子网掩码的网络化分”
mtu为网络传输单元大小
默认网关
dns

两台docker-server上分别启动容器
docker run -it --name ub1 docker.testdomain.com/username/nginx:cus bash

docker-server上的ub1

docker-server-2上的ub1

iptables -P FORWARD DROP

curl测试nginx

最后通过--link containerName:alias参数打开访问

参考:
docker容器namespace点对点通信
简要记录一下openvswitch和namespace的搭配使用

先贴个拓扑

两个docker-server的ip地址是直接配在ens33网卡上的,如果想要两个docker-server中的container互通,则需要采用cidr划分不同子网,并添加相应路由实现(通过ip寻址,也就是路由的方式转发package,这被称为三层通讯)

而本文目的是让两个docker-server中的两个同网段的container互通(在ip的package上封装EtherII的帧头,通过mac地址转发package,这被称为二层通讯)

运行一个容器,找到容器的pid,链接到/var/run/netns/中,让ip netns list 能看到这个ns

紧接着在创建veth,并给到容器内

将veth的peer添加到ovs0中

起一个gre隧道(将ip报文封装到gre协议中)

或者起一个VxLAN也可以

最后在docker-server-1上测试

其中:INPUT中这两条删掉
7 798 DROP all -- * * 0.0.0.0/0 0.0.0.0/0 ctstate INVALID
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited

Dokcer学习笔记 —— 容器网络(跨主机容器网络互通)

文章目录

Docker容器网络

1. 本地网络

docker本地有4种类型的网络:

  1. bridge

这里的bridge和虚拟机里的桥接网络类型不太一样。可以把这个看作
与虚拟机里的NAT类型相似。宿主机能上公网,那么连接此网络的容器也可以上公网。
此为默认网络类型(也就是说运行容器时不指定网络,默认都属于这种
类型)。宿主机上的docker0网卡就是属于此网络.

  1. host

和宿主机共享网络,连接此网络的容器使用ifconfig查看的信息和宿主机一致,没有做NAT转换,类似跑在宿主机上一样。

  1. none

连接此网络的容器没有IP地址等信息,只有lo本地回环网卡。
无法连接公网网络。

  1. container

多个容器连接到此网络,那么容器间可以互相通讯,不和宿
主机共享

1) bridge

所有容器连接到桥,就可以使用外网,使用NAT让容器可以访问外网

[root@docker ~]# ip a

3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:b1:7c:e1:ad brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
所有容器连接到此桥,IP地址都是172.17.0.0/16

1.创建一个名为bridge0的bridge类型的网络,指定网段为10.3.3.0/24(此网
段不能和宿主机已有的网段冲突
),网关为10.3.3.1

[root@docker ~]# docker network create -d bridge --subnet "10.3.3.0/24" --gateway "10.3.3.1" bridge0
b6f4e5f4820b0e613d97d0726fdcbf5c48e735c9bf0c2dc7097fc9e529f96910
可以查看到bridge0这个网络,要删除的话使用docker network rm
[root@docker ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
4b4c77e3837d   bridge    bridge    local
b6f4e5f4820b   bridge0   bridge    local
d1809226464e   host      host      local
bf038e1f5e1f   none      null      local

2.运行容器,指定使用刚创建的网络

[root@docker ~]# docker run -it -d --name centos --network bridge0 centos:latest
d2e97d4f45aa0638ecbbf2fa0135abb709e2256fbd94988abd8cd2ddeb902a4c

3.验证并测试此容器的网络

[root@docker ~]# docker exec centos ip a | grep inet
    inet 127.0.0.1/8 scope host lo
    inet 10.3.3.2/24 brd 10.3.3.255 scope global eth0
可以ping通网关
[root@docker ~]# docker exec centos ping -c3 10.3.3.1
PING 10.3.3.1 (10.3.3.1) 56(84) bytes of data.
64 bytes from 10.3.3.1: icmp_seq=1 ttl=64 time=0.103 ms
64 bytes from 10.3.3.1: icmp_seq=2 ttl=64 time=0.101 ms
64 bytes from 10.3.3.1: icmp_seq=3 ttl=64 time=0.108 ms

--- 10.3.3.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 0.101/0.104/0.108/0.003 ms

可以上网
[root@docker ~]# docker exec centos ping -c1 www.baidu.com
PING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.
64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=127 time=26.2 ms

4.宿主机上会产生一个网卡名为br-xxxxx, IP地址为设置的网关10.3.3.1

[root@docker ~]# ip a
4: br-b6f4e5f4820b: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:25:76:10:57 brd ff:ff:ff:ff:ff:ff
    inet 10.3.3.1/24 brd 10.3.3.255 scope global br-b6f4e5f4820b
       valid_lft forever preferred_lft forever
    inet6 fe80::42:25ff:fe76:1057/64 scope link 
       valid_lft forever preferred_lft forever

2) host

所有的容器与docker host在同一网络中,可以让容器访问,甚至可以让外网主机访问容器中的服务

[root@docker ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
d1809226464e   host      host      local

指定 host 网络运行容器

  • 安装完成后,查看IP地址,发现其使用了docker host地址
  • 好处在于方便访问
  • 坏处在多容器同时运行一种服务,端口冲突
  • 名字ip和宿主机一致,最好只在测试环境使用
[root@docker ~]# docker run -it --network host centos:latest /bin/bash
[root@docker /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether 00:0c:29:c1:2b:2e brd ff:ff:ff:ff:ff:ff
    inet 192.168.44.100/24 brd 192.168.44.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fec1:2b2e/64 scope link 
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:b1:7c:e1:ad brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever

3) none

不能与外网通讯,只有lo本地通迅

[root@docker ~]# docker run -it --network none centos:latest
[root@391a753f6ee9 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    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
ip都没有

4) container

基本不用

容器间共享同一个网络命名空间,实现容器间数据传输

docker run -itd --name c8 --
network=container:c1 centos:latest /bin/bash

c8容器与c1容器的网络一致(包括IP)

跨主机容器间网络

不同的宿主机上的容器通过映射端口,然后通过两台宿主机的IP和映射的端口来通迅。但这样做是利用了宿主机的网络,在某些场景并不方便。能不能建立跨宿主机之间的网络,让容器使用自己的IP就可以通迅呢? 答案是肯定的,而且方案也有很多种: 有docker原生的overlay、macvlan和第三方方案flannel。

1. flannel

flannel是kubernetes[kubə’netis]默认提供网络插件,由CoreOS团队设计
flannel实质上是一种“覆盖网络(overlay network)”, 也就是将TCP数据包装
在另一种网络包里面进行路由转发和通信,目前已经支持UDP、VxLAN、
AWS VPC和GCE路由等数据转发方式。

flannel可使用etcd存储,分配,维护子网信息,最终实现一个大网络内的不同
子网可以互通

  • 是Overlay网络,即覆盖型网络
  • 通过etcd保存子网信息及网络分配信息
  • 给每台Docker Host分配置一个网段
  • 通过UDP传输数据包

2. flannel 环境搭建

1) 环境准备

主机名ip安装软件
node1192.168.44.100etcd,flannel,docker
node2192.168.44.110flannel,docker
  • 配置静态ip

  • 主机名绑定(/etc/hosts)

  • 时间同步

  • 关闭防火墙和SELinux

  • yum源(使用centos安装完系统后的默认yum源再加上下面的docker-ce源)

    # yum install -y yum-utils device-mapper-persistent-data lvm2
    # yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    

2) 搭建过程

第1步: 在node1上安装etcd,flannel,docker

[root@node1 ~]# yum install etcd flannel docker-ce -y

第2步: 在node1上配置etcd服务并启动

[root@node1 ~]# vim /etc/etcd/etcd.conf
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379" 这里要监听
0.0.0.0,这样flanneld服务才能连接
[root@node1 ~]# systemctl start etcd   
[root@node1 ~]# systemctl enable etcd

第3步: 在node1上配置flanneld服务,创建网络,并启动服务

[root@node1 ~]# vim /etc/sysconfig/flanneld 
FLANNEL_ETCD_ENDPOINTS="http://192.168.44.100:2379" 注
意:这里IP改为etcd服务IP

创建一个虚拟网络(我这里创建172.18.0.0/16)
[root@node1 ~]# etcdctl mk //atomic.io/network/config '"Network":"172.18.0.0/16"' 
"Network":"172.18.0.0/16"
[root@node1 ~]# systemctl start flanneld
[root@node1 ~]# systemctl enable flanneld

验证分配的网络(在172.18.0.0/16里随机的)
[root@node1 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.18.0.0/16
FLANNEL_SUBNET=172.18.26.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false

第4步: 在node1上关联docker0网络与flannel0网络,启动docker服务,并验证网络

[root@node1 ~]# systemctl start docker
先启动docker才会产生/etc/docker/目录
[root@node1 ~]# vim /etc/docker/daemon.json

        "bip": "172.18.26.1/24",
        "mtu": 1472

说明:

  • bip 边界IP,和 /run/flannel/subnet.env 配置文件里的对应
  • mtu 网络最大传输单元,也和 /run/flannel/subnet.env 配置文件里
    的对应
这里必须要重启docker服务;否则上面创建的flannel网络不能生效
[root@node1 ~]# systemctl restart docker
[root@node1 ~]# systemctl enable docker

[root@node1 ~]# ip a | grep -E 'docker0|flannel0' 
3: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
    inet 172.18.26.0/16 scope global flannel0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    inet 172.18.86.1/24 brd 172.18.86.255 scope global docker0

第5步: 在node2安装flannel,docker

# yum install flannel docker-ce -y

第6步: 在node2上配置flanneld服务,并启动服务

[root@node2 ~]# vim /etc/sysconfig/flanneld
这里IP改为etcd服务IP
 FLANNEL_ETCD_ENDPOINTS="http://192.168.44.100:2379"
 
[root@node2 ~]# systemctl start flanneld 
[root@node2 ~]# systemctl enable flanneld


验证分配的网络
[root@node2 ~]# cat /run/flannel/subnet.env
FLANNEL_NETWORK=172.18.0.0/16
FLANNEL_SUBNET=172.18.85.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false

第7步: 在node2上启动docker服务,并验证网络

[root@node2 ~]# systemctl start docker
[root@node2 ~]# vim /etc/docker/daemon.json

        "bip": "172.18.85.1/24"
        "mtu": 1472

[root@node2 ~]# systemctl restart docker
[root@node2 ~]# systemctl enable docker

[root@node2 ~]# ip a | grep -E 'docker0|flannel0' 
3: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN group default qlen 500
    inet 172.18.85.0/16 scope global flannel0
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    inet 172.18.85.1/24 brd 172.18.85.255 scope global docker0

第8步: 在两台docker宿主机上分别运行容器

两台都下载busybox镜像(此镜像包含了ifconfig命令,镜像也小,下载快)
[root@node1 ~]# docker pull busybox
[root@node2 ~]# docker pull busybox

[root@node1 ~]# docker run -itd --name=test busybox /bin/sh
8614bb87f07d4666458aad7c5d036650e7f9332fb639f9c49a8afbaca4bcd12b
[root@node1 ~]# docker exec test ifconfig | head -2  
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:1A:02  
          inet addr:172.18.26.2  Bcast:172.18.26.255  Mask:255.255.255.0
          
          
          
[root@node2 ~]# docker run -itd --name=test busybox /bin/sh
a0803754ca1f29ec99a6671c60e7c70926f48af68b45cffcb26dedc9abf01cf0
[root@node2 ~]# docker exec test ifconfig | head -2
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:55:02  
          inet addr:172.18.85.2  Bcast:172.18.85.255  Mask:255.255.255.0

第9步: 在两台宿主机上进行容器连通测试

node1上的test容器ping测试node2上的test容器,不通
[root@node1 ~]# docker exec test ping -c2 172.18.85.2

这里是被防火墙给限制了(启动docker服务,会产生iptables的规则),清除规
则(注意FORWARD链默认规则要改)

[root@node1 ~]# iptables -F
[root@node1 ~]# iptables -P FORWARD ACCEPT
[root@node2 ~]# iptables -F
[root@node2 ~]# iptables -P FORWARD ACCEPT

最后测试
[root@node1 ~]# docker exec test ping -c3 172.18.85.2
PING 172.18.85.2 (172.18.85.2): 56 data bytes
64 bytes from 172.18.85.2: seq=0 ttl=60 time=2.836 ms
64 bytes from 172.18.85.2: seq=1 ttl=60 time=3.299 ms
64 bytes from 172.18.85.2: seq=2 ttl=60 time=1.612 ms

--- 172.18.85.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.612/2.582/3.299 ms

[root@node2 ~]# docker exec test ping -c3 172.18.26.2 
PING 172.18.26.2 (172.18.26.2): 56 data bytes
64 bytes from 172.18.26.2: seq=0 ttl=60 time=1.517 ms
64 bytes from 172.18.26.2: seq=1 ttl=60 time=1.361 ms
64 bytes from 172.18.26.2: seq=2 ttl=60 time=2.031 ms

--- 172.18.26.2 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.361/1.636/2.031 ms

以上是关于docker跨主机container网络互通 bridge/openvswitch的主要内容,如果未能解决你的问题,请参考以下文章

Dokcer学习笔记 —— 容器网络(跨主机容器网络互通)

Docker macvlan host to container 互通

docker实现跨主机通信(使用静态路由方式)

自定义网络实现跨主机 Docker 通信

云原生Docker09-Docker网络详解

8天入门docker系列 —— 第七天 让你的container实现跨主机访问