Skip to main content
RunBook Academy

KubernetesXXIX · kubeletNode architecture

Pod lifecycle from the kubelet's view — admit, sync, run, terminate

Advanced⏱ ~18 minkubectl

What you'll learn

  • Trace the kubelet's state machine for a Pod
  • Identify the failures at each step and the diagnostic
  • Distinguish the kubelet's lifecycle from the API server's lifecycle
  • Apply the operational patterns for stuck Pods

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 kubelet runs a per-Pod state machine. The state machine handles admission, container creation, network setup, volume mounting, probe execution, and termination. Each step has a failure mode; each failure mode has a diagnostic. This lesson walks the state machine and the operational patterns for stuck Pods.

The kubelet’s per-Pod state machine

The kubelet’s podWorker runs a per-Pod goroutine. The goroutine’s state machine:

stateDiagram-v2
    [*] --> Sync: Pod added to sync loop
    Sync --> Admit: kubelet admits Pod
    Admit --> CreateSandbox: CRI RunPodSandbox
    CreateSandbox --> SetupNetwork: CNI ADD
    SetupNetwork --> MountVolumes: CSI mount
    MountVolumes --> CreateContainers: CRI CreateContainer
    CreateContainers --> StartContainers: CRI StartContainer
    StartContainers --> Running: postStart hook
    Running --> Running: probes pass
    Running --> Terminating: API server delete
    Terminating --> PreStop: preStop hook
    PreStop --> StopContainers: SIGTERM
    StopContainers --> RemoveContainers: SIGKILL after grace
    RemoveContainers --> CleanupNetwork: CNI DEL
    CleanupNetwork --> CleanupVolumes: CSI unmount
    CleanupVolumes --> [*]

The state machine is the kubelet’s view of the Pod. The API server’s view is the Pod’s Status.Phase; the two are correlated but not identical.

The admit step

The kubelet’s admission step is the first decision. The kubelet checks:

  • The Pod’s resource requests against the node’s available capacity.
  • The Pod’s tolerations against the node’s taints.
  • The Pod’s node selector against the node’s labels.
  • The Pod’s affinity rules against the cluster’s state.
  • The Pod’s owner references and lifecycle.

The admission step is where the kubelet decides whether the Pod can run on the node. The decision is recorded in the Pod’s status.

The admission failure modes:

FailureDiagnostic
Insufficient resourceskubectl describe pod shows FailedScheduling
Taint not toleratedkubectl describe pod shows taint {key=value:NoSchedule}
Node selector mismatchkubectl describe pod shows didn't match Pod's node selector
Affinity unsatisfiablekubectl describe pod shows didn't match Pod's [...] affinity
Already admittedThe Pod is already on the node; kubelet logs pod already exists

The kubelet’s admission is the cluster’s filter plugin. The Pod is admitted once; the kubelet does not re-admit on every sync cycle.

The create-sandbox step

The kubelet calls the CRI to create the Pod’s sandbox. The sandbox is the network namespace, the cgroup, and the filesystem mount. The runtime creates these and returns the sandbox ID.

The failure modes:

FailureDiagnostic
Runtime downkubelet logs dial unix /run/containerd/containerd.sock: connect: connection refused
Image pull failedkubelet logs ErrImagePull, Pod events show Failed
Network namespace creation failedkubelet logs failed to create network namespace
Cgroup creation failedkubelet logs failed to create cgroup

A Pod stuck in ContainerCreating is most likely stuck in the create-sandbox step. The kubectl describe pod shows the kubelet’s error.

The setup-network step

The kubelet calls the CNI plugin to configure the Pod’s network. The CNI adds the veth pair, the IP address, and the routes.

The failure modes:

FailureDiagnostic
CNI plugin missingkubelet logs failed to find plugin "calico" in path [/opt/cni/bin]
CNI config invalidkubelet logs error parsing CNI config
IPAM exhaustedkubelet logs IPAM: no available addresses
Network namespace not readykubelet logs network namespace not ready

A Pod stuck in ContainerCreating with a network-related event is stuck in the setup-network step. The fix is to investigate the CNI plugin.

The mount-volumes step

The kubelet calls the CSI driver to mount the Pod’s volumes. The CSI driver attaches the volume to the node and mounts the filesystem.

The failure modes:

FailureDiagnostic
Volume not boundPod’s PVC is not yet bound; Pod waits for binding
CSI driver downkubelet logs csi: driver not ready
Mount failedkubelet logs mount failed: exit status 32
Permissions deniedkubelet logs permission denied

A Pod stuck in ContainerCreating with a volume-related event is stuck in the mount-volumes step.

The create-containers step

The kubelet calls the CRI to create the Pod’s containers. The runtime pulls the image, sets up the container’s filesystem, and creates the container.

