疑问:现有两个svc分别是svcA和svcB,分别对应一个实例pod,分别是podA和podB,现在podA中访问svcB,podA发出的包的src_ip是podA_ip,dst_ip是svcB_ip,按道理来说podB收到的包的src_ip应该是cni0的ip(抓包看到确实是)
k8s会在两个地方设置mark标记,这两个地方设置的标记在包最后离开主机时会进行一次SNAT把源ip换成节点上的cni0的ip(对应KUBE-POSTROUTING CHAIN中唯一的一条规则
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE)
###1.每个svc对应的KUBE-SERVICES CHAN中:如果源地址不是整个pod的网段(包括cni0)就打标记,对应的场景是集群外部client以NodePort的形式访问节点A以访问svc时,节点A上可能并没有目标svc的pod,包从节点A路由到目标pod所在节点时需要做SNAT
###把源ip NAT成cni0的ip,可以防止pod收到包时认为自己是直接访问client,从而tcp握手失败
-A KUBE-SERVICES ! -s 10.244.0.0/16 -d 10.111.118.122/32 -p tcp -m comment --comment "app/sample-metrics-app:web cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
-A KUBE-SERVICES -d 10.111.118.122/32 -p tcp -m comment --comment "app/sample-metrics-app:web cluster IP" -m tcp --dport 80 -j KUBE-SVC-ZUAJYEXOSE7G7O7F
###2.每个pod对应的KUBE-SEP CHAN中:如果源地址是pod自己的ip就打标记,防止:pod访问自己的svc,经过DNAT后srcip和dstip都是pod ip,pod会觉得是自己访问自己,从而tcp握手失败
-A KUBE-SEP-IG6GZJQ244FAYVBS -s 10.244.0.186/32 -m comment --comment "kube-system/kube-dns:dns" -j KUBE-MARK-MASQ
-A KUBE-SEP-IG6GZJQ244FAYVBS -p udp -m comment --comment "kube-system/kube-dns:dns" -m udp -j DNAT --to-destination 10.244.0.186:53
上述疑问,上面的两种情况都无法解释
在nat:POSTROUTING,还会再对一些匹配的包做MASQ,如下
-A POSTROUTING -m comment --comment "kubernetes postrouting rules" -j KUBE-POSTROUTING
-A POSTROUTING -s 10.244.0.0/16 -d 10.244.0.0/16 -j RETURN ### 这里为什么要return?
-A POSTROUTING -s 10.244.0.0/16 ! -d 224.0.0.0/4 -j MASQUERADE
-A POSTROUTING ! -s 10.244.0.0/16 -d 10.244.1.0/24 -j RETURN
-A POSTROUTING ! -s 10.244.0.0/16 -d 10.244.0.0/16 -j MASQUERADE
-A KUBE-POSTROUTING -m comment --comment "kubernetes service traffic requiring SNAT" -m mark --mark 0x4000/0x4000 -j MASQUERADE
pod中访问svc时已经在PREROTING做了DNAT了,所以包在POSTROUTING时,src_ip是podA_ip,dst_ip是podB_ip,这个时候就被RETURN了,最终岂不还是没做SNAT???