Skip to main content
RunBook Academy

KubernetesXXVIII · Node ArchitectureNode architecture

Node addresses and topology — labels the cluster reads

Advanced⏱ ~17 minkubectl

What you'll learn

  • Identify the standard labels and addresses the cluster uses
  • Trace how the kubelet and cloud provider populate them
  • Apply the operational patterns for managing the label inventory
  • Diagnose affinity failures caused by missing or wrong labels

Prerequisites

Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16

Not yet marked complete on this device.

The cluster’s topology reasoning depends on a small set of standard labels and addresses. The labels are set by the kubelet (from the local environment) and by the cloud provider (from the cloud’s metadata service). The operator’s affinity rules and topology spread constraints rely on these labels being correct. This lesson walks the labels, the sources, and the operational patterns.

The standard labels

flowchart LR
    A[kubelet] -->|hostname| B[Node labels]
    A -->|os, arch| B
    C[Cloud provider] -->|instance-type| B
    C -->|zone, region| B
    D[Operator] -->|role| B
    B --> E[Scheduler reads]
    B --> F[Affinity rules]
    B --> G[Topology spread]

The well-known labels that the cluster’s components read:

The well-known labels that the cluster’s components read:

LabelSourceUsed by
kubernetes.io/hostnamekubelet (from the node’s hostname)Pod-to-node identity, daemonset scheduling
kubernetes.io/oskubelet (from /etc/os-release)OS-aware scheduling
kubernetes.io/archkubelet (from uname -m)Architecture-aware scheduling
node.kubernetes.io/instance-typeCloud providerInstance-class affinity
topology.kubernetes.io/zoneCloud providerZone-aware scheduling
topology.kubernetes.io/regionCloud providerRegion-aware scheduling
node.kubernetes.io/role or node-role.kubernetes.io/<role>OperatorRole-based scheduling
beta.kubernetes.io/instance-type (deprecated)Cloud providerLegacy affinity (replaced by node.kubernetes.io/instance-type)
failure-domain.beta.kubernetes.io/zone (deprecated)Cloud providerLegacy zone affinity (replaced by topology.kubernetes.io/zone)

The kubernetes.io/hostname, kubernetes.io/os, and kubernetes.io/arch are set by the kubelet. The node.kubernetes.io/instance-type, topology.kubernetes.io/zone, and topology.kubernetes.io/region are set by the cloud provider’s node lifecycle controller. The node-role.kubernetes.io/<role> is set by the operator.

The addresses

The standard addresses:

TypeSet byUsed by
InternalIPkubelet (from the primary interface)Service routes, kubelet connection
ExternalIPCloud providerExternal traffic
HostnamekubeletIdentity, daemonset scheduling
InternalDNSkubelet (if configured)Cluster-internal DNS
ExternalDNSCloud providerPublic DNS

The InternalIP and Hostname are always set by the kubelet. The ExternalIP and ExternalDNS are set by the cloud provider. The InternalDNS is set by the kubelet if the cluster’s DNS is configured to resolve the node’s name.

# Substitute your own value before running:
NODE=worker-01

kubectl get node "$NODE" -o jsonpath='{.status.addresses}' | jq
[
  { "type": "InternalIP", "address": "10.0.5.21" },
  { "type": "ExternalIP", "address": "54.10.20.30" },
  { "type": "Hostname", "address": "node-1" }
]

The cluster’s CNI uses the InternalIP to route Pod traffic. The --node-ip flag on the kubelet overrides the InternalIP; this is useful when the node has multiple interfaces and the cluster should route through a specific one.

The NodeFeatureDiscovery (NFD) labels

A cluster that uses the NodeFeatureDiscovery (NFD) add-on has additional labels for hardware features:

  • feature.node.kubernetes.io/cpu-<flag>: "true" — CPU flags (e.g., avx2, sse4_2).
  • feature.node.kubernetes.io/kernel-<module>: "true" — kernel modules loaded.
  • feature.node.kubernetes.io/pci-<vendor>_<device>: "true" — PCI devices present.

The NFD labels are the operator’s primary means of identifying nodes with specific hardware. A Pod that requires AVX-512 can use an affinity on the NFD label.

affinity:
  nodeAffinity:
    requiredDuringSchedulingIgnoredDuringExecution:
      nodeSelectorTerms:
        - matchExpressions:
            - key: feature.node.kubernetes.io/cpu-avx512
              operator: In
              values: ["true"]

The NFD labels are set by the NFD worker, a DaemonSet that runs on every node and reports the hardware features via labels.

The role labels

The node-role.kubernetes.io/<role> labels are the operator’s primary means of identifying a node’s role. The convention is to use a string value (typically empty or true) for the role label:

# Substitute your own value before running:
NODE=worker-01

kubectl label nodes "$NODE" node-role.kubernetes.io/worker=
kubectl label nodes "$NODE" node-role.kubernetes.io/infra=true

The empty value is the convention; the operator can use true or "" interchangeably. The cluster’s components read the label by key, not by value.

A Pod that targets a role:

nodeSelector:
  node-role.kubernetes.io/infra: ""

The selector matches any node with the label, regardless of value.

The label inventory audit

The production rule: every node must have the standard labels and addresses that the cluster’s components rely on. A node that joins the cluster without the labels is a node that the cluster cannot reason about.

kubectl get nodes -o custom-columns=NAME:.metadata.name,HOSTNAME:.metadata.labels.kubernetes\.io/hostname,INSTANCE:.metadata.labels.node\.kubernetes\.io/instance-type,ZONE:.metadata.labels.topology\.kubernetes\.io/zone,OS:.metadata.labels.kubernetes\.io/os,ARCH:.metadata.labels.kubernetes\.io/arch

The expected output:

NAME      HOSTNAME   INSTANCE   ZONE        OS      ARCH
node-1    node-1     m5.large   us-east-1a  linux   amd64
node-2    node-2     m5.large   us-east-1b  linux   amd64
node-3    node-3     m5.xlarge  us-east-1c  linux   amd64

A node that is missing a label is a node that is failing the bootstrap. The fix is to investigate the bootstrap automation: the cloud provider’s metadata service, the NFD worker, or the kubelet’s configuration.

The addresses audit

The production rule: every node must have an InternalIP and a Hostname. The ExternalIP is optional (clusters that do not expose nodes externally do not need it).

kubectl get nodes -o custom-columns=NAME:.metadata.name,INTERNAL_IP:.status.addresses[?(@.type=="InternalIP")].address,EXTERNAL_IP:.status.addresses[?(@.type=="ExternalIP")].address,HOSTNAME:.status.addresses[?(@.type=="Hostname")].address

The expected output:

NAME      INTERNAL_IP   EXTERNAL_IP   HOSTNAME
node-1    10.0.5.21     54.10.20.30   node-1
node-2    10.0.5.22     54.10.20.31   node-2
node-3    10.0.5.23     54.10.20.32   node-3

A node that is missing an address is a node that the cluster cannot route to. The fix is to investigate the kubelet’s network configuration.

The CRI socket label

The kubernetes.io/cri-provider label (in newer versions) is set by the kubelet to advertise the container runtime:

# Substitute your own value before running:
NODE=worker-01

kubectl get node "$NODE" -o jsonpath='{.metadata.labels.kubernetes\.io/cri-provider}'

A cluster that uses containerd has kubernetes.io/cri-provider: containerd. The label is used by tools that need to know the runtime to interact with the node.

The OS and architecture labels

The kubernetes.io/os and kubernetes.io/arch labels are set by the kubelet from the node’s environment. The values:

  • linux, windows.
  • amd64, arm64, ppc64le, s390x.

A cluster that mixes architectures (a hybrid cluster with arm64 and amd64 nodes) must label the nodes correctly. A Pod that requires amd64 cannot run on an arm64 node.

nodeSelector:
  kubernetes.io/arch: amd64

The selector matches only amd64 nodes. The cluster’s general workloads without a selector can run on any arch.

The topology spread labels

The topology.kubernetes.io/zone and kubernetes.io/hostname labels are the keys for topology spread constraints. A Pod that requires zone-spread replicas uses topologyKey: topology.kubernetes.io/zone; a Pod that requires node-spread uses topologyKey: kubernetes.io/hostname.

The labels must be set on every node. A node that is missing the labels is a node that the topology spread constraint cannot consider. The Pod is rejected from the node because the topology key is missing.

The production patterns

Audit the labels at every node replacement

A new node that joins the cluster should have the same labels as the one it replaced. The audit checks every node’s labels against the cluster’s inventory.

Use the cloud provider’s labels for affinity

The cluster’s scheduler reads the standard labels for topology decisions. A custom label scheme (e.g., my-cluster/zone) is a maintenance burden. Use the standard labels.

Set the role labels deliberately

A node with node-role.kubernetes.io/worker="" is a worker. A node with node-role.kubernetes.io/infra=true is an infra node. The role labels should be set by the cluster’s bootstrap automation, not by the operator.

Document the custom labels

A cluster that adds custom labels (e.g., GPU presence, hardware generations) should document the labels and the workloads that use them. The audit at every release checks for changes.

Quiz

Knowledge check · 4 questions

  1. Q1. Which label does the scheduler read to spread Pods across failure domains?

  2. Q2. On a bare-metal cluster, zone labels must be applied by the operator or they will not exist.

  3. Q3. Restore zone-aware scheduling after a new node pool joins without its topology labels.

    A new pool added `node-10` and `node-11` last night. `kubectl get nodes -L topology.kubernetes.io/zone` shows an empty column for both, while the nine older nodes show eu-west-1a, 1b and 1c. Since then every workload with a `whenUnsatisfiable: DoNotSchedule` zone spread constraint refuses to use the two new nodes, and both still carry `node.cloudprovider.kubernetes.io/uninitialized:NoSchedule`.

  4. Q4. Which node labels does the kubelet set itself, which come from the cloud controller manager, and what stops a kubelet from setting an arbitrary label on its own Node?

Passing score: 75%. Answers are checked in this browser.

Production discipline

  • Standard labels are the cluster’s vocabulary. The cluster’s topology reasoning depends on the standard labels. A cluster that uses custom labels is a cluster that has to maintain the labels.
  • The cloud provider’s labels are the source of truth. The cluster’s components read the cloud provider’s labels. If the cloud provider’s labels are wrong, the cluster’s topology is wrong.
  • Audit the labels at every node replacement. A new node that joins the cluster should have the same labels as the one it replaced. The audit catches a missing label before it causes a scheduling failure.
  • The OS and architecture labels must be set. A cluster that mixes architectures must label the nodes correctly. The cluster’s general workloads can run on any arch; the workloads that require a specific arch must use the selector.
  • The NFD labels are a maintenance burden. NFD is a powerful tool, but the labels become part of the cluster’s vocabulary. Document them; audit them.