Skip to content

VPC Nat Gateway Functionality from KuebOVN#985

Open
rrajendran17 wants to merge 1 commit intoharvester:mainfrom
rrajendran17:vpcnatgw
Open

VPC Nat Gateway Functionality from KuebOVN#985
rrajendran17 wants to merge 1 commit intoharvester:mainfrom
rrajendran17:vpcnatgw

Conversation

@rrajendran17
Copy link
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

Signed-off-by: Renuka Devi Rajendran <renuka.rajendran@suse.com>
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

github-actions bot commented Mar 7, 2026

Name Link
🔨 Latest commit 61793e4
😎 Deploy Preview https://69ab759c36f88fb5f0351a7a--harvester-preview.netlify.app

Copy link
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.
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.

2 participants