Open-Source Wikis

/

Kubernetes

/

Primitives

/

Node

kubernetes/kubernetes

Node

A worker machine. Nodes are not provisioned by Kubernetes — the user (or the cloud-controller-manager) creates them. The Node object is the API representation of a machine that the kubelet has registered itself.

Where it lives

Concern Path
Public type staging/src/k8s.io/api/core/v1/types.go (type Node struct {...})
Internal type pkg/apis/core/types.go
Validation pkg/apis/core/validation/validation.go
REST registry pkg/registry/core/node/
Strategy pkg/registry/core/node/strategy.go
Storage (with proxy subresource) pkg/registry/core/node/storage/storage.go
Kubelet-side pkg/kubelet/kubelet_node_status.go
Cloud-side staging/src/k8s.io/cloud-provider/controllers/node/node_controller.go

Lifecycle

stateDiagram-v2
    [*] --> Registering: kubelet POSTs Node
    Registering --> Tainted: cloud taint pending
    Tainted --> Initialized: CCM removes taint
    Initialized --> Ready: kubelet reports Ready
    Ready --> Ready: heartbeat (Lease)
    Ready --> NotReady: heartbeat lapses
    NotReady --> Ready: kubelet recovers
    NotReady --> Tainted: NodeLifecycle taints
    Tainted --> Evicted: TaintEviction evicts pods
    Ready --> Drained: kubectl drain (cordon + evict)

A Node moves from "exists in the API but not Ready" to "Ready" when the kubelet posts its first heartbeat. A heartbeat is two writes:

  1. The Node Lease (in the kube-node-lease namespace) — fast, low-cost, sent every 10 seconds. Implemented in pkg/kubelet/nodelease/.
  2. The Node Status (Conditions, Capacity, Allocatable) — heavier, sent on a longer cadence and on change.

The split is what lets clusters scale: thousands of nodes can renew Leases without thrashing the Node objects.

Conditions

Condition Set by Meaning
Ready kubelet Kubelet's overall health
MemoryPressure kubelet Node memory under pressure
DiskPressure kubelet Node disk under pressure
PIDPressure kubelet Node PID exhaustion
NetworkUnavailable NodeIPAM / cloud-controller Pod network not yet routable

The node-lifecycle controller in pkg/controller/nodelifecycle/ watches these. If Ready flips to False for longer than --node-monitor-grace-period, the controller adds the node.kubernetes.io/not-ready:NoExecute taint. Pods that don't tolerate this taint are evicted.

Capacity vs Allocatable

status.capacity is the raw machine: total CPU cores, total memory, total ephemeral storage, total devices. status.allocatable is capacity minus the kubelet's reservations:

  • --system-reserved
  • --kube-reserved
  • The eviction threshold

The scheduler uses allocatable. The kubelet uses allocatable for admission. The numbers are computed once at startup (and refreshed when the kubelet config changes).

Taints and tolerations

spec.taints is [{key, value, effect}]. Effects:

  • NoSchedule — new Pods can't be scheduled here unless they tolerate the taint.
  • PreferNoSchedule — soft version of the above.
  • NoExecute — existing Pods are evicted (after tolerationSeconds) unless they tolerate.

The scheduler enforces NoSchedule/PreferNoSchedule via the tainttoleration plugin. The taint-eviction controller in pkg/controller/tainteviction/ enforces NoExecute.

Well-known taints set by the system:

  • node.kubernetes.io/not-ready
  • node.kubernetes.io/unreachable
  • node.kubernetes.io/disk-pressure
  • node.kubernetes.io/memory-pressure
  • node.kubernetes.io/pid-pressure
  • node.kubernetes.io/network-unavailable
  • node.kubernetes.io/unschedulable (from kubectl cordon)
  • node.cloudprovider.kubernetes.io/uninitialized (CCM)

Node-side controllers

In addition to kubelet, several components write Node status:

  • NodeIPAM controller allocates spec.podCIDRs.
  • Cloud-Node controller sets labels (topology.kubernetes.io/zone, topology.kubernetes.io/region, node.kubernetes.io/instance-type) and spec.providerID.
  • NodeLifecycle controller sets taints when health degrades.
  • AttachDetach controller reads Node to decide where to attach volumes.
  • Scheduler reads Node to decide where Pods fit.

Heartbeat scaling

The two-channel heartbeat (Lease for liveness, Status for snapshot) is the headline scalability feature for Node. Pre-Lease, a 5,000-node cluster generated 5,000 Node Status writes every few seconds. With Leases, only ~5,000 tiny Lease updates flow through; Node Status is updated only on real change.

Subresources

  • /status — kubelet's status writes
  • /proxy — generic kubelet proxy (used for kubectl logs, kubectl exec, kubelet /metrics, etc.)

Validation highlights

  • metadata.name is a DNS-1123 subdomain.
  • spec.podCIDRs are valid CIDRs and consistent with spec.podCIDR (single-stack vs dual-stack).
  • spec.taints[].effect is one of the allowed strings.
  • spec.providerID matches the cloud-provider's regex.

Key source files

File Purpose
staging/src/k8s.io/api/core/v1/types.go Public Node type
pkg/registry/core/node/strategy.go Node REST strategy
pkg/kubelet/kubelet_node_status.go Kubelet's Node creation + heartbeat
pkg/kubelet/nodestatus/setters.go Per-condition setters
pkg/controller/nodelifecycle/node_lifecycle_controller.go Node monitor + taints
pkg/controller/tainteviction/ NoExecute taint enforcement
pkg/controller/nodeipam/ Pod-CIDR allocation
staging/src/k8s.io/cloud-provider/controllers/node/node_controller.go Cloud-side initialization

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Node – Kubernetes wiki | Factory