跳转至

VPC Egress Gateway

VPC Egress Gateway 用于控制 VPC(包括默认 VPC)内 Pod 访问外部网络,并具有以下特点:

  • 通过 ECMP 实现 Active-Active 高可用,可实现吞吐量横向扩展
  • 通过 BFD 实现 <1s 的快速故障切换
  • 支持 IPv6 及双栈
  • 可通过 Namespace 选择器和 Pod 选择器实现细粒度路由控制
  • 可通过 Node 选择器,实现 Egress Gateway 灵活调度

同时 VPC Egress Gateway 具有如下限制:

  • 使用 macvlan 实现底层网络打通,需要底层网络支持 Underlay
  • Gateway 多实例模式下需要占用多个 Egress IP
  • 目前只支持 SNAT,不支持 EIP 和 DNAT

使用要求

VPC Egress Gateway 与 VPC NAT Gateway 相同,都需要先在集群中 部署 Multus-CNI

使用 VPC Egress Gateway 无需配置任何 ConfigMap。

使用方法

创建 NetworkAttachmentDefinition

VPC Egress Gateway 使用多网卡来同时接入 VPC 及外部网络,因此需要先创建 NetworkAttachmentDefinition 用于连接外部网络。使用 macvlan 插件并由 Kube-OVN 提供 IPAM 的示例如下:

apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: eth1
  namespace: default
spec:
  config: '{
      "cniVersion": "0.3.0",
      "type": "macvlan",
      "master": "eth1",
      "mode": "bridge",
      "ipam": {
        "type": "kube-ovn",
        "server_socket": "/run/openvswitch/kube-ovn-daemon.sock",
        "provider": "eth1.default"
      }
    }'
---
apiVersion: kubeovn.io/v1
kind: Subnet
metadata:
  name: macvlan1
spec:
  protocol: IPv4
  provider: eth1.default
  cidrBlock: 172.17.0.0/16
  gateway: 172.17.0.1
  excludeIps:
    - 172.17.0.0..172.17.0.10

您可使用任意 CNI 插件创建 NetworkAttachmentDefinition 使 VPC Egress Gateway 接入相应的网络中。

关于多网卡的具体使用方法,请参考 多网卡管理

创建 VPC Egress Gateway

创建 VPC Egress Gateway 资源,示例如下:

apiVersion: kubeovn.io/v1
kind: VpcEgressGateway
metadata:
  name: gateway1
  namespace: default
spec:
  vpc: ovn-cluster
  replicas: 1
  externalSubnet: macvlan1
  policies:
    - snat: true
      subnets:
        - ovn-default

上述资源会在 default 命名空间下为 VPC ovn-cluster 创建一个名为 gateway1 的单副本 VPC Egress Gateway,ovn-clusterovn-default 子网(10.16.0.0/16)下的所有 Pod 将通过 macvlan1 子网以 SNAT 的方式访问外部网络。

创建完成后,查看 VPC Egress Gateway:

$ kubectl get veg gateway1
NAME       VPC           REPLICAS   BFD ENABLED   EXTERNAL SUBNET   PHASE       READY   AGE
gateway1   ovn-cluster   1          false         macvlan1          Completed   true    13s

查看更多信息:

kubectl get veg gateway1 -o wide
NAME       VPC           REPLICAS   BFD ENABLED   EXTERNAL SUBNET   PHASE       READY   INTERNAL IPS     EXTERNAL IPS      WORKING NODES         AGE
gateway1   ovn-cluster   1          false         macvlan1          Completed   true    ["10.16.0.12"]   ["172.17.0.11"]   ["kube-ovn-worker"]   82s

查看工作负载:

$ kubectl get deployment -l ovn.kubernetes.io/vpc-egress-gateway=gateway1
NAME       READY   UP-TO-DATE   AVAILABLE   AGE
gateway1   1/1     1            1           4m40s

$ kubectl get pod -l ovn.kubernetes.io/vpc-egress-gateway=gateway1 -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP           NODE              NOMINATED NODE   READINESS GATES
gateway1-b9f8b4448-76lhm   1/1     Running   0          4m48s   10.16.0.12   kube-ovn-worker   <none>           <none>

查看 Pod 中的 IP、路由及 iptables 规则:

$ kubectl exec gateway1-b9f8b4448-76lhm -c gateway -- ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: net1@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 62:d8:71:90:7b:86 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.11/16 brd 172.17.255.255 scope global net1
       valid_lft forever preferred_lft forever
    inet6 fe80::60d8:71ff:fe90:7b86/64 scope link
       valid_lft forever preferred_lft forever
17: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default
    link/ether 36:7c:6b:c7:82:6b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.16.0.12/16 brd 10.16.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::347c:6bff:fec7:826b/64 scope link
       valid_lft forever preferred_lft forever

