Skip to content

VM with a direct public IP

You want a virtual machine that is reachable from the internet on its own address - the way a rented server is - rather than one sitting behind a load balancer that publishes a single port. On AWS the closest thing is an EC2 instance in a public subnet with a public IPv4 address attached.

Here that is two objects you already know: a public subnet, and a VM deployed into the project that subnet created. The VM picks up an address from the subnet automatically, on its own network interface.

Prerequisites

  • An account allowed to create projects
  • A free range from the public pool - the subnets list shows what is already claimed
  • An SSH public key, if you want to log in

The step-by-step guide and the console walkthrough cover the operations. The rest of this page explains how it fits together.

What is in the path

flowchart TB
    subgraph VMPATH["VM in a public subnet"]
        direction TB
        NET["internet"] -->|routed, no NAT| FAB["network fabric"]
        FAB -->|BGP| NODE["cluster node"]
        NODE --> VM1["VM - 146.19.177.11 on eth0"]
    end
    subgraph LBPATH["service behind a load balancer"]
        direction TB
        NET2["internet"] --> LB["LoadBalancer address"]
        LB -->|one port, SNAT| SVC["Service"]
        SVC --> POD["pod - cluster-internal address"]
    end

The difference is what holds the address. Behind a load balancer the public address belongs to the Service, one port at a time, and the workload never sees it. In a public subnet the address is configured on the VM's own interface, so every port and every protocol works, and the VM knows its own address.

Load balancer Public subnet
Address lives on the Service the VM's eth0
Exposed per port every port and protocol
Outbound source address SNAT'd the VM's own address
Who filters traffic NetworkPolicy the guest firewall, and any firewall you add

No NAT in either direction

A VM in a public subnet is routed, not translated. Its address is what the internet sees on the way out as well as the way in - so outbound connections carry the VM's own address, which is what reputation-sensitive traffic such as outbound mail depends on.

That symmetry is also the security consequence: nothing in the platform is filtering for you. Other projects start with a default-deny firewall; the project of a public subnet is created without any, so whatever the guest has listening is reachable on that address. The guest firewall is the control, and it is yours to configure.

A NetworkPolicy does apply to a VM - it selects the pod the VM runs in, whether or not a Service is involved - so you can add one to narrow what reaches the VM. From the moment one selects the VM, only what it admits gets through. See Restrict what reaches the VM.

The VM is exposed the moment it boots

Give it a firewall and key-based SSH from the start. Treat it exactly as you would a server placed directly on the internet, because that is what it is.

The platform takes the first two addresses

A subnet is not all yours. OVN takes the first usable address for the gateway the VM routes through, and the second for its own management port. In a /29 such as 146.19.177.8/29:

Address Used by
.8 network address
.9 gateway - the VM's default route
.10 node management port
.11 - .14 your workloads
.15 broadcast

So a /29 gives four usable addresses, not six. OVN claims .9 and .10 itself; there is nothing to declare and no field for them.