Skip to content

VPC Nat Gateway Functionality from KuebOVN#985

Merged
w13915984028 merged 2 commits intoharvester:mainfrom
rrajendran17:vpcnatgw
Mar 27, 2026
Merged

VPC Nat Gateway Functionality from KuebOVN#985
w13915984028 merged 2 commits intoharvester:mainfrom
rrajendran17:vpcnatgw

Conversation

@rrajendran17
Copy link
Copy Markdown
Contributor

Problem:

Add documentation for VPC Nat Gateway functionality for external and inbound access for overlay VMs

Solution:

Add documentation for VPC Nat Gateway functionality for external and inbound access for overlay VMs

Related Issue(s):

harvester/harvester#9455

Test plan:

Additional documentation or context

Copilot AI review requested due to automatic review settings March 7, 2026 00:43
@rrajendran17 rrajendran17 requested a review from a team March 7, 2026 00:48
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 7, 2026

Name Link
🔨 Latest commit ecaaf74
😎 Deploy Preview https://69c5fc1cc74008d0563f62e3--harvester-preview.netlify.app

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new documentation page describing how to use Kube-OVN VPC NAT Gateway to provide outbound (SNAT) and inbound (DNAT) connectivity for overlay VMs, including an end-to-end example configuration.

Changes:

  • Introduces a new doc page for VPC NAT Gateway concepts and workflow.
  • Provides example manifests for NADs, VPC/Subnets, VpcNatGateway, and iptables-based EIP/SNAT/DNAT rules.
  • Includes verification steps and expected outputs (StatefulSet/Pod details, interfaces, iptables rules).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


Kube-OVN supports NAT via Kubernetes custom resources (CRDs), not just IP-tables directly. For example, resources like OvnEip, OvnSnatRule, OvnDnatRule (or their iptables-based equivalents) are used to define NAT behavior declaratively. In the context of Harvester, the VM orchestration (compute, storage, VM lifecycle) is handled by Harvester; networking — including routing, NAT, VPC/subnets — is handled by Kube-OVN. This separation allows for more scalable, flexible and clean networking.

## KubeOVN as Secondary CNI
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This heading has inconsistent spacing and product naming. Elsewhere the docs use "Kube-OVN"; consider renaming the heading accordingly and removing the extra space after the ## so it renders consistently in navigation/TOC.

Suggested change
## KubeOVN as Secondary CNI
## Kube-OVN as Secondary CNI

Copilot uses AI. Check for mistakes.
Comment on lines +56 to +65
```
kubectl get net-attach-def vswitchexternal1 -o yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
labels:
network.harvesterhci.io/ready: "true"
network.harvesterhci.io/type: OverlayNetwork
name: vswitchexternal
namespace: kube-system
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example command is querying vswitchexternal1, but the manifest shown below sets metadata.name: vswitchexternal. Readers following this will likely get a NotFound error; please make the resource name consistent (either change the command or the manifest name).

Copilot uses AI. Check for mistakes.
Comment on lines +130 to +134
kind: VpcNatGateway
apiVersion: kubeovn.io/v1
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: default/vswitchinternal
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency with the other YAML snippets in this doc (and most Kubernetes examples), put apiVersion before kind. Also consider fixing the extra indentation under metadata.annotations to make the YAML easier to copy/paste without confusion.

Suggested change
kind: VpcNatGateway
apiVersion: kubeovn.io/v1
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: default/vswitchinternal
apiVersion: kubeovn.io/v1
kind: VpcNatGateway
metadata:
annotations:
k8s.v1.cni.cncf.io/networks: default/vswitchinternal

Copilot uses AI. Check for mistakes.
```

##### Create a VM and attach it to the vswitchinternal overlay network and add the following default route in the guest os.
(172.20.10.254 is the ip addresses on net1 interface on vpc nat gw pod)
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "ip addresses" should be singular here (and consider capitalizing "IP").

Suggested change
(172.20.10.254 is the ip addresses on net1 interface on vpc nat gw pod)
(172.20.10.254 is the IP address on net1 interface on vpc nat gw pod)

Copilot uses AI. Check for mistakes.

Flexible networking for VPCs / overlay networks: Using NAT (SNAT / DNAT) with Kube-OVN means you can build isolated private subnets / VPCs and still allow controlled egress (outbound) or ingress (inbound) traffic. This is especially relevant for VM workloads managed by Harvester, where VMs may need internet access or to expose services externally.

