跳转至

VPC Egress Gateway

VPC Egress Gateway 用于控制 VPC(包括默认 VPC)内 Pod 访问外部网络。VPC Egress Gateway 参考了 VPC NAT Gateway 的设计,在 VPC NAT Gateway 的基础上实现了基于 ECMP 路由的负载均衡以及基于 BFD 的高可用,并支持 IPv6 以及双栈。

VPC Egress Gateway 支持默认 VPC 及自定义 VPC。

使用要求

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 策略。必须配置至少一条策略。 -
nodeSelector object array - 工作负载的节点选择器,工作负载(Deployment/Pod)将运行在被选择的节点上。 -

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

节点选择器:

字段 类型 可选 默认值 说明 示例
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

评论