Skip to content

ExternalIP (IPPool) Resource Kind

Kind: ExternalIPapiVersion: pivirt.hu/v1Aliases: ippool, extip, ip

The ExternalIP resource (also addressed via the alias IPPool) binds public or external IP addresses, 1:1 NAT mappings, and granular port-forwarding rules from physical interfaces to guest virtual machines on private subnets.

With namespace set, the binding lives inside that VPCRouter’s network namespace — the address goes on the router’s uplink interface and the NAT rules into the router’s own nftables table — so two VPCs with the same private CIDR keep their bindings apart. Without it, the binding is in the host namespace: the single-host form. The director realizes a tenant’s FloatingIP as an ExternalIP on the VPC’s router.


In pivirtctl commands, any of the following aliases are recognized: ExternalIP, externalip, externalips, external-ip, external-ips, ippool, ippools, ip-pool, ip-pools, extip, extips, ip, ips.


apiVersion: pivirt.hu/v1
kind: ExternalIP
metadata:
name: web-ingress-ip
labels:
role: ingress
service: frontend
spec:
address: "203.0.113.50"
prefixLen: 24
interface: eth0
internalIP: "192.168.100.10"
portForwards:
- protocol: tcp
externalPort: 80
internalPort: 80
- protocol: tcp
externalPort: 443
internalPort: 443

Field Type Required Default Description
address string Yes Public/external IPv4 address (pivirtd’s NAT table is IPv4; IPv6 prefixes are routed, not translated)
prefixLen int No 32 Prefix length the address is configured with on the interface
interface string Outside a namespace uplink inside a router Interface to bind the address to
internalIP string Yes Target VM private IPv4 address
namespace string No The VPCRouter network namespace holding the NAT table
portForwards list No [] Forward only these ports instead of the whole address
portForwards[].protocol string No tcp Transport protocol: tcp or udp
portForwards[].externalPort int Yes Port number on the external IP address
portForwards[].internalPort int Yes Destination port number on the guest private IP

  • 1:1 mode (no portForwards): DNAT address → internalIP in prerouting, SNAT internalIP → address in postrouting, and a forward accept for the guest. The guest’s outbound traffic leaves with the public address.
  • Port-forward mode: one DNAT and one forward accept per entry, plus the SNAT — only the listed ports reach the guest.
  • Re-apply is honest. Rule comments carry a fingerprint of the spec: an unchanged binding is recognised as installed and issues nothing; a changed internalIP drops the old rules, installs the new ones, and flushes conntrack for the address so existing flows stop following the old target.
  • Removal deletes exactly this binding’s rules (by comment prefix), the address, and its conntrack entries — nothing else in the table is touched.
  • A binding in a namespace fails with a clear message until that VPCRouter exists on the host.

Terminal window
# Apply external IP manifest
pivirtctl apply -f external-ip.yaml
# List all external IPs (using IPPool alias)
pivirtctl get ippools
# List using multi-word kind alias
pivirtctl get ip pools
# Inspect bindings and forward status
pivirtctl describe ippool web-ingress-ip
# Delete external IP (removes the address, its nftables rules and conntrack entries)
pivirtctl delete ippool web-ingress-ip