参考文献:
https://blog.csdn.net/wangshuaiwsws95/article/details/80687384
- 本方案,未依赖任何第三方插件。
- 本方案,仅仅是测试研究分析,不能用于生产。
- 必须是新部署的docker环境,
- 因为文章中有些命令使用了规则的序号,
- 如果不是最新部署的docker环境,序号可能不一样,导致iptables命令失败,报查询不到chain/name等。
一、背景
目前正在研究docker的网络,kubernetes网络的相关解决方案,如calico;
而calico的底层也是调用iptables, ipset来实现的。 如何解决跨主机通信是值得研究的。
分析完这个后,有助于理解calico是如何在docker、k8s环境中应用的。
二、概述
- docker默认情况下:
单台主机上的docker容器间的通信可以通过docker0网桥直接通信 - 如何解决呢?
其中一方案是,通过映射端口来进行通信;
但是,此方案,不能满足我们的使用场景。 - 希望达到的效果是,通过docker容器自己的IP直接进行通信
三、测试环境介绍
-
物理环境介绍
主机名 IP 系统 a-master 172.16.91.131 centos7.5 a-slave1 172.16.91.132 centos7.5 -
docker版本
四、情景构造(描述需求)
有两个物理主机1和主机2,在各自宿主机上启动一个容器,启动成功之后,两个容器分别运行在两个宿主机之上,默认的IP地址分配如图所示,这也是Docker自身默认的网络
此时两台主机上的Docker容器如何直接通过IP地址进行通信?
每个节点开启ipv4路由转发功能,使得流量可以在docker0跟物理机网卡之间进行通信。
然后修改跟docker有关的iptables规则。 接下来尝试尝试.
五、环境准备
5.1 部署docker
-
更新yum源
yum install -y yum-utils device-mapper-persistent-data lvm2 yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
-
配置私有仓库地址(添加自己的加速器)
mkdir -p /etc/docker tee /etc/docker/daemon.json <<-'EOF' { "registry-mirrors": ["https://XXXXXX.mirror.aliyuncs.com"] }EOF
-
配置master节点的docker子网段信息
vim /lib/systemd/system/docker.service
-
配置slave节点的docker子网段信息
vim /lib/systemd/system/docker.service
-
重新启动docker服务(master,slave1节点)
systemctl enable docker systemctl daemon-reload systemctl restart docker
5.2 创建容器
-
在master上创建容器
docker run --name m-web1 -itd busybox
-
在slave上创建容器
docker run --name s-web1 -itd busybox
5.3 具体步骤
-
查看a-master,a-slave节点上的ipv4路由是否开启
-
查看是否开启?
sysctl -a | grep net.ipv4.ip_forward
net.ipv4.ip_forward=0,说明未开启
-
如何开启?
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf sysctl -p
-
-
清理nat表中的POSTROUTING链(master节点上操作)
- 清理前测试
- 清理POSTROUTING链(目的:防止进行NAT转换)
iptables -t nat -F POSTROUTING
- 清理后测试
- 清理前测试
-
查看a-slave节点上filter表
-
修改a-slave节点上filter表中FORWARD的默认策略
iptables -P FORWARD ACCEPT
iptables -t filter -R DOCKER-ISOLATION-STAGE-2 1 -j ACCEPT
六、测试
在master节点进行测试
注意,这里仅仅可以master节点上去ping slave节点, 反之不行,
如果想实现双向通信的话, 操作步骤跟上面类似。
七、扩展测试
7.1 测试net.ipv4.ip_forward参数
也就是说,docker0跟物理机网卡ens33进行通信是通过这个参数进行设置的。
7.2 修改a-slave节点上filter表中DOCKER-ISOLATION-STAGE-2链中的跳转动作
-
修改成DROP? 查看
iptables -t filter -R DOCKER-ISOLATION-STAGE-2 1 -j DROP
-
修改成REJECT? 查看
iptables -t filter -R DOCKER-ISOLATION-STAGE-2 1 -j REJECT
-
总结DROP跟REJECT的区别?
- DROP
- 网络可达,
- 返回的数据可以到达docker0, 然后就被iptables的DROP过滤掉了
- REJECT
- 网络不可达,
- 报protocol 1 port 34841 unreachable, length 92
- DROP
八、iptables 知识点补充
https://www.cnblogs.com/davidwang456/p/3540837.html
默认情况下,查询的是filter表, 如果要操作nat有关的链,必须显示的指明
-
如何设置链的默认策略,通过-P参数进行
iptables -P FORWARD ACCEPT
-
如何更新规则的跳转动作
- 先查看规则的序号 (如查看DOCKER-ISOLATION-STAGE-2链里的规则)
iptables -t filter --line-number -nL DOCKER-ISOLATION-STAGE-2
- 重新设置跳转动作
iptables -t filter -R DOCKER-ISOLATION-STAGE-2 1 -j DROP
-
如何删除某条规则
- 先查看规则的序号 (如查看DOCKER-ISOLATION-STAGE-2链里的规则)
iptables -t filter --line-number -nL DOCKER-ISOLATION-STAGE-2
- 删除规则
iptables -t filter -D DOCKER-ISOLATION-STAGE-2 1
九、问题排查思路
- 根据数据包走向图,进行排查,查询是哪里不通
- 使用tcpdump抓包分析
- ipv4是否开启
- iptables链是否正确