$ kubectl exec gateway1-b9f8b4448-76lhm -c gateway -- ip route show
default via 172.17.0.1 dev net1
10.16.0.0/16 dev eth0 proto kernel scope link src 10.16.0.12
172.17.0.0/16 dev net1 proto kernel scope link src 172.17.0.11

$ kubectl exec gateway1-b9f8b4448-76lhm -c gateway -- iptables -t nat -S
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-A POSTROUTING -s 10.16.0.0/16 -j MASQUERADE --random-fully

在 Gateway Pod 中抓包验证网络流量:

$ kubectl exec -ti gateway1-b9f8b4448-76lhm -c gateway -- bash
nobody@gateway1-b9f8b4448-76lhm:/kube-ovn$ tcpdump -i any -nnve icmp and host 172.17.0.1
tcpdump: data link type LINUX_SLL2
tcpdump: listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
06:50:58.936528 eth0  In  ifindex 17 92:26:b8:9e:f2:1c ethertype IPv4 (0x0800), length 104: (tos 0x0, ttl 63, id 30481, offset 0, flags [DF], proto ICMP (1), length 84)
    10.16.0.9 > 172.17.0.1: ICMP echo request, id 37989, seq 0, length 64
06:50:58.936574 net1  Out ifindex 2 62:d8:71:90:7b:86 ethertype IPv4 (0x0800), length 104: (tos 0x0, ttl 62, id 30481, offset 0, flags [DF], proto ICMP (1), length 84)
    172.17.0.11 > 172.17.0.1: ICMP echo request, id 39449, seq 0, length 64
06:50:58.936613 net1  In  ifindex 2 02:42:39:79:7f:08 ethertype IPv4 (0x0800), length 104: (tos 0x0, ttl 64, id 26701, offset 0, flags [none], proto ICMP (1), length 84)
    172.17.0.1 > 172.17.0.11: ICMP echo reply, id 39449, seq 0, length 64
06:50:58.936621 eth0  Out ifindex 17 36:7c:6b:c7:82:6b ethertype IPv4 (0x0800), length 104: (tos 0x0, ttl 63, id 26701, offset 0, flags [none], proto ICMP (1), length 84)
    172.17.0.1 > 10.16.0.9: ICMP echo reply, id 37989, seq 0, length 64

OVN Logical Router 中会自动创建路由策略(自定义 VPC 中是静态路由):

$ kubectl ko nbctl lr-policy-list ovn-cluster
Routing Policies
     31000                            ip4.dst == 10.16.0.0/16           allow
     31000                           ip4.dst == 100.64.0.0/16           allow
     30000                              ip4.dst == 172.18.0.2         reroute                100.64.0.3
     30000                              ip4.dst == 172.18.0.3         reroute                100.64.0.2
     30000                              ip4.dst == 172.18.0.4         reroute                100.64.0.4
     29100                            ip4.src == 10.16.0.0/16         reroute                10.16.0.12
     29000 ip4.src == $ovn.default.kube.ovn.control.plane_ip4         reroute                100.64.0.2
     29000       ip4.src == $ovn.default.kube.ovn.worker2_ip4         reroute                100.64.0.4
     29000        ip4.src == $ovn.default.kube.ovn.worker_ip4         reroute                100.64.0.3

如果您需要开启多副本负载均衡,修改 .spec.replicas 即可,示例如下:

$ kubectl scale veg gateway1 --replicas=2
vpcegressgateway.kubeovn.io/gateway1 scaled

$ kubectl get veg gateway1
NAME       VPC           REPLICAS   BFD ENABLED   EXTERNAL SUBNET   PHASE       READY   AGE
gateway1   ovn-cluster   2          false         macvlan           Completed   true    39m

$ kubectl get pod -l ovn.kubernetes.io/vpc-egress-gateway=gateway1 -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE               NOMINATED NODE   READINESS GATES
gateway1-b9f8b4448-76lhm   1/1     Running   0          40m   10.16.0.12   kube-ovn-worker    <none>           <none>
gateway1-b9f8b4448-zd4dl   1/1     Running   0          64s   10.16.0.13   kube-ovn-worker2   <none>           <none>

$ kubectl ko nbctl lr-policy-list ovn-cluster
Routing Policies
     31000                            ip4.dst == 10.16.0.0/16           allow
     31000                           ip4.dst == 100.64.0.0/16           allow
     30000                              ip4.dst == 172.18.0.2         reroute                100.64.0.3
     30000                              ip4.dst == 172.18.0.3         reroute                100.64.0.2
     30000                              ip4.dst == 172.18.0.4         reroute                100.64.0.4
     29100                            ip4.src == 10.16.0.0/16         reroute                10.16.0.12, 10.16.0.13
     29000 ip4.src == $ovn.default.kube.ovn.control.plane_ip4         reroute                100.64.0.2
     29000       ip4.src == $ovn.default.kube.ovn.worker2_ip4         reroute                100.64.0.4
     29000        ip4.src == $ovn.default.kube.ovn.worker_ip4         reroute                100.64.0.3