Kube-OVN supports NAT via Kubernetes custom resources (CRDs), not just IP-tables directly. For example, resources like OvnEip, OvnSnatRule, OvnDnatRule (or their iptables-based equivalents) are used to define NAT behavior declaratively. In the context of Harvester, the VM orchestration (compute, storage, VM lifecycle) is handled by Harvester; networking — including routing, NAT, VPC/subnets — is handled by Kube-OVN. This separation allows for more scalable, flexible and clean networking.
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the standard term "iptables" here (instead of "IP-tables") to match common Linux/Kube-OVN terminology and avoid confusion when cross-referencing commands like iptables-save.

Suggested change
Kube-OVN supports NAT via Kubernetes custom resources (CRDs), not just IP-tables directly. For example, resources like OvnEip, OvnSnatRule, OvnDnatRule (or their iptables-based equivalents) are used to define NAT behavior declaratively. In the context of Harvester, the VM orchestration (compute, storage, VM lifecycle) is handled by Harvester; networking — including routing, NAT, VPC/subnets — is handled by Kube-OVN. This separation allows for more scalable, flexible and clean networking.
Kube-OVN supports NAT via Kubernetes custom resources (CRDs), not just iptables directly. For example, resources like OvnEip, OvnSnatRule, OvnDnatRule (or their iptables-based equivalents) are used to define NAT behavior declaratively. In the context of Harvester, the VM orchestration (compute, storage, VM lifecycle) is handled by Harvester; networking — including routing, NAT, VPC/subnets — is handled by Kube-OVN. This separation allows for more scalable, flexible and clean networking.

Copilot uses AI. Check for mistakes.
Comment on lines +175 to +182
externalvswitch.kube-system.ovn.kubernetes.io/routes: '[{"dst":"0.0.0.0/0","gw":"10.115.55.254"}]'
internalvswitch.default.ovn.kubernetes.io/ip_address: 172.20.10.254
internalvswitch.default.ovn.kubernetes.io/logical_switch: internalsubnet
internalvswitch.default.ovn.kubernetes.io/routes: '[{"dst":"10.55.0.0/16","gw":"172.20.10.1"},{"dst":"10.115.48.0/21","gw":"172.20.10.1"}]'
internalvswitch.default.ovn.kubernetes.io/vpc_nat_gw: gw1
k8s.v1.cni.cncf.io/networks: default/internalvswitch, kube-system/externalvswitch
ovn.kubernetes.io/ip_address: 172.20.10.254
ovn.kubernetes.io/logical_switch: internalsubnet
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The StatefulSet/pod output uses internalvswitch/externalvswitch and internalsubnet/externalsubnet, but the earlier examples define vswitchinternal/vswitchexternal and subnetinternal/subnetexternal. This mismatch makes it hard to follow which names should be used; please align the examples/outputs to the same object names (or add an explicit note explaining why the names differ).

Suggested change
externalvswitch.kube-system.ovn.kubernetes.io/routes: '[{"dst":"0.0.0.0/0","gw":"10.115.55.254"}]'
internalvswitch.default.ovn.kubernetes.io/ip_address: 172.20.10.254
internalvswitch.default.ovn.kubernetes.io/logical_switch: internalsubnet
internalvswitch.default.ovn.kubernetes.io/routes: '[{"dst":"10.55.0.0/16","gw":"172.20.10.1"},{"dst":"10.115.48.0/21","gw":"172.20.10.1"}]'
internalvswitch.default.ovn.kubernetes.io/vpc_nat_gw: gw1
k8s.v1.cni.cncf.io/networks: default/internalvswitch, kube-system/externalvswitch
ovn.kubernetes.io/ip_address: 172.20.10.254
ovn.kubernetes.io/logical_switch: internalsubnet
vswitchexternal.kube-system.ovn.kubernetes.io/routes: '[{"dst":"0.0.0.0/0","gw":"10.115.55.254"}]'
vswitchinternal.default.ovn.kubernetes.io/ip_address: 172.20.10.254
vswitchinternal.default.ovn.kubernetes.io/logical_switch: subnetinternal
vswitchinternal.default.ovn.kubernetes.io/routes: '[{"dst":"10.55.0.0/16","gw":"172.20.10.1"},{"dst":"10.115.48.0/21","gw":"172.20.10.1"}]'
vswitchinternal.default.ovn.kubernetes.io/vpc_nat_gw: gw1
k8s.v1.cni.cncf.io/networks: default/vswitchinternal, kube-system/vswitchexternal
ovn.kubernetes.io/ip_address: 172.20.10.254
ovn.kubernetes.io/logical_switch: subnetinternal