The failure modes:

FailureDiagnostic
Image pull failedkubelet logs ErrImagePull or ImagePullBackOff
Insufficient CPUkubelet logs cannot allocate memory
Mount conflictskubelet logs mount conflict
ConfigMap / Secret not foundkubelet logs configmap not found

A Pod stuck in ContainerCreating with a container creation-related event is stuck in the create-containers step.

The start-containers step

The kubelet calls the CRI to start the containers. The runtime starts the container’s process; the process performs its initial work.

The failure modes:

FailureDiagnostic
Container crashedkubelet logs container exited with status
PostStart hook failedkubelet logs PostStart hook failed
Startup probe failedkubelet waits for the startup probe to succeed

A Pod that restarts repeatedly is in the start-containers step. The kubectl describe pod shows the container’s exit status and the reason.

The running state

The Pod is running. The kubelet runs the probes and updates the status.

The failure modes:

FailureDiagnostic
Liveness probe failedkubelet restarts the container; events show Liveness probe failed
Readiness probe failedkubelet removes the Pod from the EndpointSlice; events show Readiness probe failed
Out of memorykubelet kills the container; events show OOMKilled
Out of diskkubelet evicts the Pod; events show DiskPressure

A Pod that is running but not serving traffic is in the running state with a failed readiness probe. The fix is to investigate the application.

The terminating state

The kubelet receives the API server’s delete request. The Pod’s containers are terminated gracefully.

sequenceDiagram
    autonumber
    participant API as API server
    participant K as kubelet
    participant C as Container
    participant CNI as CNI

    API->>K: delete Pod
    K->>C: preStop hook
    K->>C: SIGTERM
    C->>C: ... shutdown
    K->>C: SIGKILL (after grace period)
    K->>CNI: DEL
    K->>API: status update: Succeeded or Failed

The kubelet’s termination grace is the Pod’s terminationGracePeriodSeconds (default 30s). The kubelet sends SIGTERM, waits for the grace period, then sends SIGKILL.

The failure modes:

FailureDiagnostic
Container ignores SIGTERMkubelet waits for the grace period, then SIGKILL
Container has long shutdownkubelet waits; the Pod is stuck in Terminating
Cleanup failedkubelet logs failed to clean up

A Pod stuck in Terminating is a Pod whose cleanup is failing. The fix is to investigate the log path, the volume unmount, or the network namespace cleanup.

The “could not be evicted” state

A Pod that is being terminated but cannot be evicted is in a special state. The kubelet cannot remove the Pod’s sandbox because:

  • Another process is using the network namespace.
  • The volume unmount is hanging.
  • The cgroup is busy.

The kubelet logs the error and retries. The fix is to investigate the kubelet’s logs.

The mirror Pod

The kubelet creates a mirror Pod for each static Pod. The mirror Pod is in the API server; the static Pod is on the node. The mirror Pod is read-only.

The kubelet syncs the mirror Pod’s status with the static Pod’s status. The operator can see the static Pod’s status via kubectl get pod -n kube-system | grep <name>.

Quiz

Knowledge check · 4 questions

  1. Q1. In the kubelet's Pod startup sequence, what happens before any container image is pulled?

  2. Q2. A Pod stuck in `ContainerCreating` with no image-pull errors points at sandbox or volume setup rather than the registry.

  3. Q3. Clear a StatefulSet Pod that has been Terminating for 45 minutes without risking its volume.

    `postgres-0` on `node-5` has been Terminating for 45 minutes after a routine rollout; its `metadata.deletionTimestamp` is 45 minutes old and its containers have already exited. The kubelet logs repeat `UnmountVolume.TearDown failed for volume "data" ... device or resource busy`, and the StatefulSet will not create the replacement until the old Pod object is gone.

  4. Q4. A Pod sits in ContainerCreating. Name the three kubelet steps that can hold it there and one distinguishing log line for each.

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

Production discipline

  • A Pod stuck in ContainerCreating is the kubelet’s state machine. The kubectl describe pod shows the kubelet’s error. The fix is to read the error.
  • A Pod stuck in Terminating is the kubelet’s cleanup. The kubelet’s logs show the cleanup error. The fix is to investigate the log path, the volume unmount, or the network namespace.
  • The kubelet’s state machine is the cluster’s ground truth. The Pod’s Status.Phase is the cluster’s view; the kubelet’s state machine is the node’s view. The two can diverge during a long- running cleanup.
  • Audit the kubelet’s logs at every release. A kubelet that is silently failing is a node that is silently failing. The audit catches the silence.
  • Static Pods are the cluster’s fallback. The cluster’s critical add-ons should be static Pods or DaemonSets that the kubelet can start.