开启 BFD 高可用

BFD 高可用依赖 VPC 的 BFD LRP 功能,因此需要先修改 VPC 资源,开启 BFD Port。示例如下:

apiVersion: kubeovn.io/v1
kind: Vpc
metadata:
  name: vpc1
spec:
  bfdPort:
    enabled: true
    ip: 10.255.255.255
---
apiVersion: kubeovn.io/v1
kind: Subnet
metadata:
  name: subnet1
spec:
  vpc: vpc1
  protocol: IPv4
  cidrBlock: 192.168.0.0/24

开启 BFD Port 后,对应的 OVN LR 上会自动创建一个专用于 BFD 的 LRP:

$ kubectl ko nbctl show vpc1
router 0c1d1e8f-4c86-4d96-88b2-c4171c7ff824 (vpc1)
    port bfd@vpc1
        mac: "8e:51:4b:16:3c:90"
        networks: ["10.255.255.255"]
    port vpc1-subnet1
        mac: "de:c9:5c:38:7a:61"
        networks: ["192.168.0.1/24"]

完成后,将 VPC Egress Gateway 的 .spec.bfd.enabled 设置为 true 即可。示例如下:

apiVersion: kubeovn.io/v1
kind: VpcEgressGateway
metadata:
  name: gateway2
  namespace: default
spec:
  vpc: vpc1
  replicas: 2
  internalSubnet: subnet1
  externalSubnet: macvlan
  bfd:
    enabled: true
  policies:
    - snat: true
      ipBlocks:
        - 192.168.0.0/24

查看 VPC Egress Gateway 信息:

$ kubectl get veg gateway2 -o wide
NAME       VPC    REPLICAS   BFD ENABLED   EXTERNAL SUBNET   PHASE       READY   INTERNAL IPS                    EXTERNAL IPS                    WORKING NODES                            AGE
gateway2   vpc1   2          true          macvlan           Completed   true    ["192.168.0.2","192.168.0.3"]   ["172.17.0.13","172.17.0.14"]   ["kube-ovn-worker","kube-ovn-worker2"]   58s

$ kubectl get pod -l ovn.kubernetes.io/vpc-egress-gateway=gateway2 -o wide
NAME                       READY   STATUS    RESTARTS   AGE     IP            NODE               NOMINATED NODE   READINESS GATES
gateway2-fcc6b8b87-8lgvx   1/1     Running   0          2m18s   192.168.0.3   kube-ovn-worker2   <none>           <none>
gateway2-fcc6b8b87-wmww6   1/1     Running   0          2m18s   192.168.0.2   kube-ovn-worker    <none>           <none>

$ kubectl ko nbctl lr-route-list vpc1
IPv4 Routes
Route Table <main>:
           192.168.0.0/24               192.168.0.2 src-ip ecmp ecmp-symmetric-reply bfd
           192.168.0.0/24               192.168.0.3 src-ip ecmp ecmp-symmetric-reply bfd

$ kubectl ko nbctl list bfd
_uuid               : 223ede10-9169-4c7d-9524-a546e24bfab5
detect_mult         : 3
dst_ip              : "192.168.0.2"
external_ids        : {af="4", vendor=kube-ovn, vpc-egress-gateway="default/gateway2"}
logical_port        : "bfd@vpc1"
min_rx              : 1000
min_tx              : 1000
options             : {}
status              : up

_uuid               : b050c75e-2462-470b-b89c-7bd38889b758
detect_mult         : 3
dst_ip              : "192.168.0.3"
external_ids        : {af="4", vendor=kube-ovn, vpc-egress-gateway="default/gateway2"}
logical_port        : "bfd@vpc1"
min_rx              : 1000
min_tx              : 1000
options             : {}
status              : up

进入 Pod 查看 BFD 连接:

$ kubectl exec gateway2-fcc6b8b87-8lgvx -c bfdd -- bfdd-control status
There are 1 sessions:
Session 1
 id=1 local=192.168.0.3 (p) remote=10.255.255.255 state=Up

$ kubectl exec gateway2-fcc6b8b87-wmww6 -c bfdd -- bfdd-control status
There are 1 sessions:
Session 1
 id=1 local=192.168.0.2 (p) remote=10.255.255.255 state=Up

配置参数

VPC BFD Port

