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:
- The Node
Lease(in thekube-node-leasenamespace) — fast, low-cost, sent every 10 seconds. Implemented inpkg/kubelet/nodelease/. - 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 (aftertolerationSeconds) 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-readynode.kubernetes.io/unreachablenode.kubernetes.io/disk-pressurenode.kubernetes.io/memory-pressurenode.kubernetes.io/pid-pressurenode.kubernetes.io/network-unavailablenode.kubernetes.io/unschedulable(fromkubectl 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) andspec.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 forkubectl logs,kubectl exec, kubelet/metrics, etc.)
Validation highlights
metadata.nameis a DNS-1123 subdomain.spec.podCIDRsare valid CIDRs and consistent withspec.podCIDR(single-stack vs dual-stack).spec.taints[].effectis one of the allowed strings.spec.providerIDmatches 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.