搭建前准备:
manager node: Centos 7
worker node: Centos 7
由于比较熟悉iptables,这里决定先将firewalld关闭,然后安装iptables来使用,分别在manager node 和worker node中运行以下命令
Systemctl stop firewalld
Systemctl disable firewalld
yum install iptables-services -y
systemctl enable iptables
同时还需要打开docker swarm 需要用到的端口,否则添加docker worker的时候可能会添加失败,如果不添加udp 4789 ,overlay 网络应该也是会有问题
vi /etc/sysconfig/iptables
添加以下的rule
-A INPUT -p tcp -m state --state NEW -m tcp --dport 2377 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 2376 -j ACCEPT
-A INPUT -p udp -m state --state NEW -m udp --dport 4789 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 7946 -j ACCEPT
-A INPUT -p udp -m state --state NEW -m udp --dport 7946 -j ACCEPT
安装docker,可以参考以下链接中步骤进行(推荐手动安装)
https://www.runoob.com/docker/centos-docker-install.html
搭建docker swarm
1. 在manger node上运行
docker swarm init
2. 执行第一步后,会有相应的提示告诉你如何再添加worker node 和manager node 把添加worker node的命令复制后,
到worker node上执行。如果添加失败,请确保防火墙没有block 2367的流量。
3. 用docker node ls 查看当前所有的swarm 节点
4 . 使用docker service create 来创建对应一个service
docker service create --name nginx -p 80:80 --replicas 2 ningzaige2013/nginx:ds
这里就差不多了,其实这篇文章主要不是记录这个事情,而是我们在创建service后,访问我们的服务的时候,老是会遇到访问不了。这里基本上都是iptables的问题,这里我需要吐槽一下iptables,很容易出问题,导致我们的snat或者dnat出问题。同时,还要将docker0 和docker_gwbridge 调成混杂模式。有时候,我们发现从container访问外网的时候,访问不了,比如访问114.114.114.114,访问不了。这里需要怎么排查呢,首先docker swarm 中,container会有一个172.18.0.x的网卡,这个网卡是连接在docker_gwbridge这个网桥上,当访问外网的时候,流量会先打到docker_gwbridge,然后通过主机的内核协议栈进行转发,而访问不了的,基本上是因为iptables没有进行snat。当我们查看iptables -t nat 会发现有两条masq。按理说应该不会有问题呀,但是就是莫名其妙的没有进行snat,所以我们需要手动的加上snat规则。以下我将更改docker0和docker_gwbridge网卡的混杂模式和添加snat的命令写成一个service.这样我们就不需要每次重启都更改了。
#promisc --modify the docker0 and docker_gwbridge promisc
[Unit]
Description=customize service
After=network.target docker.service
[Service]
Type=simple
Restart=on-failure
ExecStartPre=/usr/bin/logger "promisc pre-start" -t promisc
ExecStart=/var/promisc/modifyDevPromisc.sh
ExecStartPost=/usr/bin/logger "promisc post-start" -t promisc
[Install]
WantedBy=multi-user.target
将以上的promisc.service 文件放在/usr/lib/systemd/system/目录下
#!/usr/bin/bash
/usr/sbin/ifconfig docker0 promisc
/usr/sbin/ifconfig docker_gwbridge promisc
/usr/sbin/iptables -t nat -A POSTROUTING -s 172.18.0.0/16 -j SNAT --to-source 192.168.3.43
将以上的modifyDevPromisc.sh 放到/var/promisc目录下。
然后systemctl enable promisc.service 来让其开机自启动。
同时,下载的nginx image,因为刚开始我测试的时候,是从其中一个nginx container去访问另一个nginx containier,每次发现都能ping通,但是却不能访问80端口,最后才发现nginx这个container,自己也是有iptables规则来过滤流量的。是不允许内部出去访问服务的。如果不想再搭建其他服务来测试,可以使用iptables -F 来清除所有的iptables规则,前提是进入 container的namespace( nsenter --net=/var/run/docker/netns/<container namespace id>)
如图所示,可以看到output 只允许state established 的流量出去,所以内部访问外部的80端口会被drop。