字段 类型 可选 默认值 说明 示例
enabled boolean false 是否开启 BFD Port。 true
ip string - BFD Port 使用的 IP 地址,不可与其它地址冲突。支持 IPv6 及双栈。 169.255.255.255 / fdff::1 / 169.255.255.255,fdff::1
nodeSelector object - 用于选择承载 BFD Port 工作节点的标签选择器。BFD Port 会绑定一个由选择出来的节点组成的 OVN HA Chassis Group,并以 Active/Backup 的模式工作在 Active 节点上。如果未指定 nodeSelector,Kube-OVN 会自动选择至多三个节点。您可以通过 kubectl ko nbctl list ha_chassis_group 查看当前所有的 OVN HA Chassis Group 资源。 -
nodeSelector.matchLabels dict/map - 键值对形式的标签选择器。 -
nodeSelector.matchExpressions object array - 表达式形式的标签选择器。 -

VPC Egress Gateway

Spec:

字段 类型 可选 默认值 说明 示例
vpc string 默认 VPC 名称(ovn-cluster) VPC 名称。 vpc1
replicas integer/int32 1 副本数。 2
prefix string - 工作负载 Deployment 名称前缀。不可修改。 veg-
image string - 工作负载 Deployment 使用的镜像。 docker.io/kubeovn/kube-ovn:v1.14.0-debug
internalSubnet string VPC 默认子网名称 接入 VPC 网络的子网名称。 subnet1
externalSubnet string - 接入外部网络的子网名称。 ext1
internalIPs string array - 接入 VPC 网络使用的 IP 地址,支持 IPv6 及双栈。指定的 IP 数量不得小于副本数。建议将数量设置为 <replicas> + 1 以避免某些极端情况下 Pod 无法正常创建的问题。 10.16.0.101 / fd00::11 / 10.16.0.101,fd00::11
externalIPs string array - 接入外部网络使用的 IP 地址,支持 IPv6 及双栈。指定的 IP 数量不得小于副本数。建议将数量设置为 <replicas> + 1 以避免某些极端情况下 Pod 无法正常创建的问题。 10.16.0.101 / fd00::11 / 10.16.0.101,fd00::11
bfd object - BFD 配置。 -
policies object array - Egress 策略。可与 selectors 同时配置。 -
selectors object array - 通过 Namespace Selector 以及 Pod Selector 配置 Egress 策略。匹配到的 Pod 将开启 SNAT/MASQUERADE。可与 policies 同时配置。 -
nodeSelector object array - 工作负载的节点选择器,工作负载(Deployment/Pod)将运行在被选择的节点上。 -
trafficPolicy string Cluster 可选值:Cluster/Local仅开启 BFD 时生效。 设置为 Local 时,Egress 流量将优先导向同节点上的 VPC Egress Gateway 实例。若同节点上的 VPC Egress Gateway 实例出现故障,Egress 流量将导向其它实例。 Local

BFD 配置:

字段 类型 可选 默认值 说明 示例
enabled boolean false 是否开启 BFD。 true
minRX integer/int32 1000 BFD minRX 值(ms)。 500
minTX integer/int32 1000 BFD minTX 值(ms)。 500
multiplier integer/int32 3 BFD multiplier 值。 1

Egress 策略:

字段 类型 可选 默认值 说明 示例
snat boolean false 是否开启 SNAT/MASQUERADE。 true
ipBlocks string array - 应用于此 Gateway 的 IP 范围段。支持 IPv6。 192.168.0.1 / 192.168.0.0/24
subnets string array - 应用于此 Gateway 的 VPC 子网名称。支持 IPv6 子网及双栈子网。 subnet1

Selectors:

字段 类型 可选 默认值 说明 示例
namespaceSelector object - Namespace 选择器。空值时将匹配所有 Namespace。 -
namespaceSelector.matchLabels dict/map - 键值对形式的标签选择器。 -
namespaceSelector.matchExpressions object array - 表达式形式的标签选择器。 -
podSelector object - Pod 选择器。空值时将匹配所有 Pod。 -
podSelector.matchLabels dict/map - 键值对形式的标签选择器。 -
podSelector.matchExpressions object array - 表达式形式的标签选择器。 -

节点选择器:

字段 类型 可选 默认值 说明 示例
matchLabels dict/map - 键值对形式的标签选择器。 -
matchExpressions object array - 表达式形式的标签选择器。 -
matchFields object array - 表达式形式的字段选择器。 -

Status:

字段 类型 说明 示例
ready boolean Gateway 是否就绪。 true
phase string Gateway 处理阶段。 Pending / Processing / Completed
internalIPs string array 接入 VPC 网络使用的 IP 地址。 -
externalIPs string array 接入外部网络使用的 IP 地址。 -
workload object 工作负载信息。 -
workload.apiVersion string 工作负载 API 版本。 apps/v1
workload.kind string 工作负载类型。 Deployment
workload.name string 工作负载名称。 gateway1
workload.nodes string array 工作负载所在的节点名称。 -
conditions object array - -

微信群 Slack Support

评论