一、问题描述
某次OS升级重启后,发现docker redis实例无法启动,报错如下:
Error response from daemon: driver failed programming external connectivity on endpoint vpm.redis.2 (f4b70fef65000bcacb574ee59e65d9b7a25f2abfa5dec0be9b7421b6c4a985e0): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 6379 -j DNAT --to-destination 172.1.10.3:6379 ! -i docker0: iptables: No chain/target/match by that name.(exit status 1))
Error: failed to start containers: 00cb13547452
现场环境:BCLinux 8.2
二、处理过程
1)由上报错可知是iptables的问题,现场firewall已禁用;手动执行规则添加命令:
iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 6379 -j DNAT --to-destination 172.1.10.3:6379 ! -i docker0
报错同上:iptables: No chain/target/match by that name.
2)检查iptables的nat表,发现根本没有docker链
iptables -nL -t nat //输出如下Chain PREROUTING (policy ACCEPT)
target prot opt source destination Chain INPUT (policy ACCEPT)
target prot opt source destination Chain POSTROUTING (policy ACCEPT)
target prot opt source destination Chain OUTPUT (policy ACCEPT)
target prot opt source destination
3)我们需要手动添加DOCKER链到NAT表中:
iptables -t nat -N DOCKER //创建 iptables 中 nat 表中的 docker 链,执行此命令后,docker 链就会被创建#重新执行上述容器的docker链添加命令,实际容器启动时会自动添加
iptables -t nat -A PREROUTING -i eth0 -j DOCKER //将所有来自 docker0 虚拟网卡的数据包转发到 docker 链
iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 6379 -j DNAT --to-destination 172.1.10.3:6379 ! -i docker0 //在 docker 链中添加规则:将除docker0口的所有数据包转发到172.1.10.3地址的6379端口redis上
#验证
iptables -t nat -L DOCKER
4)再次重启redis容器,执行:docker start contained_id,报错:
Error response from daemon: driver failed programming external connectivity on endpoint vpm.redis.2 (38aa4d7de267a30e436881f97bc75d1e564649d5e942203297a2563): (iptables failed: iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.1.10.3 --dport 6379 -j ACCEPT: iptables: No chain/target/match by that name.(exit status 1))
Error: failed to start containers: 00cb13547452#同上,还需要在 filter表创建DOCKER链
iptables -t filte -N DOCKER#将发往而非来自docker0 接口的数据包发往redis,即允许来自 docker0 接口以外的 TCP 数据包访问 172.1.10.3 地址的 6379 端口,允许外部访问 Docker 容器中的 Redis 服务
iptables --wait -t filter -A DOCKER ! -i docker0 -o docker0 -p tcp -d 172.1.10.3 --dport 6379 -j ACCEPT
5)再次重启redis容器,正常
iptables -t nat -L //输出如下
Chain PREROUTING (policy ACCEPT)
target prot opt source destination Chain INPUT (policy ACCEPT)
target prot opt source destination Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE tcp -- 172.17.0.3 172.1.10.3 tcp dpt:redisChain OUTPUT (policy ACCEPT)
target prot opt source destination Chain DOCKER (0 references)
target prot opt source destination
DNAT tcp -- anywhere anywhere tcp dpt:redis to:172.1.10.1:6379
DNAT tcp -- anywhere anywhere tcp dpt:redis to:172.1.10.3:6379