Why Your Pod Restores Are Failing With 'Memory Mismatch' In Production
Why did our newly restored K8s pod crash instantly upon resuming an AI workload using the 1.37 checkpoint feature? When a spot node died, Kubernetes 1.
We thought we outsmarted cloud compute costs by moving our massive model training jobs to preemptible GPU instances. When a spot node died, Kubernetes 1.37 successfully dumped the memory state, but the restored pod instantly crashed with a fatal memory alignment error. Instead of resuming execution, our workloads entered a continuous failure loop that burned hours of troubleshooting time.
TL;DR: Kubernetes 1.37 checkpoint/restore features do not abstract away underlying hardware topologies like NUMA or CPU page sizes. Restoring a container on a node with mismatched memory architecture triggers immediate
SIGSEGVor fatal memory mismatches. This post details how to diagnose restore failures and enforce exact hardware topologies using strict node affinities.
What you’ll walk away with:
- Identify the exact hardware discrepancies causing container restore panics.
- Write strict NodeAffinity rules that pin restored workloads to compatible NUMA topologies.
- Validate memory page size configurations across heterogeneous node pools.
- Configure Kubelet topology managers to prevent scheduling checkpointed workloads on incompatible hardware.
Checkpoint/Restore In Userspace (CRIU) is a Linux utility integrated into the kubelet that freezes a running container and serializes its exact memory state to disk for later resumption. We heavily relied on this feature for our Aicademy training clusters, expecting workloads to jump from dying nodes to new ones effortlessly. The reality involved far more hardware constraints.
Why Do Kubernetes Pod Restores Fail With Memory Mismatch Errors?
Kubernetes pod restores fail with memory mismatch errors because the target node has a different NUMA architecture, CPU instruction set, or hugepage size than the origin node. The checkpointed process expects exact memory addresses and page alignments upon waking up. A hardware discrepancy immediately invalidates the restored memory segments.
Our incident started subtly. The Aicademy scheduling system preempted an AWS g5.4xlarge node, and the Kubernetes 1.37 CRIU integration correctly wrote the pod’s checkpoint archive to our shared persistent volume. We watched the scheduler spin up a replacement pod on a g4dn.4xlarge node. The pod status flipped to Running, then immediately crashed.
View the full CRIU CrashLoopBackOff stack trace
1
2
3
4
5
6
7
Error: failed to restore container
criu failed: type NOTIFY errno 0
log file:
(00.123456) Restoring namespaces (pid: 123)
(00.123567) Memory Mismatch: Page size 2097152 expected, got 4096
(00.123789) Fatal: Can't map memory at 0x7f8b9c000000
(00.123801) PieRestore routine failed
The error explicitly called out a page size expectation of 2MB (hugepages), which the new node did not have configured. The container runtime attempted to map the serialized memory into RAM, found the memory architecture incompatible, and threw a fatal exception. The scheduler retried relentlessly, causing a massive CrashLoopBackOff cycle.
This behavior perfectly illustrates Why Your Kubernetes AI Workloads Lose 48 Hours of Progress on Node Failure when infrastructure configurations drift.
Always check the origin and target node’s CPU architectures and hugepage configurations when debugging CRIU restore faults.
How Do You Diagnose Checkpoint Hardware Topology Mismatches?
You diagnose checkpoint hardware topology mismatches by comparing the lscpu NUMA node configurations and the kubelet topology manager policies between the origin and destination nodes. Identifying differences in allocated hugepages or PCIe bus mappings reveals exactly why the container runtime rejected the serialized memory state.
We needed to prove the discrepancy across our node pools. By default, the Kubelet topology manager policy is set to none, meaning Kubernetes 1.37 makes no attempt to align resource allocations with NUMA nodes. We ran a quick JSONPath query against our cluster to inspect the hugepage capacities across our active nodes.
1
kubectl get nodes -l gpu-workload=true -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.allocatable.hugepages-2Mi}{"\n"}{end}'
1
2
ip-10-0-1-50.ec2.internal 2048Mi
ip-10-0-1-51.ec2.internal 0
The output confirmed our suspicion. The original g5.4xlarge (ip-10-0-1-50) had 2MB hugepages allocated, while the fallback node (ip-10-0-1-51) had none. When CRIU attempted to restore the process, it demanded a memory layout the target host could not physically provide.
flowchart TD
A["Origin Node (g5)"] -->|"Writes Checkpoint"| B["Persistent Storage"]
B -->|"Reads Checkpoint"| C["Target Node (g4dn)"]
C --> D{"Memory Arch Matches?"}
D -->|"No (Page Size Mismatch)"| E["Fatal CRIU Error"]
D -->|"Yes"| F["Process Resumes"]
To prevent this in production environments, teams must audit their node pools systematically before relying on checkpoint/restore mechanics.
-
Verify Kubelet
topologyManagerPolicyis identical across all nodes expected to share checkpoints. - Ensure all origin and target nodes use the exact same CPU instruction sets (e.g., AVX-512).
-
Confirm hugepage capacities (
hugepages-2Mi,hugepages-1Gi) match identically on target nodes. -
Validate that persistent volumes hosting checkpoints support
ReadWriteManyif restoring across zones.
Rely on
kubectl get node -o jsonpathto quickly compare hugepage capacities across your target node pools before enabling checkpoints.
What Is The Best Way To Enforce Node Affinity For Restored Pods?
The best way to enforce node affinity for restored pods is by configuring strict requiredDuringSchedulingIgnoredDuringExecution rules targeting specific instance family labels. This guarantees the Kubernetes scheduler only places the resumed container on a node with identical CPU and memory architectures.
We could not rely on Kubernetes simply finding another GPU node; it had to find the exact same model of GPU node. We updated our Aicademy model training manifests to restrict pod placement entirely. Using node affinity constraints, we pinned the workload to the specific instance type.
1
2
3
4
5
6
7
8
9
10
11
12
@@ -14,2 +14,9 @@
containers:
- name: ai-trainer
+ affinity:
+ nodeAffinity:
+ requiredDuringSchedulingIgnoredDuringExecution:
+ nodeSelectorTerms:
+ - matchExpressions:
+ - key: node.kubernetes.io/instance-type
+ operator: In
+ values:
+ - g5.4xlarge
Applying this configuration completely eliminated the memory mismatch panics. If a g5.4xlarge was unavailable, the pod remained Pending instead of entering a destructive crash loop. This is a far safer failure mode than corrupting a checkpoint with a failed partial restore.
When you enforce strict constraints, you must also ensure your cluster definitions are structurally sound. We previously detailed how bad manifest parsing can break constraints in The Kubernetes YAML Parser Bug That Silently Drops Your Network Policies. A single typo in the affinity block will leave your pod unschedulable.
Pin stateful checkpointed workloads to exact instance family labels, not just general GPU capacity or vendor labels.
How Do Node Topologies Compare For Checkpoint Resumption?
Node topologies compare for checkpoint resumption based on their CPU architectures, NUMA alignment, and hugepage availability. Symmetrical architectures resume cleanly, while asymmetric deployments require strict Kubelet topology manager configurations to avoid segmentation faults during process reanimation.
If you are currently evaluating how to structure your clusters for Kubernetes 1.37, you must choose a topology strategy that supports your restore goals. Mixing node types requires careful labeling and affinity logic.
| Topology Strategy | Hugepage Consistency | Scheduling Flexibility | Best For |
|---|---|---|---|
| Symmetrical Pools | Identical across all nodes | Very High | Winner: Production AI workloads requiring reliable CRIU resumes. |
| Asymmetrical Pools | Varies by instance family | Medium | Cost-optimized clusters using strict nodeAffinity constraints. |
| Heterogeneous (Mixed) | Inconsistent and unmanaged | Low | Stateless microservices, not recommended for checkpoint features. |
Moving from a heterogeneous layout to symmetrical node pools requires careful planning. You can follow the architectural principles outlined in 4 Steps to Safely Migrate Your Cluster to Kubernetes 1.37 KYAML to standardize your infrastructure definitions.
Set your Kubelet topology manager policy to
single-numa-nodefor latency-sensitive restored workloads.
Bottom Line
Kubernetes 1.37 checkpoint and restore capabilities provide massive cost savings for interruptible workloads, but they demand absolute hardware symmetry. Attempting to restore a container across mismatched memory configurations will result in immediate, unrecoverable crashes. Enforce strict nodeAffinity configurations to guarantee your origin and target nodes share the exact same hardware profile.
In the next part of this series, we cover how to debug container storage interface (CSI) timeouts during massive checkpoint disk writes.
FAQ
What happens if the target node lacks the expected hugepage capacity?
The container runtime will fail to map the serialized memory state into RAM. The pod will transition into a CrashLoopBackOff state immediately after initialization.
Can I restore a Kubernetes 1.37 checkpoint from an Intel node onto an AMD node?
No. Differences in CPU instruction sets and microarchitectures will cause CRIU to panic during the namespace restoration phase. You must target identical CPU architectures.
How do I verify my kubelet topology manager policy?
Run cat /var/lib/kubelet/config.yaml | grep topologyManagerPolicy on the target node. The Kubernetes 1.37 default is none.
Does node affinity prevent preemptions on spot instances?
No. Node affinity only controls where the pod schedules after it is preempted. The cloud provider will still terminate your spot instance regardless of Kubernetes scheduling constraints.
Why does my pod stay Pending instead of restoring?
If you applied strict requiredDuringSchedulingIgnoredDuringExecution affinity rules, the scheduler will leave the pod Pending until a node matching the exact hardware constraints becomes available in the cluster.
Part of the series: k8s-1-37-ai-kyaml-series
- Why Your Kubernetes AI Workloads Lose 48 Hours of Progress on Node Failure
- Cut Your GPU Spot Instance Costs by 40% With Pod-Level Checkpointing
- The Kubernetes YAML Parser Bug That Silently Drops Your Network Policies
- 4 Steps to Safely Migrate Your Cluster to Kubernetes 1.37 KYAML
- Why Your Pod Restores Are Failing With 'Memory Mismatch' In Production (you are here)
Further Reading
- https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
- https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/
- https://github.com/kubernetes/kubernetes
🚀 Ready to get hands-on? Spin up an interactive AI or Kubernetes Sandbox at Aicademy Labs for free.
