KubernetesXXVIII · Node ArchitectureNode architecture
Node addresses and topology — labels the cluster reads
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
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:
| Label | Source | Used by |
|---|---|---|
kubernetes.io/hostname | kubelet (from the node’s hostname) | Pod-to-node identity, daemonset scheduling |
kubernetes.io/os | kubelet (from /etc/os-release) | OS-aware scheduling |
kubernetes.io/arch | kubelet (from uname -m) | Architecture-aware scheduling |
node.kubernetes.io/instance-type | Cloud provider | Instance-class affinity |
topology.kubernetes.io/zone | Cloud provider | Zone-aware scheduling |
topology.kubernetes.io/region | Cloud provider | Region-aware scheduling |
node.kubernetes.io/role or node-role.kubernetes.io/<role> | Operator | Role-based scheduling |
beta.kubernetes.io/instance-type (deprecated) | Cloud provider | Legacy affinity (replaced by node.kubernetes.io/instance-type) |
failure-domain.beta.kubernetes.io/zone (deprecated) | Cloud provider | Legacy 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:
| Type | Set by | Used by |
|---|---|---|
InternalIP | kubelet (from the primary interface) | Service routes, kubelet connection |
ExternalIP | Cloud provider | External traffic |
Hostname | kubelet | Identity, daemonset scheduling |
InternalDNS | kubelet (if configured) | Cluster-internal DNS |
ExternalDNS | Cloud provider | Public 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
Q1. Which label does the scheduler read to spread Pods across failure domains?
Q2. On a bare-metal cluster, zone labels must be applied by the operator or they will not exist.
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`.
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.