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
| Type | Behaviour |
|---|---|
| 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.