Environment
Os: centos7.1
Kubelet: 1.6.7
Docker: 17.06-ce
Calico: 2.3
K8s Cluster: master, node-1, node-2
Problem
現有 service A, 爲了能使外部訪問,故將 service type 設爲NodePort
。端口爲 31246。
A 所對應的 pod 運行在 node-1 上。
經過測試發現,外部訪問 master:31246
和 node-2:31246
時均出現失敗,只有通過 node-1:31246
纔可正常訪問。
Reason
爲了安全起見, docker 在 1.13 版本之後,將系統iptables 中 FORWARD 鏈的默認策略設置爲 DROP,併爲連接到 docker0 網橋的容器添加了放行規則。這裏引用 moby issue#14041 中的描述:
When docker starts, it enables
net.ipv4.ip_forward
without changing the iptables FORWARD chain default policy to DROP. This means that another machine on the same network as the docker host can add a route to their routing table, and directly address any containers running on that docker host.For example, if the docker0 subnet is
172.17.0.0/16
(the default subnet), and the docker host’s IP address is192.168.0.10
, from another host on the network run:
$ ip route add 172.17.0.0/16 via 192.168.0.10 $ nmap 172.17.0.0/16
The above will scan for containers running on the host, and report IP addresses & running services found.
To fix this, docker needs to set the FORWARD policy to DROP when it enables the
net.ipv4.ip_forward
sysctl parameter.
kubernetes 使用的 cni 插件會因此受影響(cni並不會在 FORWARD 鏈中生成相應規則),由此導致除 pod 所在 host 以外節點無法轉發報文而訪問失敗。
Solution
如果對安全要求較低,可將 FORWARD 鏈的默認規則設爲 ACCEPT
iptables -P FORWARD ACCEPT
其它方法可參考: