目录
模拟flannel host-gw 直接路由,实现不同主机之间docker容器互相通信
0、实验环境:
- macos 10.15.7
- virtual box 6.1.18
- vagrant 2.2.14
vagrant教程参考 https://zhuanlan.zhihu.com/p/259833884
可以手动安装配置虚拟机,不用vagrant。
- centos7
- docker 19.03.15
一、虚拟机创建
1、docker1 虚拟机Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "centos-7"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.12"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
sudo yum install -y yum-utils lvm2
sudo curl -fsSL https://repo.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
sudo sed -i 's+download.docker.com+repo.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
sudo yum makecache fast
sudo yum install -y docker-ce-19.03.15 docker-ce-cli-19.03.15 containerd.io
sudo rm -f /etc/localtime
sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
SHELL
end
2、docker2虚拟机Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://vagrantcloud.com/search.
config.vm.box = "centos-7"
# Disable automatic box update checking. If you disable this, then
# boxes will only be checked for updates when the user runs
# `vagrant box outdated`. This is not recommended.
# config.vm.box_check_update = false
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
# NOTE: This will enable public access to the opened port
# config.vm.network "forwarded_port", guest: 80, host: 8080
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine and only allow access
# via 127.0.0.1 to disable public access
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
# Create a private network, which allows host-only access to the machine
# using a specific IP.
config.vm.network "private_network", ip: "192.168.33.11"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network "public_network"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
# vb.memory = "1024"
# end
#
# View the documentation for the provider you are using for more
# information on available options.
# Enable provisioning with a shell script. Additional provisioners such as
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "shell", inline: <<-SHELL
# apt-get update
# apt-get install -y apache2
sudo yum install -y yum-utils lvm2
sudo curl -fsSL https://repo.huaweicloud.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
sudo sed -i 's+download.docker.com+repo.huaweicloud.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
sudo yum makecache fast
sudo yum install -y docker-ce-19.03.15 docker-ce-cli-19.03.15 containerd.io
sudo rm -f /etc/localtime
sudo ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
SHELL
end
二、docker网络配置
3、docker1虚拟机 daemon.json 的配置
bip: docker0 网卡的ip
fixed-cidr: docker run默认的ip地址
default-address-pools: 创建其他bridge网桥如docker-compose的网桥,会从这里挑地址
{
"bip": "173.17.0.1/16",
"fixed-cidr": "173.17.0.1/16",
"default-address-pools": [
{
"base": "173.18.0.0/16",
"size": 24
},
{
"base": "173.19.0.0/16",
"size": 24
}
],
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn"
]
}
4、docker机器2 daemon.json 的配置
{
"bip": "174.17.0.1/16",
"fixed-cidr": "174.17.0.1/16",
"default-address-pools": [
{
"base": "174.18.0.0/16",
"size": 24
},
{
"base": "174.19.0.0/16",
"size": 24
}
],
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn"
]
}
三、虚拟机路由表配置
5、docker1虚拟机 的路由表配置
# 添加docker2上容器的ip范围和docker2虚拟机的ip
ip route add 174.0.0.0/8 via 192.168.33.11
6、docker2虚拟机 的路由表配置
# 添加docker1上容器的ip范围和docker1虚拟机的ip
ip route add 173.0.0.0/8 via 192.168.33.12
阶段成果:
首先分别在两台主机上创建一个容器
docker run --rm -d --name nginx1 nginx:alpine
docker run --rm -d --name nginx2 nginx:alpine
这时已经能 traceroute到另一台机器上的容器ip了。
也能ping通另一台机器上的docker0了,因为docker0的ip时算local的,机器的default网络栈直接给应答了,流量都不会走到docker0。
但是还不能ping通 另一台主机上的容器,因为docker默认的iptables规则FORWARD链做了限制:
在docker版本19.03.15中,iptables filter表 FORWARD链中DOCKER-USER会把所有流量都RETURN。
- 疑问:为什么只有另一台主机来的会走到这里?本地主机ping容器ip不会走到FORWARD链?
在docker1虚拟机上ping docker2上的nginx2,这时流量会走到docker2的FORWARD-》DOCKER-USER 被RETURN
在docker2虚拟机上ping nginx2,这时流量不会走到FORWARD,直接会走到nginx2.
可能:因为本地主机中有 arp记录,没有走routing路由,在二层直接发给docker0 ,没有走iptables?
你能帮帮我吗?
四、虚拟机iptables规则配置
7、docker1虚拟机 的iptables配置
iptables -I DOCKER-USER -s 0.0.0.0/0 -d 0.0.0.0/0 -j LOG --log-level 4
iptables -I DOCKER-USER -s 0.0.0.0/0 -d 0.0.0.0/0 -j ACCEPT
8、docker2虚拟机 的iptables配置
iptables -I DOCKER-USER -s 0.0.0.0/0 -d 0.0.0.0/0 -j LOG --log-level 4
iptables -I DOCKER-USER -s 0.0.0.0/0 -d 0.0.0.0/0 -j ACCEPT
9、ping
# 在docker1 上
docker exec nginx1 ip a
173.17.0.2/16
# 在docker2 上
docker exec nginx2 ip a
174.17.0.2/16
# 在docker1 上 nginx1 ping docker2上的nginx2
docker exec nginx1 ping 174.17.0.2