1. Calico natOutgoing

POD 访问 Kubernetes 集群之外的节点时,为了报文能够返回通常需要在宿主机上进行 SNAT (MASQUERADE),以 Calico 为例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
Chain POSTROUTING (policy ACCEPT)
target              prot opt source               destination         
cali-POSTROUTING    all  --  0.0.0.0/0            0.0.0.0/0            /* cali:O3lYWMrLQYEMJtB5 */
KUBE-POSTROUTING    all  --  0.0.0.0/0            0.0.0.0/0            /* kubernetes postrouting rules */
MASQUERADE          all  --  40.40.40.0/24        0.0.0.0/0 

Chain cali-POSTROUTING (1 references)
target               prot opt source               destination         
cali-fip-snat        all  --  0.0.0.0/0            0.0.0.0/0            /* cali:Z-c7XtVd2Bq7s_hA */
cali-nat-outgoing    all  --  0.0.0.0/0            0.0.0.0/0            /* cali:nYKhEzDlr11Jccal */
MASQUERADE           all  --  0.0.0.0/0            0.0.0.0/0            /* cali:e9dnSgSVNmIcpVhP */ ADDRTYPE match src-type !LOCAL limit-out ADDRTYPE match src-type LOCAL

Chain cali-nat-outgoing (1 references)
target            prot opt source               destination         
MASQUERADE        all  --  0.0.0.0/0            0.0.0.0/0            /* cali:flqWnvo8yq4ULQLa */ match-set cali40masq-ipam-pools src ! match-set cali40all-ipam-pools dst

关于 iptable 的 addrtype 模块,该模块按照特定规则匹配报文的源地址和目的地址。其中,–limit-iface-out 和 –limit-iface-in 参数将检查设备网卡进行限制。

cali-POSTROUTING 链的 MASQUERADE 规则包含 ADDRTYPE 条件:

  • ADDRTYPE match src-type LOCAL:LOCAL 表示主机上分配的任何 IP 地址,包括 127.0.0.1 和 其他 IP,规则含义是源地址是本地 IP
  • ADDRTYPE match src-type !LOCAL limit-out: limit-out 限制了 LOCAL 表示的 IP 内容,此时的 LOCAL 只包括 Package 发出设备上的 IP,即 src-type !LOCAL limit-out 的含义是源地址 IP 是除 Package 发出设备以外的本地 IP ,

综上 cali-POSTROUTING 进行 MASQUERADE 的条件是:src 是本地地址,并且 src 地址 ip 不能是 out-interface 的 ip。

cali-nat-outgoing 中限制了对所有 dst 不是 PodIP 的报文进行 MASQUERADE。

calico 支持在 IPPool 中配置 Outgoing 流量是否进行 NAT:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
apiVersion: crd.projectcalico.org/v1
kind: IPPool
metadata:
  name: default-ipv4-ippool
spec:
  blockSize: 26
  cidr: 10.233.64.0/18
  ipipMode: Never
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: CrossSubnet

关闭 natOutgoing 参数后,会发现在 Pod 中无法访问外网的网络。

附:iptables addrtype 模块

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
iptables -m addrtype --help

Address type match options:
 [!] --src-type type[,...]      Match source address type
 [!] --dst-type type[,...]      Match destination address type
     --limit-iface-in           Match only on the packet's incoming device
     --limit-iface-out          Match only on the packet's outgoing device

Valid types:           
                                UNSPEC
                                UNICAST
                                LOCAL
                                BROADCAST
                                ANYCAST
                                MULTICAST
                                BLACKHOLE
                                UNREACHABLE
                                PROHIBIT
                                THROW
                                NAT
                                XRESOLVE

参考

Configure outgoing NAT