Open bingoogolapple opened 7 years ago
当 docker0 所提供的默认 ip 地址范围不能满足我们希望为容器分配的 ip 地址时,可以通过 Linux 自带的 ifconfig 命令来修改 docker0。不知为何在 Ubuntu 虚拟机中使用这种方式没生效,重启 Docker 守护进程后就失效了
➜ ~ sudo ifconfig docker0 192.168.200.1 netmask 255.255.255.0
[sudo] password for ubuntuone:
➜ ~ ifconfig
docker0 Link encap:Ethernet HWaddr 02:42:e4:b8:02:1f
inet addr:192.168.200.1 Bcast:192.168.200.255 Mask:255.255.255.0
inet6 addr: fe80::42:e4ff:feb8:21f/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:32 errors:0 dropped:0 overruns:0 frame:0
TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:2144 (2.1 KB) TX bytes:648 (648.0 B)
...
添加虚拟网桥
➜ ~ sudo brctl addbr br0
➜ ~ sudo ifconfig br0 192.168.100.1 netmask 255.255.255.0
➜ ~ ifconfig
br0 Link encap:Ethernet HWaddr aa:cc:31:3c:b4:ba
inet addr:192.168.100.1 Bcast:192.168.100.255 Mask:255.255.255.0
inet6 addr: fe80::a8cc:31ff:fe3c:b4ba/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:508 (508.0 B)
在 Docker 守护进程启动配置文件 /lib/systemd/system/docker.service 中的 ExecStart 末尾增加参数 -b=br0 或者用空格隔开 -b br0,并重启 Docker 守护进程
sudo vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H fd:// -H tcp://0.0.0.0:2375 -b=br0
ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H fd:// -H tcp://0.0.0.0:2375 -b br0
sudo systemctl daemon-reload
sudo service docker restart
ps -ef | grep docker
此时新建一个容器就能看见上面的配置已经生效
➜ ~ docker run -it --name nwt1 bingoogolapple/bga-ubuntu bash
root@4c07917612af:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:c0:a8:64:02
inet addr:192.168.100.2 Bcast:0.0.0.0 Mask:255.255.255.0
inet6 addr: fe80::42:c0ff:fea8:6402/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0 frame:0
TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:508 (508.0 B) TX bytes:508 (508.0 B)
...
容器启动时的选项 --link 参数。先启动容器 cct1,然后启动容器 cct2 并让它连接到 cct1 上指定别名为 web_server,此时 cct2 中会有很多以 WEB_SERVER 开头的环境变量,在 hosts 中也添加了 web_server 的地址映射,这样的话重启 Docker 守护进程后在 cct2 中还是能通过 web_server 来访问 cct1
需要注意的是:容器 cct2 依赖容器 cct1,所以必须先启动容器 cct1 然后再启动容器 cct2
docker run --link=[CONTAINER_NAME]:[ALIAS]
➜ test docker run -it -d --name cct1 -p 8080:80 bingoogolapple/bga-ubuntu nginx -g "daemon off;"
➜ test docker run -it --link=cct1:web_server --name cct2 bingoogolapple/bga-ubuntu
root@fe4dafdfb110:/# ping web_server
PING web_server (172.17.0.2): 56 data bytes
64 bytes from 172.17.0.2: icmp_seq=0 ttl=64 time=0.168 ms
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.077 ms
^C--- web_server ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.077/0.122/0.168/0.046 ms
root@fe4dafdfb110:/# env
WEB_SERVER_PORT_80_TCP=tcp://172.17.0.2:80
HOSTNAME=fe4dafdfb110
TERM=xterm
WEB_SERVER_PORT=tcp://172.17.0.2:80
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WEB_SERVER_PORT_80_TCP_PROTO=tcp
PWD=/
SHLVL=1
WEB_SERVER_PORT_80_TCP_ADDR=172.17.0.2
HOME=/root
WEB_SERVER_NAME=/cct2/web_server
WEB_SERVER_PORT_80_TCP_PORT=80
_=/usr/bin/env
root@fe4dafdfb110:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 web_server fc743f8120fc cct1
172.17.0.3 fe4dafdfb110
修改 Docker 守护进程的启动选项 --icc=false 即可拒绝所有容器间的互联
在 --icc=false 时阻断所有容器之间的访问,设置 --iptables=true 时,仅仅允许使用 --link 选项配置的容器进行相互的访问
sudo vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H fd:// -H tcp://0.0.0.0:2375 --icc=false --iptables=true
sudo systemctl daemon-reload
sudo service docker restart
创建4个测试容器
docker run -it -d --name cct1 -p 8080:80 bingoogolapple/bga-ubuntu nginx -g "daemon off;"
docker run -it --name cct2 bingoogolapple/bga-ubuntu
docker run -it --link=cct1:web_server --name cct3 bingoogolapple/bga-ubuntu
解决 Docker 的 bug
看到 Chain FORWARD (policy ACCEPT) 里有一行将所有的都 DROP 了,这是 Docker 的 bug,接下来清空 iptables 并重启 Docker 守护进程
sudo iptables -L -n
sudo iptables -F
sudo service docker restart
docker restart cct1 cct2 cct3 cct4
sudo iptables -L -n
此时从 Chain DOCKER 能看到 cct3 和 cct1 的链接、cct4 和 cct1 的链接
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.4 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.4 tcp spt:80
ACCEPT tcp -- 172.17.0.5 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.5 tcp spt:80
此时 cct4 的 hosts 文件内容,此时就能通过 curl web_server 或 curl cct1 或 curl 207b9ac09b69 来访问 cct1 中的服务,「注意只是访问 cct1 里面的服务,使用 ping 命令还是 ping 不通 cct1 的」
root@a7e8760c52e1:/# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 web_server 207b9ac09b69 cct1
172.17.0.5 a7e8760c52e1
sysctl net.ipv4.conf.all.forwarding
查看 filter 表,也可以忽略 -t 参数,因为 iptables 默认指定的就是 filter 表。包含 INPUT、FORWARD、OUTPUT 三个链,也包含了一个名为 DOCKER 的链,这个 DOCKER 的链实际上就是 FORWARD 链中 DOCKER 操作的子链
➜ ~ sudo iptables -t filter -L -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER-ISOLATION all -- 0.0.0.0/0 0.0.0.0/0
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
DROP all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.4 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.4 tcp spt:80
ACCEPT tcp -- 172.17.0.5 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.5 tcp spt:80
Chain DOCKER-ISOLATION (1 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
限制 192.168.56.112 通过 TCP 协议访问 172.17.0.2 的 80 端口
➜ ~ sudo iptables -I DOCKER -s 192.168.56.112 -d 172.17.0.2 -p TCP --dport 80 -j DROP
➜ ~ sudo iptables -L -n
...
Chain DOCKER (1 references)
target prot opt source destination
DROP tcp -- 192.168.56.112 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.4 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.4 tcp spt:80
ACCEPT tcp -- 172.17.0.5 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.5 tcp spt:80
...
删除上一步添加的规则。删除 filter 表中 DOCKER 链表的第一条规则
➜ ~ sudo iptables -t filter -D DOCKER 1
➜ ~ sudo iptables -L -n
...
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.4 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.4 tcp spt:80
ACCEPT tcp -- 172.17.0.5 172.17.0.2 tcp dpt:80
ACCEPT tcp -- 172.17.0.2 172.17.0.5 tcp spt:80
...
增加别名方便重置测试环境 vim + .zshrc 【注意是单引号】
alias stopWeave='weave stop-plugin && weave stop-router && weave stop-proxy'
alias stopAllContainer='docker stop $(docker ps -aq)'
alias rmAllContainer='docker rm -v $(docker ps -aq)'
alias stopAndRmAllContainer='docker stop $(docker ps -aq) && docker rm -v $(docker ps -aq)'
alias resetWeaveTest='weave stop-plugin && weave stop-router && weave stop-proxy && docker stop $(docker ps -aq) && docker rm -v $(docker ps -aq)'
alias reloadDaemonAndRestartDocker='sudo systemctl daemon-reload && sudo service docker restart'
两台主机的 ip
10.211.55.3
10.211.55.5
修改主机 /etc/network/interfaces 文件
auto br0
iface br0 inet static
address 10.211.55.3
netmask 255.255.255.0
gateway 10.211.55.1
bridge_ports eth0
在 Docker 守护进程启动配置文件 /lib/systemd/system/docker.service 中的 ExecStart 末尾增加参数,并重启 Docker 守护进程
Host1: 10.211.55.64/26
地址范围: 10.211.55.65~10.211.55.126
Host2: 10.211.55.128/26
地址范围: 10.211.55.129~10.211.55.190
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H fd:// -H tcp://0.0.0.0:2375 -b=br0 --fixed-cidr='10.211.55.64/26'
sudo systemctl daemon-reload
sudo service docker restart
ps -ef | grep docker
它是一个高质量的,多层的虚拟交换机,使用开源 Apache2.0 许可协议,主要实现代码是可移植的 C 代码。目的是让大规模网络自动化可以通过编程扩展,同时仍然支持标准的管理接口和协议
操作步骤:
在 192.168.56.111 上操作
sudo ovs-vsctl show
建立一个名为 obr0 的 ovs 网桥
sudo ovs-vsctl add-br obr0
为 obr0 网桥添加一个名为 gre0 的 gre 接口,如果报错请看 http://stackoverflow.com/questions/35689488/ovs-vsctl-error-detected-while-setting-up-bridge
sudo ovs-vsctl add-port obr0 gre0
设置 gre0 接口,类型为 gre,指定要连接的远程服务器的地址
sudo ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.56.112
sudo ovs-vsctl show
建立本机 Docker 容器需要使用的虚拟网桥
新建一个名为 br0 的网桥
sudo brctl addbr br0
为 br0 网桥设置网络地址
sudo ifconfig br0 192.168.1.1 netmask 255.255.255.0
为 br0 网桥添加 ovs 网桥的链接
sudo brctl addif br0 obr0
查看当前网桥链接状态
sudo brctl show
编辑 Docker 守护进程启动配置选项,设置 Docker 容器使用 br0 网桥
sudo vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H fd:// -H tcp://0.0.0.0:2375 -b=br0
sudo systemctl daemon-reload
sudo service docker restart
ps -ef | grep docker
此时运行一台容器就能 ping 同 192.168.56.112 了
docker run -it --name nt1 bga/tv
ping 192.168.56.112
如果 ping 不通就添加一条路由信息,告诉路由表通过本机的 enp0s8 网卡来连接,在 192.168.56.112 这台机器上能找到 192.168.2.0/24 这个网段
route
sudo ip route add 192.168.2.0/24 via 192.168.56.112 dev enp0s8
在 192.168.56.112 上操作
sudo ovs-vsctl show
建立一个名为 obr0 的 ovs 网桥
sudo ovs-vsctl add-br obr0
为 obr0 网桥添加一个名为 gre0 的 gre 接口 http://stackoverflow.com/questions/35689488/ovs-vsctl-error-detected-while-setting-up-bridge
sudo ovs-vsctl add-port obr0 gre0
设置 gre0 接口,类型为 gre,指定要连接的远程服务器的地址
sudo ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.56.111
sudo ovs-vsctl show
建立本机 Docker 容器需要使用的虚拟网桥
新建一个名为 br0 的网桥
sudo brctl addbr br0
为 br0 网桥设置网络地址
sudo ifconfig br0 192.168.2.1 netmask 255.255.255.0
为 br0 网桥添加 ovs 网桥的链接
sudo brctl addif br0 obr0
查看当前网桥链接状态
sudo brctl show
编辑 Docker 守护进程启动配置选项,设置 Docker 容器使用 br0 网桥
sudo vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --label=name=docker_server_ubuntutwo -H fd:// -H tcp://0.0.0.0:2375 -b=br0
重启 Docker 守护进程
sudo systemctl daemon-reload
sudo service docker restart
ps -ef | grep docker
此时运行一台容器就能 ping 同 192.168.56.111 了
docker run -it --name nt1 bga/tv
ping 192.168.56.111
如果 ping 不通就添加一条路由信息,告诉路由表通过本机的 enp0s8 网卡来连接,在 192.168.56.111 这台机器上能找到 192.168.1.0/24 这个网段
route
sudo ip route add 192.168.1.0/24 via 192.168.56.111 dev enp0s8
在实际的生成环境中通过 shell 脚本来讲这一系列的操作自动化
建立一个虚拟的网络,用于将运行在不同主机的 Docker 容器连接起来,通过 weave 来为容器指定希望的 ip 地址和 ip 地址段
安装 weave
sudo curl -L git.io/weave -o /usr/local/bin/weave
sudo chmod a+x /usr/local/bin/weave
192.168.56.111 上运行
启动 weave
weave launch
启动名为 test_weave_11 的容器,并设置 ethwe 网络设备对应的 ip
weave run 192.168.5.11/24 -itd --name test_weave_11 bga/tv
或
docker run -itd --name test_weave_11 bga/tv
weave attach 192.168.5.11/24 test_weave_11
进入容器
docker attach test_weave_11
执行 ifconfig 命令能看到多了一个叫 ethwe 网络设备,在这个设备中的 ip 地址就是执行 wave 命令启动容器时指定的 ip
ifconfig
ping 192.168.5.22
ping test_weave_21
192.168.56.112 上运行
启动 weave 并指定另一台主机的 ip 地址
weave launch 192.168.56.111
启动名为 test_weave_21 的容器,并设置 ethwe 网络设备对应的 ip
cid=$(weave run 192.168.5.22/24 -it --name test_weave_21 bga/tv)
这里的 cid 就是使用 weave 命令运行的容器的 id
echo $cid
进入容器
docker attach $cid
执行 ifconfig 命令能看到多了一个叫 ethwe 网络设备,在这个设备中的 ip 地址就是执行 wave 命令启动容器时指定的 ip
ifconfig
ping 192.168.5.11
ping test_weave_11
基本概念
是 OSI 七层模型中数据链路层的一种设备,用来通过 MAC 地址,也就是网络设备的物理地址来对网络进行划分,并且在不同的网络之间传递数据
Linux 虚拟网桥的特点:
通常来说 IP 地址是三层协议的内容,也就是网络层协议的内容,不应该出现在二层设备上,但 Linux 的虚拟网桥是通用网络设备抽象的一种,只要是网络设备就能够设置 IP 地址,当虚拟网桥拥有 IP 后 Linux 就可以通过路由表或者 IP 表规则在网络层定位网桥,这就相当于拥有了一个隐藏的虚拟网卡,而这个网卡的名字就是虚拟网桥的名字,也就是上面的 docker0