Docs
Kubernetes

Technical Information

Kubernetes to NetBox Object Mapping

This page describes how Kubernetes data is mapped to NetBox objects by the integration.

Data flows in one direction only, from Kubernetes to NetBox. The integration never writes to the cluster.

The integration makes these read-only calls to the cluster's API server:

API callUsed for
List nodes (/api/v1/nodes)Nodes, their roles, status, addresses, and pod CIDRs
Read the kube-system namespace (/api/v1/namespaces/kube-system)The cluster's identity (the namespace UID)
List services in all namespaces (/api/v1/services)LoadBalancer service addresses
API discovery for networking.k8s.io/v1Whether the cluster serves the ServiceCIDR resource
List service CIDRs (/apis/networking.k8s.io/v1/servicecidrs)Service blocks

Node and service lists are read in pages of 500. Each request times out after 30 seconds. Requests that fail with HTTP status 429, 500, 502, 503, or 504 are retried up to three times with backoff, honoring any Retry-After header the API server sends.

Object Type Mapping Table

Kubernetes sourceNetBox ObjectKey Fields Mapped
(static)ClusterTypeKubernetes
(static)ClusterGroupKubernetes
CLUSTER_NAME and the kube-system namespaceClusterCLUSTER_NAME → name, type and group Kubernetes, status "active", namespace UID → custom_fields.nbl_matching_id
(static, device mode)ManufacturerKubernetes
(static, device mode)DeviceTypeKubernetes Node, manufacturer Kubernetes
Node node-role.kubernetes.io/* labelsDeviceRoleRole name (see Node role mapping)
Node (NODE_OBJECT_TYPE: device)Devicemetadata.name → name, device type Kubernetes Node, role, site SITE_NAME, cluster, status, custom fields (see Nodes)
Node (NODE_OBJECT_TYPE: virtual_machine)VirtualMachinemetadata.name → name, cluster, role, status, custom fields (see Nodes)
NodeInterface or VMInterfaceOne per node, named kubernetes. Devices get type virtual
Node status.addresses (InternalIP, ExternalIP)IPAddressHost address (/32 or /128), global table, assigned to the node's kubernetes interface
(per cluster)VRFCLUSTER_NAME → name, route distinguisher derived from the kube-system namespace UID
Node spec.podCIDRsPrefixEach node's pod CIDR, in the cluster VRF, is_pool and mark_utilized set
ServiceCIDR spec.cidrsPrefixEach service CIDR, in the cluster VRF, is_pool and mark_utilized set
LoadBalancer service status.loadBalancer.ingress[].ipIPAddressHost address, global table, custom_fields.k8s_namespace and custom_fields.k8s_service_name

Choosing a node object type and site

Two configuration values cannot be changed safely after the first run. Decide them before you configure the agent.

NODE_OBJECT_TYPE

Every node becomes either a NetBox device or a NetBox virtual machine. There is no default: you must set NODE_OBJECT_TYPE to device or virtual_machine, and the integration never detects it.

  • Use device for bare-metal nodes.
  • Use virtual_machine for nodes that run as virtual machines. If a hypervisor integration, such as VMware vCenter or Proxmox VE, already syncs the machines your nodes run on, virtual_machine avoids competing with it for the same device records.

The integration never deletes objects from NetBox. If you change NODE_OBJECT_TYPE later, every record written under the previous type stays in NetBox, and the nodes are recorded again under the new type.

The setting applies to every node in a policy. It cannot be set per node.

SITE_NAME

In device mode, every node device is placed in the site named by SITE_NAME, which is required. NetBox identifies a device by its name and site. If the site already contains devices with the same names as your nodes, the integration updates those existing records, including their device type and role, instead of creating new devices. This is what you want when NetBox already holds your bare-metal servers under their node names. Otherwise, choose a site that does not contain devices with your node names.

In device mode, the named site also receives the integration's tags. See Known Limitations.

In virtual_machine mode, virtual machines are not placed in a site, and SITE_NAME is not used.

Cluster Mapping

Each policy creates one NetBox cluster:

  • Name - the value of CLUSTER_NAME. Kubernetes has no API that reports a cluster's name, so this setting is required and has no default. It can be at most 89 characters, because the integration also creates a tag named kubernetes-<CLUSTER_NAME>, and NetBox limits tag names to 100 characters.
  • Type and group - both Kubernetes.
  • Status - always active. Kubernetes does not report a cluster-level health status.
  • Identity - the UID of the cluster's kube-system namespace is stored in the nbl_matching_id custom field. If you change CLUSTER_NAME, the existing cluster record is found by this UID and renamed, instead of a second cluster being created.

The cluster is not assigned to a site.

Nodes

Node fields

NetBox fieldDevice (device mode)Virtual machine (virtual_machine mode)
Namemetadata.namemetadata.name
ClusterThe policy's clusterThe policy's cluster
SiteSITE_NAMENot set
Device typeKubernetes Node (manufacturer Kubernetes)Not applicable
RoleFrom node role labels (see Node role mapping)From node role labels
StatusFrom the Ready condition (see Node status)From the Ready condition
nbl_matching_idstatus.nodeInfo.systemUUID, when unique (see Node identity)Same as device
k8s_system_uuidstatus.nodeInfo.systemUUIDSame as device
k8s_provider_idspec.providerIDSame as device

A node device appears on its cluster's page in NetBox, so the cluster lists the machines that belong to it.

Node role mapping

Each node's role comes from its node-role.kubernetes.io/<role> labels. The label suffix is converted to a role name by replacing hyphens and underscores with spaces, capitalizing each word, and adding the prefix Kubernetes:

Node labelNetBox role
node-role.kubernetes.io/control-planeKubernetes Control Plane
node-role.kubernetes.io/masterKubernetes Master
node-role.kubernetes.io/etcdKubernetes Etcd
(no role label)Kubernetes Node

Worker nodes usually carry no role label, so they get Kubernetes Node.

When a node carries more than one role label, the label suffix that sorts first alphabetically is used. For example, a node with both control-plane and master labels, common on clusters upgraded from older kubeadm versions, gets Kubernetes Control Plane.

Roles are created only for role names found on the nodes in scope. In device mode, roles are created as device-only roles. In virtual_machine mode, they are created as roles that can be assigned to virtual machines.

Node status

Node Ready conditionNetBox status
Trueactive
False or Unknownoffline
(no Ready condition reported)active

A cordoned node (spec.unschedulable) is still Ready, so it stays active.

Node identity

A node is matched to an existing NetBox record by its system UUID (status.nodeInfo.systemUUID), stored in the nbl_matching_id custom field. If you rename a node in Kubernetes, the existing NetBox record is found by this UUID and renamed.

The system UUID is not used as the matching ID in two cases:

  • The node reports no system UUID. The integration logs a warning naming the node.
  • More than one node reports the same system UUID. This usually happens when virtual machines are cloned from a template without regenerating the UUID. The nbl_matching_id field must be unique in NetBox, so none of the nodes sharing the UUID uses it. The integration logs a warning naming the nodes.

In both cases the node is matched by name (and site in device mode, or cluster in virtual_machine mode) instead. The node is still synced, but renaming it creates a new NetBox record rather than updating the existing one. k8s_system_uuid is recorded either way.

Interfaces and Node Addresses

Kubernetes does not expose a node's network interfaces, so the integration creates one interface per node to hold its addresses:

  • Name - kubernetes. It is deliberately not a real interface name such as eth0, so that it never updates an existing interface on a server record the integration adopts.
  • Type - virtual, for device interfaces. Virtual machine interfaces have no type.

Each node's InternalIP and ExternalIP addresses from status.addresses are created as IP addresses:

  • Addresses are host addresses: /32 for IPv4 and /128 for IPv6.
  • They are created in the global table (no VRF), because they are real addresses on your network.
  • Each is assigned to its node's kubernetes interface.
  • IPv6 link-local addresses are skipped.
  • Hostname entries in status.addresses are not addresses and are ignored.
  • If two nodes report the same address, it is assigned only to the first node read, and the integration logs a warning naming both nodes.

Nodes are not given a primary IP. See Known Limitations.

VRF and Prefixes

Cluster VRF

Each cluster gets a VRF that holds its pod and service blocks. Many clusters use the same default private ranges, such as 10.244.0.0/16 for pods, and without a VRF per cluster those blocks would collapse into one NetBox prefix shared by every cluster.

  • Name - the value of CLUSTER_NAME.
  • Route distinguisher - k8s: followed by 17 hexadecimal characters derived from a hash of the kube-system namespace UID, for example k8s:9e49cfecc54d38c87. It is generated by the integration so that the VRF keeps its identity if CLUSTER_NAME changes. It is not a route distinguisher used in your network.

Node addresses and LoadBalancer service addresses are not placed in this VRF.

Pod prefixes

Each node's pod CIDRs are read from spec.podCIDRs, giving one prefix per address family on dual-stack clusters. Older clusters that report only spec.podCIDR are also supported. A node with no pod CIDR assigned produces no pod prefix.

Service prefixes

Each CIDR in the spec.cidrs of each ServiceCIDR object is created as a prefix. A cluster can hold several ServiceCIDR objects, and all of them are read.

The networking.k8s.io/v1 ServiceCIDR resource is available from Kubernetes 1.33. If the cluster does not serve it, which is typical of clusters older than 1.33, or the service account cannot read it, no service prefix is created and the rest of the sync continues.

Prefix fields

All pod and service prefixes:

  • are placed in the cluster VRF
  • have Is a pool (is_pool) set
  • have Mark utilized (mark_utilized) set, because the addresses inside them are deliberately not synced. Without it, a block would look empty in NetBox and invite someone to allocate from it

Prefixes are deduplicated by CIDR. Single-address blocks (/32, /128) and values that cannot be parsed are skipped with a warning.

LoadBalancer Service Addresses

For each service of type LoadBalancer, every IP address in status.loadBalancer.ingress is created as an IP address:

  • Host address (/32 or /128), in the global table.
  • The service's namespace and name are recorded in the k8s_namespace and k8s_service_name custom fields.
  • The integration sets only the address and these two custom fields. An existing NetBox record for the address, for example one created by your own IPAM process, keeps its description, status, and other values.
  • The address is not assigned to any interface, because it is answered by a load balancer or by any node, not by a single interface.

Additional behavior:

  • Services of other types (ClusterIP, NodePort, ExternalName) are not read for addresses.
  • A LoadBalancer with no ingress yet produces nothing until an address is assigned.
  • A LoadBalancer whose ingress is a hostname, not an IP address, is not recorded. The integration logs one warning giving the number of such services. This is expected on Amazon EKS and on any platform whose load balancer is fronted by a DNS name.
  • An address shared by two services keeps the namespace and name of the first service read.
  • An address that is also a node address, which happens with k3s's built-in service load balancer or a MetalLB pool overlapping the node subnet, is recorded once: the node's address record also receives the namespace and service name.

Custom Fields

The integration creates the following custom fields. All are created during bootstrap, and all are read-only in the NetBox UI.

Custom FieldObject TypeTypePurpose
nbl_matching_idCluster, device, virtual machineText (unique)Shared matching key across NetBox Labs integrations. The kube-system namespace UID on the cluster, and the node's system UUID on a node
k8s_system_uuidDevice, virtual machineTextThe node's status.nodeInfo.systemUUID. The hardware UUID of the machine running the node, for matching a node to its hypervisor's inventory
k8s_provider_idDevice, virtual machineTextThe node's spec.providerID, the cloud provider's identifier for the node. Empty on most on-premises clusters
k8s_namespaceIP addressTextNamespace of the Kubernetes service reachable at this address
k8s_service_nameIP addressTextName of the Kubernetes service reachable at this address

k8s_system_uuid and k8s_provider_id are recorded for reference. The integration does not link nodes to hypervisor hosts or cloud instances in NetBox.

Tags

Objects created by the integration are tagged:

  • kubernetes and discovered on the objects it creates, except custom fields
  • kubernetes-<CLUSTER_NAME> on the objects specific to the cluster, such as the cluster, its nodes, interfaces, addresses, VRF, and prefixes

Configuration Parameters

Configure these under the config key in the policy definition.

ParameterRequiredDefaultDescription
K8S_API_URLYes*-API server base URL, for example https://10.0.0.1:6443
K8S_TOKENYes*-Service account bearer token (see Authentication and Permissions)
CLUSTER_NAMEYes*-Name of the NetBox cluster, at most 89 characters. Use a different name for each cluster
NODE_OBJECT_TYPEYes-device or virtual_machine (case-insensitive). Required in bootstrap mode too. See NODE_OBJECT_TYPE
SITE_NAMEIn device mode*-Site the node devices are placed in. Not used in virtual_machine mode. See SITE_NAME
K8S_CA_CERTNo-The cluster's CA certificate, as a PEM-encoded certificate or a path to a CA bundle file (see TLS verification)
SKIP_SSLNofalseWhen true, the API server's certificate is not verified
BOOTSTRAPNofalseWhen true, creates static objects only and makes no Kubernetes API calls (see Bootstrap Mode)

* Not required in bootstrap mode, where only NODE_OBJECT_TYPE is required.

scope Parameters

The scope key in the policy definition is optional and limits which nodes are synced. Omit it to sync all nodes.

ParameterDescription
node_labelsA Kubernetes label selector, as a single string. Only nodes matching the selector are synced
scope:
  node_labels: "hardware=baremetal,kubernetes.io/arch=arm64"

The selector uses the same syntax as kubectl get nodes -l, and comma-separated conditions must all match. It is passed to the API server as-is, so an invalid selector fails the run with the API server's own error message.

  • node_labels must be a string, not a YAML list. A list fails the run.
  • A selector that matches no nodes fails the run. The error lists the label keys present on the cluster's nodes. A typo in a label key and a legal but empty value such as hardware== both return no nodes rather than an error from the API server, so the integration treats zero matches as a mistake.
  • Narrowing the selector does not remove anything. Nodes synced under a wider selector stay in NetBox.

Only nodes in scope produce roles, interfaces, addresses, and pod prefixes. The cluster, VRF, service prefixes, and LoadBalancer service addresses are cluster-wide and are not affected by node_labels.

Authentication and Permissions

The integration authenticates to the API server with a service account bearer token, set in K8S_TOKEN. The token needs get and list on four resources:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: nbl-kubernetes
rules:
  - apiGroups: [""]
    resources: ["nodes", "namespaces", "services"]
    verbs: ["get", "list"]
  - apiGroups: ["networking.k8s.io"]
    resources: ["servicecidrs"]
    verbs: ["get", "list"]

A token with only this role cannot read pods or secrets. See Create a service account and token for the full setup.

PermissionIf missing
nodesThe run fails
namespacesThe run fails, because the cluster's identity comes from the kube-system namespace
servicesNo LoadBalancer service addresses are recorded. The run logs a warning and continues
servicecidrsNo service prefixes are recorded. The run logs a warning and continues

TLS verification

TLS verification is enabled by default. An API server's certificate is normally signed by the cluster's own certificate authority, which is not in the agent host's trust store, so verification usually fails unless you provide the cluster's CA certificate in K8S_CA_CERT.

K8S_CA_CERT accepts either the PEM-encoded certificate itself or a path to a CA bundle file readable inside the agent container. A value that is neither fails the run.

Setting SKIP_SSL: true disables verification. The integration logs a warning when it does, and the warning notes when a K8S_CA_CERT was also configured and is therefore unused. Use K8S_CA_CERT in preference to SKIP_SSL.

Proxy

There is no proxy configuration key. The integration reads HTTPS_PROXY, HTTP_PROXY, and NO_PROXY from the agent's environment. When both HTTPS_PROXY and HTTP_PROXY are set, HTTPS_PROXY is used, because the API server is always reached over HTTPS.

Bootstrap Mode

When BOOTSTRAP is set to True, the integration creates the following without connecting to the cluster:

  • Tags: kubernetes, discovered
  • Custom fields: nbl_matching_id, k8s_system_uuid, k8s_provider_id, k8s_namespace, k8s_service_name
  • The Kubernetes cluster type and cluster group
  • In device mode only: the Kubernetes manufacturer and the Kubernetes Node device type

NODE_OBJECT_TYPE is still required, because it decides whether the manufacturer and device type are created. The credentials, CLUSTER_NAME, and SITE_NAME are not read.

Device roles are not created in bootstrap mode, because they depend on the role labels found on the cluster's nodes. Use bootstrap mode on the initial setup only, then set it to False for all subsequent runs.

Sync Behavior

  • Direction: One-way, Kubernetes to NetBox. The integration does not write to the cluster.
  • Object deletion: The integration does not delete NetBox objects. Nodes removed from the cluster, LoadBalancer addresses that are released, and records left behind by a change of NODE_OBJECT_TYPE or node_labels all remain in NetBox. Handle these removals manually.
  • Idempotency: Subsequent runs update existing NetBox objects rather than creating duplicates. The Diode SDK handles conflict resolution.
  • Multiple clusters: Each policy syncs one cluster. Run a separate policy for each cluster, each with its own CLUSTER_NAME.

Known Limitations

  • Workloads are not synced. Pods, deployments, and persistent volumes are not read or modeled in NetBox. Individual pod IP addresses and service ClusterIPs are not recorded.
  • Services are not created as NetBox services. NetBox requires a service to belong to a device, virtual machine, or FHRP group, and a Kubernetes service belongs to the whole cluster. Only LoadBalancer addresses are recorded, with the service's namespace and name in custom fields.
  • Nodes have no primary IP. Node addresses are synced and assigned to the node's interface, but no primary IPv4 or IPv6 address is set. Setting one would let the integration match an unrelated NetBox record that already holds the same address as its primary IP.
  • LoadBalancer services with a hostname endpoint are not recorded. This includes most services on Amazon EKS. The hostname is not resolved, because the addresses behind it change without any change in the cluster.
  • The cluster-wide pod CIDR is not recorded. Kubernetes does not expose it through its API, so only each node's pod CIDR is recorded.
  • Pod and service prefixes always show as fully utilized, because the addresses inside them are not synced.
  • The site named in SITE_NAME receives the integration's tags. In device mode, the site is tagged kubernetes, discovered, and kubernetes-<CLUSTER_NAME>, and the integration does not remove these tags later. Bear this in mind if SITE_NAME names an existing site that holds your own servers.
  • Node address assignment can conflict with a hypervisor integration. If a hypervisor integration also syncs the virtual machines your nodes run on, both integrations assign the same address records to their own interface, and the assignment changes on every run of either integration.
  • Two policies for different clusters must not use the same CLUSTER_NAME. The second policy matches the first policy's cluster record by name, and each run overwrites the other's identity.
  • A cordoned node is shown as active. NetBox has no status for a node that is in service but not accepting new pods.
  • Node object type and site apply to every node in a policy. They cannot be set per node.
  • Vanilla Kubernetes only. OpenShift and other distributions are not supported in this release.

On this page