我有一个docker容器,我无法从容器内运行DNS查找,虽然它从docker主机工作正常。
构buildDocker主机的configurationpipe理代码已知可以在市场上的标准RHEL 7映像上运行,因此这个问题被称为SOE RHEL 7映像中的内容。
RHEL 7.2 / Docker版本1.12.6,版本88a4867 / 1.12.6。 容器是RHEL 7.3。 SELinux处于启用/允许模式。 Docker主机是Amazon EC2实例。
一些configuration:
# /etc/sysconfig/docker OPTIONS='--dns=10.0.0.10 --dns=10.0.0.11 --dns-search=example.com' DOCKER_CERT_PATH=/etc/docker ADD_REGISTRY='--add-registry registry.example.com' no_proxy=169.254.169.254,localhost,127.0.0.1,registory.example.com http_proxy=http://proxy.example.com:8080 https_proxy=http://proxy.example.com:8080 ftp_proxy=http://proxy.example.com:8080
容器和主机中的Resolverconfiguration是一样的:
# /etc/resolv.conf search example.com nameserver 10.0.0.10 nameserver 10.0.0.11
如果我用--debug重新启动journalctl -u docker.service守护进程,我在journalctl -u docker.service看到以下journalctl -u docker.service :
Aug 08 11:44:23 myhost.example.com dockerd-current[17341]: time="2017-08-08T11:44:23.430769581+10:00" level=debug msg="Name To resolve: http://proxy.example.com." Aug 08 11:44:23 myhost.example.com dockerd-current[17341]: time="2017-08-08T11:44:23.431488213+10:00" level=debug msg="Query http://proxy.example.com.[1] from 172.18.0.6:38189, forwarding to udp:10.162.182.101" Aug 08 11:44:27 myhost.example.com dockerd-current[17341]: time="2017-08-08T11:44:27.431772666+10:00" level=debug msg="Read from DNS server failed, read udp 172.18.0.6:38189->10.162.182.101:53: i/o timeout"
继续进一步的观察,如果我指定一个IP地址,而不是代理的DNS名称,我可以得到一些networking工作。 虽然这真的只是避免使用DNS的一种方式,而不是一个真正的解决办法。
事实上,( 更新#3 )事实certificate,我可以完全避免这个问题完全通过configurationDNS使用TCP而不是UDP,即
# head -1 /etc/sysconfig/docker OPTIONS="--dns=10.0.0.10 --dns=10.0.0.11 --dns-search=example.com --dns-opt=use-vc"
(添加一行use-vc告诉parsing器使用TCP而不是UDP。)
我确实在iptables中logging了一些可疑的规则,但事实certificate这是正常的:
# iptables -n -L DOCKER-ISOLATION -v --line-numbers Chain DOCKER-ISOLATION (1 references) num pkts bytes target prot opt in out source destination 1 0 0 DROP all -- br-1d6a05c10468 docker0 0.0.0.0/0 0.0.0.0/0 2 0 0 DROP all -- docker0 br-1d6a05c10468 0.0.0.0/0 0.0.0.0/0 3 34903 11M RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
删除了这两个DROP规则后,我继续看到这个问题。
完整的iptables:
# iptables -nL -v Chain INPUT (policy ACCEPT 2518 packets, 1158K bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 0 packets, 0 bytes) pkts bytes target prot opt in out source destination 23348 9674K DOCKER-ISOLATION all -- * * 0.0.0.0/0 0.0.0.0/0 0 0 DOCKER all -- * docker0 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- * docker0 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 0 0 ACCEPT all -- docker0 !docker0 0.0.0.0/0 0.0.0.0/0 0 0 ACCEPT all -- docker0 docker0 0.0.0.0/0 0.0.0.0/0 23244 9667K DOCKER all -- * br-1d6a05c10468 0.0.0.0/0 0.0.0.0/0 23232 9667K ACCEPT all -- * br-1d6a05c10468 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED 104 6230 ACCEPT all -- br-1d6a05c10468 !br-1d6a05c10468 0.0.0.0/0 0.0.0.0/0 12 700 ACCEPT all -- br-1d6a05c10468 br-1d6a05c10468 0.0.0.0/0 0.0.0.0/0 Chain OUTPUT (policy ACCEPT 2531 packets, 414K bytes) pkts bytes target prot opt in out source destination Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 ACCEPT tcp -- !br-1d6a05c10468 br-1d6a05c10468 0.0.0.0/0 172.18.0.2 tcp dpt:443 0 0 ACCEPT tcp -- !br-1d6a05c10468 br-1d6a05c10468 0.0.0.0/0 172.18.0.2 tcp dpt:80 0 0 ACCEPT tcp -- !br-1d6a05c10468 br-1d6a05c10468 0.0.0.0/0 172.18.0.3 tcp dpt:389 Chain DOCKER-ISOLATION (1 references) pkts bytes target prot opt in out source destination 0 0 DROP all -- br-1d6a05c10468 docker0 0.0.0.0/0 0.0.0.0/0 0 0 DROP all -- docker0 br-1d6a05c10468 0.0.0.0/0 0.0.0.0/0 23348 9674K RETURN all -- * * 0.0.0.0/0 0.0.0.0/0
网桥configuration
# ip addr show docker0 4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN link/ether 02:42:a8:73:db:bb brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 scope global docker0 valid_lft forever preferred_lft forever # ip addr show br-1d6a05c10468 3: br-1d6a05c10468: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:d5:b6:2d:f5 brd ff:ff:ff:ff:ff:ff inet 172.18.0.1/16 scope global br-1d6a05c10468 valid_lft forever preferred_lft forever
和
# docker network inspect bridge [ { "Name": "bridge", "Id": "e159ddd37386cac91e0d011ade99a51f9fe887b8d32d212884beace67483af44", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" } ] }, "Internal": false, "Containers": {}, "Options": { "com.docker.network.bridge.default_bridge": "true", "com.docker.network.bridge.enable_icc": "true", "com.docker.network.bridge.enable_ip_masquerade": "true", "com.docker.network.bridge.host_binding_ipv4": "0.0.0.0", "com.docker.network.bridge.name": "docker0", "com.docker.network.driver.mtu": "1500" }, "Labels": {} } ]
在日志中:
Aug 04 17:33:32 myhost.example.com systemd[1]: Starting Docker Application Container Engine... Aug 04 17:33:33 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:33.056770003+10:00" level=info msg="libcontainerd: new containerd process, pid: 2140" Aug 04 17:33:34 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:34.740346421+10:00" level=info msg="Graph migration to content-addressability took 0.00 seconds" Aug 04 17:33:34 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:34.741164354+10:00" level=info msg="Loading containers: start." Aug 04 17:33:34 myhost.example.com dockerd-current[2131]: .........................time="2017-08-04T17:33:34.903371015+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:35 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:35.325581993+10:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0.0/16. Daemon option --bip can be used to set a preferred IP address" Aug 04 17:33:36 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:36+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:37 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:37+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:37 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:37+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:38 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:38+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:39 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:39+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:40 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:40+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:40 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:40+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:42 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:42+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:42 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:42+10:00" level=info msg="Firewalld running: true" Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.541905145+10:00" level=info msg="Loading containers: done." Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.541975618+10:00" level=info msg="Daemon has completed initialization" Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.541998095+10:00" level=info msg="Docker daemon" commit="88a4867/1.12.6" graphdriver=devicemapper version=1.12.6 Aug 04 17:33:43 myhost.example.com dockerd-current[2131]: time="2017-08-04T17:33:43.548508756+10:00" level=info msg="API listen on /var/run/docker.sock" Aug 04 17:33:43 myhost.example.com systemd[1]: Started Docker Application Container Engine.
从容器中,我可以ping默认网关,但所有名称parsing失败。
我注意到日志中有一个奇怪的东西( 更新#2我现在知道这是一个红鲱鱼 – 见下面的讨论):
# journalctl -u docker.service |grep insmod > /tmp/log # \n's replaced below Jul 26 23:59:02 myhost.example.com dockerd-current[3185]: time="2017-07-26T23:59:02.056295890+10:00" level=warning msg="Running modprobe bridge br_netfilter failed with message: insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/bridge/bridge.ko sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-arptables: No such file or directory sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-ip6tables: No such file or directory modprobe: ERROR: Error running install command for bridge modprobe: ERROR: could not insert 'bridge': Unknown error 253 insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/llc/llc.ko insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/802/stp.ko install /sbin/modprobe --ignore-install bridge && /sbin/sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0 insmod /lib/modules/3.10.0-514.26.2.el7.x86_64/kernel/net/bridge/br_netfilter.ko , error: exit status 1"
更新#1 :这是来自:
# tail -2 /etc/modprobe.d/dist.conf # Disable netfilter on bridges when the bridge module is loaded install bridge /sbin/modprobe --ignore-install bridge && /sbin/sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0
也:
# cat /proc/sys/net/bridge/bridge-nf-call-{arp,ip,ip6}tables 1 1 1
但是,即使我这样做:
# for i in /proc/sys/net/bridge/bridge-nf-call-{arp,ip,ip6}tables ; do echo 0 > $i ; done
仍然没有运气。
我花了一整天的时间,现在把头发拉出来。 任何想法,我还可以尝试什么,或者什么问题可能会非常感激。
更新#4
我使用Netcat进行了一些实验,并且certificate了从任何容器 – >主机发送的所有UDP数据包都不会被转发。 我尝试使用几个端口,包括53,2115和50000.然而,TCP数据包很好。 如果我使用iptables -F刷新iptables规则,这仍然是正确的。
而且,我可以将UDP数据包从一个容器发送到另一个容器 – 只有来自容器 – >主机的UDPstream量不会被转发。
设置testing:
在具有IP 10.1.1.10的主机上:
# nc -u -l 50000
在容器上:
# echo "foo" | nc -w1 -u 10.1.1.10 50000
在TCP转储捕获期间,我看到:
17:20:36.761214 IP (tos 0x0, ttl 64, id 48146, offset 0, flags [DF], proto UDP (17), length 32) 172.17.0.2.41727 > 10.1.1.10.50000: [bad udp cksum 0x2afa -> 0x992f!] UDP, length 4 0x0000: 4500 0020 bc12 4000 4011 53de ac11 0002 E.....@[email protected]..... 0x0010: 0aa5 7424 a2ff c350 000c 2afa 666f 6f0a ..t$...P..*.foo. 0x0020: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 17:20:36.761214 IP (tos 0x0, ttl 64, id 48146, offset 0, flags [DF], proto UDP (17), length 32) 172.17.0.2.41727 > 10.1.1.10.50000: [bad udp cksum 0x2afa -> 0x992f!] UDP, length 4 0x0000: 4500 0020 bc12 4000 4011 53de ac11 0002 E.....@[email protected]..... 0x0010: 0aa5 7424 a2ff c350 000c 2afa 666f 6f0a ..t$...P..*.foo. 0x0020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
我试图通过这个修复不好的UDP校验和。
但是我注意到,即使在成功传输UDP数据包(主机 – >主机)和容器 – >容器期间,也可以看到错误的UDP校验和。
总之,我现在知道:
路由很好
iptables被刷新
SELinux是宽容的
所有的TCP都在各个方面工作
所有来自容器 – >容器的UDP都没问题
从主机 – >主机的所有UDP都很好
从主机 – >容器的所有UDP都很好
但是没有来自容器 – >主机的UDP数据包被转发
看来你有一个modprobe install指令,不能工作。 可能是由于对RHEL 7.2的不完整更新或一些手动修复造成的。
尝试使用grep -r bridge /etc/modprobe.d /lib/modprobe.d作为初学者,或者在/etc/modprobe.d或/lib/modprobe.d挖掘,并尝试find它在哪里定义调用的install规则sysctl -q -w net.bridge.bridge-nf-call-arptables=0 net.bridge.bridge-nf-call-iptables=0 net.bridge.bridge-nf-call-ip6tables=0
这个sysctl显然是错误的地方。 它是多余的,或者应该出现在br_netfilter之后,而不是之前。 为什么? 最近, /proc/sys/net/bridge处理已经从bridge模块移动到br_netfilter模块。 这发生在某些版本的kernel*.rpm ,而modprobe.d目录的内容与其他单独的包一起分发。 我已经在我的RHEL 7.2上进行了validation:
# modprobe bridge # sysctl -q -w net.bridge.bridge-nf-call-iptables=0 sysctl: cannot stat /proc/sys/net/bridge/bridge-nf-call-iptables: No such file or directory # modprobe br_netfilter # sysctl -q -w net.bridge.bridge-nf-call-iptables=0 # ok now
我在我的香草RHEL 7.1上看不到这些“破碎”的规则,它们的起源对我来说是神秘的 。 我试过了:
# modprobe -n -vvv bridge modprobe: INFO: custom logging function 0x40a130 registered insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/llc/llc.ko insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/802/stp.ko insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/bridge/bridge.ko modprobe: INFO: context 0xf1c270 released # echo "install bridge echo example_of_a_modprobe_rule" > /etc/modprobe.d/zzz5.conf # modprobe -n -vvv bridge modprobe: INFO: custom logging function 0x40a130 registered insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/llc/llc.ko insmod /lib/modules/3.10.0-229.11.1.el7.x86_64/kernel/net/802/stp.ko install echo example_of_a_modprobe_rule modprobe: INFO: context 0xeaa270 released # rm /etc/modprobe.d/zzz5.conf
更新:看起来像xenserver使用类似的modprobe破解 。 无论你是否真正运行xenserver,全局改变每个人的内核模块行为都是一个令人讨厌的bug。 这个bug已经对我们发起了攻击。
更新2:现在,你已经发现/etc/modprobe.d/dist.conf导致这个问题,而不是docker。 无论你是否有docker, modprobe bridge将始终返回1,并打印错误。 通常,dist.conf是RHEL6上module-init-tools软件包的一部分。 这个文件不应该在RHEL7上使用。 它不在我的任何RHEL7系统上,它们运行得很好。 在RHEL7中,软件包是kmod ,不包含dist.conf。 我会:
rpm -qf /etc/modprobe.d/dist.conf # what package owns this file?
如果dist.conf不属于软件包,请将其备份并删除任何不会给您带来明显好处的行(甚至可能完全删除文件)。
如果dist.conf被包所有,请考虑删除/更新该包,因为在RHEL 7.2兼容性方面,它明显变成了bug。
我想到了。
我们有一个在我不知道的SOE中运行的趋势科技(防病毒)代理。
解决这个问题非常简单:
# systemctl stop ds_agent.service # pkill ds_agent
不完全确定在这一点上,为什么它阻止来自容器的UDP或如何阻止它。