Show examples as

Networks

kcore supports three network types for VMs: NAT, bridge, and VXLAN. Each type creates a Linux bridge (kbr-<name>) and optionally provides DHCP, masquerade, or overlay connectivity.

Supported network types

TypeBehaviour
NAT (default) Linux bridge with dnsmasq DHCP (range .100–.199) and nftables masquerade + DNAT from externalIP. Single-node only.
Bridge Physical NIC (or VLAN sub-interface) added as a bridge port. VMs use upstream DHCP. No local DHCP or NAT.
VXLAN L2 overlay across nodes (VXLAN/UDP 4789). VM addresses are allocated cluster-wide for that network name (no duplicate IPs on the same overlay). Cloud-init applies static addressing; no local dnsmasq. When nodes join or leave, peer forwarding is updated on all participants. Optional outbound NAT. Same logical name on each node shares one VNI and subnet.

VXLAN in a cluster

Default network

A default network is auto-created on every node during installation. It is always NAT type and cannot be deleted or created via kctl.

Create a network

kctl create network private \
  --external-ip 192.168.40.105 \
  --gateway-ip 10.250.0.1 \
  --internal-netmask 255.255.255.0 \
  --type vxlan
kind: Network
metadata:
  name: private
spec:
  type: vxlan
  externalIp: 192.168.40.105
  gatewayIp: 10.250.0.1
  internalNetmask: "255.255.255.0"

Apply: kctl apply -f network.yaml

Showing Terraform examples. Provider source is kcorehypervisor/kcore, version 0.5.0.

resource "kcore_network" "private" {
  name             = "private"
  network_type     = "vxlan"
  external_ip      = "192.168.40.105"
  gateway_ip       = "10.250.0.1"
  internal_netmask = "255.255.255.0"
}

List, describe, delete

# One row per logical network name (example)
kctl get networks
# NAME   TYPE   GATEWAY      NETMASK         VLAN  OVERLAY  BRIDGE           NODES
# prod   vxlan  10.100.0.1   255.255.255.0   -     yes      kbr-prod         3

# Full detail: overlay flag, bridge name, every node (VTEP for VXLAN)
kctl describe network prod

# Remove (use --target-node when deleting one node’s copy of a shared name)
kctl delete network prod

VLAN tagging

NAT and bridge networks support VLAN tagging via --vlan-id. When specified, kcore creates a VLAN sub-interface (gatewayInterface.<id>) and uses it as the bridge uplink.

kctl create network vlan-net \
  --type nat \
  --vlan-id 100 \
  --external-ip 192.168.100.10 \
  --gateway-ip 10.100.0.1 \
  --internal-netmask 255.255.255.0
kind: Network
metadata:
  name: vlan-net
spec:
  type: nat
  vlanId: 100
  externalIp: 192.168.100.10
  gatewayIp: 10.100.0.1
  internalNetmask: "255.255.255.0"

Apply: kctl apply -f network.yaml

resource "kcore_network" "vlan_net" {
  name             = "vlan-net"
  network_type     = "nat"
  vlan_id          = 100
  external_ip      = "192.168.100.10"
  gateway_ip       = "10.100.0.1"
  internal_netmask = "255.255.255.0"
}

Disable VXLAN on a node

If a node should not participate in VXLAN overlays, pass --disable-vxlan during installation:

kctl node install ... --disable-vxlan
resource "kcore_node" "worker" {
  address         = "192.168.40.151:9091"
  os_disk         = "/dev/sda"
  certs_dir       = kcore_cluster.prod.certs_dir
  join_controller = "192.168.40.107:9090"
  disable_vxlan   = true
  insecure        = true
}

The controller will reject VXLAN network creation requests targeting that node with a FailedPrecondition error.

IPv6

A network stays IPv4-only until it is given a /64 whose host bits are clear. The gateway must be the first address of that prefix. The controller then assigns each NIC the next host address, starting at ::2, and cloud-init adds it beside the IPv4 address. The bridge receives the gateway. There is no DHCPv6.

kctl create network overlay \
  --external-ip 0.0.0.0 \
  --gateway-ip 10.240.0.1 \
  --type vxlan \
  --ipv6-prefix fd00:10:240::/64 \
  --ipv6-gateway fd00:10:240::1
kind: Network
metadata:
  name: overlay
spec:
  type: vxlan
  externalIp: 0.0.0.0
  gatewayIp: 10.240.0.1
  ipv6Prefix: fd00:10:240::/64
  ipv6Gateway: fd00:10:240::1
resource "kcore_network" "overlay" {
  name             = "overlay"
  network_type     = "vxlan"
  external_ip      = "0.0.0.0"
  gateway_ip       = "10.240.0.1"
  ipv6_prefix      = "fd00:10:240::/64"
  ipv6_gateway     = "fd00:10:240::1"
}

East-west firewall

--east-west-firewall (YAML spec.eastWestFirewall: true) drops VM-to-VM traffic on that bridge. Established flows, the gateway, DHCP, and security-group rules that name a target IP stay allowed. The filter is off unless the network asks for it. On a 255.255.255.0 mask the drop covers the /24.

resource "kcore_network" "overlay" {
  name               = "overlay"
  network_type       = "vxlan"
  external_ip        = "0.0.0.0"
  gateway_ip         = "10.240.0.1"
  ipv6_prefix        = "fd00:10:240::/64"
  ipv6_gateway       = "fd00:10:240::1"
  east_west_firewall = true
}

Multi-homed VMs

NIC 0 is --network and owns the guest default route. Repeat --extra-network for each further network, up to eight NICs in total. Two NICs on the same VM cannot join the same network. NAT extras get a DHCP reservation that does not replace the default route. VXLAN extras get a static address and no gateway.

kctl create vm web --network frontend --extra-network backend

image_url and image_path are mutually exclusive. URL mode needs image_sha256. cpu and memory_bytes are required.

resource "kcore_vm" "web" {
  name               = "web"
  cpu                = 2
  memory_bytes       = 4 * 1024 * 1024 * 1024
  storage_backend    = "filesystem"
  storage_size_bytes = 40 * 1024 * 1024 * 1024
  image_url          = "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2"
  image_sha256       = "<sha256>"

  nic {
    network = "frontend"
  }

  nic {
    network = "backend"
  }
}

VM network attachment

Attach a VM to a network at creation time:

kctl create vm web-01 --network private --image ubuntu-24.04 --cpus 2 --memory 4096
kind: VM
metadata:
  name: web-01
spec:
  cpu: 2
  memoryBytes: "4G"
  storageBackend: filesystem
  storageSizeBytes: "40G"
  nics:
    - network: private
  disks:
    - image: https://...
      sha256: "<sha256>"
      format: qcow2

Apply: kctl apply -f vm.yaml

image_url and image_path are mutually exclusive. URL mode needs image_sha256. cpu and memory_bytes are required.

resource "kcore_vm" "web" {
  name               = "web-01"
  cpu                = 2
  memory_bytes       = 4 * 1024 * 1024 * 1024
  storage_backend    = "filesystem"
  storage_size_bytes = 40 * 1024 * 1024 * 1024
  image_url          = "https://..."
  image_sha256       = "<sha256>"

  nic {
    network = "private"
  }
}

VMs on VXLAN networks receive controller-assigned static IPs (unique across the cluster for that overlay name) via cloud-init. VMs on NAT networks receive IPs from dnsmasq DHCP.