跳转至

Datapath

对需要生效的规则分为三类:所有节点,相对于 EgressGatewayPolicy 的「网关节点」和「非网关节点」。只有当业务 Pod 调度到的「非网关节点」,该节点上的规则才会生效。

所有节点

  1. 各节点之间,隧道打通规则;
    # 本地隧道网卡信息
    LOCAL_TUNNEL_IPV4="20.0.0.80/24"
    
    LOCAL_TUNNEL_IPV6="fccc::80/64"
    
    TUNNEL_NAME="egress-vxlan"
    
    VXLAN_ID="20"
    
    LOCAL_DEV="eth1"
    
    LOCA_PHY_IP="172.16.1.11"
    
    DEST_UDP_PORT="8789"
    
    LOCAL_TUNNEL_MAC="00:11:00:00:00:80"
    
    
    # 创建隧道网卡
    ip l d $TUNNEL_NAME &>/dev/null
    
    ip link add $TUNNEL_NAME type vxlan id $VXLAN_ID local $LOCA_PHY_IP dstport $DEST_UDP_PORT dev $LOCAL_DEV nolearning
    
    ip -6 a add $LOCAL_TUNNEL_IPV6 dev $TUNNEL_NAME
    
    ip -4 a add $LOCAL_TUNNEL_IPV4 dev $TUNNEL_NAME
    
    ip l set $TUNNEL_NAME address $LOCAL_TUNNEL_MAC
    
    ip link set $TUNNEL_NAME up
    
    
    # 对端隧道信息
    REMOTE1_TUNNEL_MAC="00:11:00:00:00:85"
    
    REMOTE1_TUNNEL_IPV4="20.0.0.85"
    
    REMOTE1_TUNNEL_IPV6="fccc::85"
    
    REMOTE1_PHY_IP="172.16.2.21"
    
    
    # 添加对端隧道转发信息
    bridge fdb append to $REMOTE1_TUNNEL_MAC dst $REMOTE1_PHY_IP dev $TUNNEL_NAME
    
    ip -4 n add  $REMOTE1_TUNNEL_IPV4  lladdr  $REMOTE1_TUNNEL_MAC  dev $TUNNEL_NAME
    
    ip -6 n add  $REMOTE1_TUNNEL_IPV6  lladdr  $REMOTE1_TUNNEL_MAC  dev $TUNNEL_NAME
    
    # 添加策略路由信息
    ip rule add fwmark $NODE_MARK table $TABLE_NUM
    
    ip route add default via $REMOTE1_TUNNEL_IPV4 dev $TUNNEL_NAME onlink table $TABLE_NUM
    
    ip -6 rule add fwmark $NODE_MARK table $TABLE_NUM
    
    ip -6 route add default via $REMOTE1_TUNNEL_IPV6 dev $TUNNEL_NAME onlink table $TABLE_NUM
    
  2. 在节点第一次变成网关节点时更新,或者节点 join 时,将 policy 命中的流量,重新打标签。其他情况不更新。
iptables -t mangle -N EGRESSGATEWAY-RESET-MARK
iptables -t mangle -I FORWARD 1  -j EGRESSGATEWAY-RESET-MARK -m comment --comment "egress gateway: mark egress packet"

iptables -t mangle -A EGRESSGATEWAY-RESET-MARK \
    -m mark --mark $NODE_MARK/0x26000000 \
    -j MARK --set-mark 0x12000000 \
    -m comment --comment "egress gateway: change mark"
  1. 保持 policy 命中流量的标签。直接创建一次,不需要更新;
iptables -t filter -I FORWARD 1 -m mark --mark 0x12000000 -j ACCEPT -m comment --comment "egress gateway: keep mark"

iptables -t filter -I OUTPUT 1 -m mark --mark 0x12000000 -j ACCEPT -m comment --comment "egress gateway: keep mark"

iptables -t mangle -I POSTROUTING 1 -m mark --mark 0x12000000 -j ACCEPT -m comment --comment "egress gateway: keep mark"
  1. 聚合 policy 命中流量打标签的链。直接创建一次,不需要更新;
iptables -t mangle -N EGRESSGATEWAY-MARK-REQUEST

iptables -t mangle -I PREROUTING 1 -j EGRESSGATEWAY-MARK-REQUEST -m comment --comment "egress gateway: mark egress packet"
  1. 聚合不需要做 SNAT 规则的链。直接创建一次,不需要更新;
iptables -t nat -N EGRESSGATEWAY-NO-SNAT

iptables -t nat -I POSTROUTING 1  -j EGRESSGATEWAY-NO-SNAT -m comment --comment "egress gateway: no snat"

iptables -t nat -A EGRESSGATEWAY-NO-SNAT -m mark --mark 0x12000000 -j ACCEPT -m comment --comment "egress gateway: no snat"
  1. 聚合需要做 SNAT 规则的链。直接创建一次,不需要更新。
iptables -t nat -N EGRESSGATEWAY-SNAT-EIP

# 需要在不需要 SNAT 的规则后面插入,才能保证该链在最前面
iptables -t nat -I POSTROUTING 1  -j EGRESSGATEWAY-SNAT-EIP -m comment --comment "egress gateway: snat EIP"
  1. egress-ingore-cidr 当 EgressGatewayPolicy 的 destSubnet 字段为空时,数据面将会自动匹配 EgressClusterStatus CR 中的 CIDR 之外的流量,并将其转发到 Egress 网关。
IPSET_RULE_DEST_NAME=egress-ingore-cidr

ipset x $IPSET_RULE_DEST_NAME

ipset create $IPSET_RULE_DEST_NAME hash:net

ipset add $IPSET_RULE_DEST_NAME 10.6.105.150/32

相对于 EIP 的非 Egress Gateway 节点

  1. policy 命中的源 IP、目的 IP 的 ipset;
IPSET_RULE_DEST_NAME=egress-dest-uuid

ipset x $IPSET_RULE_DEST_NAME

ipset create $IPSET_RULE_DEST_NAME hash:net

ipset add $IPSET_RULE_DEST_NAME 10.6.105.150/32


IPSET_RULE_SRC_NAME=egress-src-uuid

ipset x $IPSET_RULE_SRC_NAME

ipset create $IPSET_RULE_SRC_NAME hash:net

ipset add $IPSET_RULE_SRC_NAME 172.29.234.173/32
  1. policy 命中的流量打标签,保证能从隧道走。其中 NODE_MARK 的值根据 policy 对应的 EIP 所在节点决定。
iptables -A EGRESSGATEWAY-MARK-REQUEST -t mangle -m conntrack --ctdir ORIGINAL \
-m set --match-set $IPSET_RULE_DEST_NAME dst  \
-m set --match-set $IPSET_RULE_SRC_NAME src  \
-j MARK --set-mark $NODE_MARK -m comment --comment "rule uuid: mark request packet"
  1. 策略路由规则
ip rule add fwmark $NODE_MARK table $TABLE_NUM
  1. 适配 Weave 避免做 SNAT 成 Egress 隧道的 IP。做成开关
iptables -t nat -A EGRESSGATEWAY-NO-SNAT \
-m set --match-set $IPSET_RULE_DEST_NAME dst  \
-m set --match-set $IPSET_RULE_SRC_NAME src  \
-j ACCEPT -m comment --comment "egress gateway: weave does not do SNAT"

相对于 EIP 的 Egress Gateway 节点

  1. policy 命中的源 IP、目的 IP 的 ipset;
IPSET_RULE_DEST_NAME=egress-dest-uuid

ipset x $IPSET_RULE_DEST_NAME

ipset create $IPSET_RULE_DEST_NAME hash:net

ipset add $IPSET_RULE_DEST_NAME 10.6.105.150/32


IPSET_RULE_SRC_NAME=egress-src-uuid

ipset x $IPSET_RULE_SRC_NAME

ipset create $IPSET_RULE_SRC_NAME hash:net

ipset add $IPSET_RULE_SRC_NAME 172.29.234.173/32
  1. policy 命中的流量。出网关时做 SNAT。实时更新。
iptables -t nat -A EGRESSGATEWAY-SNAT-EIP \
    -m set --match-set $IPSET_RULE_SRC_NAME src \
    -m set --match-set $IPSET_RULE_DST_NAME dst \
    -j SNAT --to-source $EIP

其他

  1. NODE_MARK:每个节点对应一个全局唯一的标签。标签由前缀 + 唯一标识符生成。标签格式如下 NODE_MARK = 0x26 + value + 0000value 为 16 位,支持的节点总数为 2^16

  2. TABLE_NUM:

    • 由于每个主机只能有 [0, 255] 张路由表(其中 0、253、254、255 已被系统使用),超出表的张数时,会导致节点路由没法计算,从而节点失联。而且表名与表的 ID 匹配,如果没有匹配,则内核会随机分配。所以为了保险起见,控制表的的张数(n 表示,默认值为 100)也就是网关节点的上限,可以通过变量设置。
    • TABLE_NUM 算法:用户可以设置一个起始值(s 表示,默认值为 3000),则表名的范围为 [s, (s+n)],用户需要保证 [s, (s+n)] 的表名没有被占用。随机从 [s, (s+n)] 取一个起始值,依次增加,环形取值,直到获得一个本节点未使用的表名,未找到则报错。