Copilot uses AI. Check for mistakes.

```

##### Verify SNAT filter iptable rule created inside the VPC NAT gateway pod
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "iptable" should be "iptables" (the command examples below use iptables-legacy-save).

Suggested change
##### Verify SNAT filter iptable rule created inside the VPC NAT gateway pod
##### Verify SNAT filter iptables rule created inside the VPC NAT gateway pod

Copilot uses AI. Check for mistakes.
```

Ping from VM (inside guest os) to 8.8.8.8 must be successful
The traffic from VM reaches net1 of vpc nat gw pod and with route installed egress out of net2 and hits the iptable rule for SNAT and translates 172.20.10.0/24 subnet ip to 10.115.55.200 for external connectivity.
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "iptable" should be "iptables".

Suggested change
The traffic from VM reaches net1 of vpc nat gw pod and with route installed egress out of net2 and hits the iptable rule for SNAT and translates 172.20.10.0/24 subnet ip to 10.115.55.200 for external connectivity.
The traffic from VM reaches net1 of vpc nat gw pod and with route installed egress out of net2 and hits the iptables rule for SNAT and translates 172.20.10.0/24 subnet ip to 10.115.55.200 for external connectivity.

Copilot uses AI. Check for mistakes.
test nginx locally on the VM
curl http://127.0.0.1

Now curl -k http://10.115.55.200:8888 from external must be successful
Copy link

Copilot AI Mar 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curl -k disables TLS certificate verification, but this example uses plain HTTP (http://). Either drop -k or switch the example to https:// if TLS is intended; as written, -k is misleading.

Suggested change
Now curl -k http://10.115.55.200:8888 from external must be successful
Now curl http://10.115.55.200:8888 from external must be successful

Copilot uses AI. Check for mistakes.
akashraj4261
akashraj4261 previously approved these changes Mar 17, 2026
Copy link
Copy Markdown
Member

@w13915984028 w13915984028 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, some suggestions.


Flexible networking for VPCs / overlay networks: Using NAT (SNAT / DNAT) with Kube-OVN means you can build isolated private subnets / VPCs and still allow controlled egress (outbound) or ingress (inbound) traffic. This is especially relevant for VM workloads managed by Harvester, where VMs may need internet access or to expose services externally.

Kube-OVN supports NAT via Kubernetes custom resources (CRDs), not just IP-tables directly. For example, resources like OvnEip, OvnSnatRule, OvnDnatRule (or their iptables-based equivalents) are used to define NAT behavior declaratively. In the context of Harvester, the VM orchestration (compute, storage, VM lifecycle) is handled by Harvester; networking — including routing, NAT, VPC/subnets — is handled by Kube-OVN. This separation allows for more scalable, flexible and clean networking.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(compute, storage, VM lifecycle)
->
(compute, storage, VM lifecycle, L2 VLAN based networking, underlay networking)

networking — including routing, NAT, VPC/subnets
->
overlay networking — including routing, NAT, VPC/subnets


### Example Configuration and Working

#### Create a network attachment definition (tenant or internal network)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the configuration process available on UI now? when true, please also add descriptions about how to create things on UI step by step

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UI is planned for v1.9.0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please mention this on doc, UI is not available on v180, thanks.

"/run/openvswitch/kube-ovn-daemon.sock", "provider": "vswitchinternal.default.ovn"}'
```

#### Create a network attachment definition (external network)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will be helpful on readability to have

diagram to show the traffic in/out

or

diagram to show the raltionships of those CRDs

w13915984028
w13915984028 previously approved these changes Mar 26, 2026
Copy link
Copy Markdown
Member

@w13915984028 w13915984028 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, the steps and details are very helpful, thanks.

Signed-off-by: Renuka Devi Rajendran <renuka.rajendran@suse.com>
@rrajendran17
Copy link
Copy Markdown
Contributor Author

rrajendran17 commented Mar 27, 2026

@w13915984028 I have updated the flow diagram to be even more clearer.Can you please review and approve? We can merge this.

Copy link
Copy Markdown
Member

@w13915984028 w13915984028 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks.

@w13915984028 w13915984028 merged commit aabde1e into harvester:main Mar 27, 2026
3 checks passed
@rrajendran17 rrajendran17 deleted the vpcnatgw branch March 27, 2026 08:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants