Skip to content

Networks

A Network groups endpoints into an isolated network. Endpoints are usually pods but may also be hosts outside the cluster. Networks are isolated by default: an endpoint reaches only its own network unless a routing policy opens a path. See Topology for how networks are connected.

spec.type selects one of three kinds:

  • l3 — typical CNI single-pod network.
  • l2 — suitable for KubeVirt VM workloads.
  • external — external underlay addresses.

Every pod in an L2 or L3 network has an associated NetworkEndpoint recording its address and location.

A routed network with an IPv4 and/or IPv6 subnet.

apiVersion: lace-cni.io/v1alpha1
kind: Network
metadata:
name: backend
spec:
type: l3
ipv4Subnet:
prefix: 10.40.0.0/16
hostLocalPrefixLength: 24

IPAM is host-local:

  • The subnet’s prefix is cut into blocks sized by hostLocalPrefixLength.
  • The controller allocates a block to each node.
  • Each node allocates pod addresses from its own block.
  • A node’s block is recorded in its Allocation, a node-scoped resource holding the prefix(es) given to that node for the network.

Forwarding is routed between the nodes’ blocks:

  • A destination address resolves to the node that owns the covering block.
  • Same-node traffic is delivered over L2.
  • Cross-node traffic is the IP packet encapsulated in SRv6 to the destination node.
  • The gateway is the first address in the node’s block.

A flat network with a subnet whose endpoints share a single L2 domain.

apiVersion: lace-cni.io/v1alpha1
kind: Network
metadata:
name: storage
spec:
type: l2
ipv4Subnet:
prefix: 10.50.0.0/24

IPAM is global:

  • There are no per-node blocks.
  • The controller allocates each pod address directly from the subnet.

Forwarding is by MAC:

  • An address is resolved to a MAC (Neighbor), then forwarded to the MAC’s location (FDBEntry).
  • ARP and NDP are answered locally with synthetic replies instead of being flooded across the network. See BUM traffic.
  • Cross-node traffic is the Ethernet frame encapsulated in SRv6.
  • Addresses on the same subnet and their MACs may also be learned, tracked through the same Neighbor and FDBEntry resources. Learned addresses and MACs may be mobile, moving between locations.
  • The gateway is the first address in the network’s prefix(es).

Defined by prefixes, with no subnet and no IPAM of its own. Represents addresses outside the cluster.

apiVersion: lace-cni.io/v1alpha1
kind: Network
metadata:
name: corp
spec:
type: external
externalPrefixes:
- 192.0.2.0/24

An underlay address is matched to a network by longest prefix match across all external networks’ prefixes. See External networks.

See Data plane for encapsulation.

spec.anonymous suppresses the implicit route that lets endpoints reach their own network. When set, reaching the network (even from its own endpoints) requires an explicit NetworkRoutingPolicy, so the node cannot be used as a transit next hop.

  • spec.typel3, l2, or external. Immutable.
  • spec.ipv4Subnet, spec.ipv6Subnet — the subnet per address family for l3/l2; at least one is required. Both are immutable.
    • prefix — the subnet CIDR.
    • hostLocalPrefixLength — the size of the block carved out per node for host-local IPAM. l3 only.
  • spec.externalPrefixes — the CIDRs reachable through the network. external only, at least one required.
  • spec.anonymous — suppresses the implicit self-route.
  • status.id — the numeric id assigned to the network, used in the data plane.

A NetworkBindingPolicy decides which network a resource binds to.

  • A resource binds to the network of the matching policy.
  • Pods are matched once, when they are created.
  • Services are matched continuously. A service’s network is the context for routing to its endpoints, so it should match the pods it targets.
  • spec.priority — orders policies: the lowest value takes precedence, ties broken lexicographically by name. Defaults to 0.
  • spec.matchKind — scopes the policy to pod, service, and/or networkpolicy resources. Omitted matches every kind.
  • spec.rules — an ordered list; at least one rule is required. The highest-priority matching rule decides the binding.
    • network — the static network the rule binds to, or (for a deny rule) shields. An allow rule sets exactly one of network or celExpression.
    • celExpression — derives the network name dynamically from the resource instead of naming it statically (see below).
    • policyallow (default) binds the network; deny shields it from lower-priority policies and selects by name only.
    • selector — selects the resource by name, or by matchLabels/matchExpressions, with an optional nested namespaceSelector that further scopes the match to namespaces whose labels match.

An allow rule may set celExpression instead of a static network. The selectors filter first, then the expression resolves the name from the matched resource. The resource is exposed as object, an unstructured map, and the expression must evaluate to an optional string:

  • An absent optional means the rule does not match — evaluation continues with the next rule.
  • A present value is the network name; an empty string is allowed and behaves like an unbound network.

This binds a pod to the network named after its namespace with a team- prefix stripped (e.g. namespace team-blue → network blue), falling through to a default otherwise:

apiVersion: lace-cni.io/v1alpha1
kind: NetworkBindingPolicy
metadata:
name: per-team
spec:
matchKind: [pod]
rules:
- celExpression: >-
object.metadata.namespace.startsWith('team-')
? optional.of(object.metadata.namespace.substring(5))
: optional.none()
- network: default

Within a policy, rules are tried in order: the CEL rule yields nothing for namespaces without the prefix, so the walk falls through to the default rule.

Expressions are compiled and validated once. A policy whose expression is invalid is ignored by binding entirely, and its status carries a CELValid condition reporting the error.