OOM-Killed Enterprise Workflow: Incident Anatomy
Follow the enterprise AI workflow platform's failed request from physical RAM to Kubernetes evidence, then prove the smallest safe recovery.
The enterprise problem and today’s slice
Enterprise problem: the enterprise AI workflow platform's workflow-platform disappears during a traffic spike because its container is killed for exceeding a memory boundary, and a blind restart or larger node can hide the cause while readers keep seeing errors. Whole-course context: The incoming evidence is the physical-to-pod memory model: requests reserve scheduler capacity, limits become Linux control-group ceilings, and neither creates RAM. Today’s slice: We trace one failed HTTP request through the application, container, pod, node, and Linux kernel, then separate immediate restoration from a justified resource change. End-of-day evidence: An incident record links the OOMKilled termination, limit, node condition, traffic replay, rollout revision, and unaffected control request. Still unsolved: Fleet autoscaling, cloud-provider capacity, and GitOps-controlled promotion are deferred to later days.
The thesis is simple: OOMKilled is evidence of a boundary crossing, not a diagnosis of why memory grew. The useful response follows observe → locate the enforcing boundary → change one thing → replay → compare.
Customer use cases
An outage becomes longer when responders cannot distinguish a container limit breach from whole-node exhaustion. These use cases make customer restoration and safe diagnosis independently observable.
| Use case ID | Actor | Customer job | Success outcome | Denial or recovery evidence |
|---|---|---|---|---|
| D58-UC-01 | Platform operator | Restore the enterprise AI workflow platform for readers without discarding the original failure evidence | Healthy replicas serve the traffic replay and no replacement is OOM-killed | Rollout is stopped if node headroom is absent; the old termination and a healthy control request remain recorded |
| D58-UC-02 | Incident reviewer | Prove whether a leak, legitimate peak, or node pressure caused the failure | Timeline correlates request volume, process memory, cgroup ceiling, and node condition | Unsupported root-cause claims are rejected; missing measurements are named as gaps |
Actor-centred user stories
Recovery without falsifiable acceptance conditions can merely move the outage to another node. Each story therefore requires both positive customer evidence and a negative or unaffected control.
| Story ID | Use case IDs | User story | Observable acceptance conditions |
|---|---|---|---|
| D58-US-01 | D58-UC-01 | As a workflow-platform operator, I want to restore the enterprise AI workflow platform with measured headroom, so that readers regain service without creating a second memory incident | New revision is Ready, replay error rate is acceptable, restart count stays flat, and an unrelated pod remains healthy |
| D58-US-02 | D58-UC-02 | As an incident reviewer, I want one timeline across application and kernel evidence, so that the declared root cause can be disproved | Timeline includes actor, pod UID, container, node, limit, peak usage, termination reason, node pressure, environment, timestamp, and immutable incident ID |
End-to-end product flows
The customer-visible symptom begins outside Kubernetes, so starting with a manifest edit loses the causal chain. The smallest flow follows the request to its failed process and back to a verified reader response before expanding into internal evidence.
| Flow ID | Use case IDs | Path | Trigger | Numbered steps | Terminal evidence |
|---|---|---|---|---|---|
| D58-FLOW-01 | D58-UC-01, D58-UC-02 | Recovery | Reader receives an error from the enterprise AI workflow platform | 1. Capture the failed request and time. 2. Identify the serving pod and previous container. 3. Read termination, resource, node, and traffic evidence. 4. Choose rollback, traffic reduction, or measured resize. 5. Deploy one controlled revision. 6. Replay traffic and compare controls. | Incident ID, deployment revision, request trace, old termination, resource diff, replay result, and unaffected pod probe |
| D58-FLOW-02 | D58-UC-01, D58-UC-02 | Denied | Operator proposes raising the limit before checking node capacity | 1. Admission or reviewer reads requested resources. 2. Compare them with allocatable headroom and policy. 3. Reject the unsafe revision. 4. Preserve the running recovery option. 5. Record the missing evidence. | Denied revision with actor, reason, expected headroom, observed headroom, environment, timestamp, and immutable review ID |
System design derived from the flows
A restart reason alone cannot show whether the node was also unhealthy, so the incident system must join Kubernetes desired state with kernel and customer observations. A control group, or cgroup, is the Linux accounting and enforcement boundary used for the container's processes.
| Use case ID | Entry point | Responsible services | Authoritative store | Failure evidence |
|---|---|---|---|---|
| D58-UC-01 | Incident console and Deployment revision | Ingress, Deployment controller, scheduler, kubelet, container runtime, Linux cgroup controller, synthetic probe | Kubernetes API desired/status state plus probe result store | OOMKilled, replacement Pending, failed readiness, elevated customer error rate, or node headroom denial |
| D58-UC-02 | Incident evidence review | Metrics, logs, events, kubelet status, application profiler, incident recorder | Time-series/log stores and immutable incident record keyed to pod UID | Missing interval, mismatched pod UID, absent node condition, or hypothesis contradicted by replay |
Kubernetes documents that memory limits are enforced reactively by the kernel and that a container may be killed when it exceeds its limit; scheduling, by contrast, uses requests (Kubernetes resource management). Node-pressure eviction is a separate kubelet mechanism that protects the node (Kubernetes node-pressure eviction).
Data model and ownership
An incident cannot be audited if mutable pod names are the only join key, because replacements reuse labels but receive new identities. The records below preserve desired state, observed runtime state, and customer proof without pretending they share one owner.
Generated-application database: Not created in this slice — the platform's domain data is unchanged; Kubernetes, observability, deployment, and incident stores already own the evidence required to recover and review the outage.
| Record or entity | Store and owner | Primary key | Foreign key or opaque reference | Tenant key | Material constraint | Lifecycle and deletion | Use case IDs |
|---|---|---|---|---|---|---|---|
| WorkloadRevision | Kubernetes API store, owned by Deployment controller and platform team | Deployment UID plus revision | Pod-template hash references created pods | Namespace | Requests and limits pass policy and the revision is immutable once observed | Created per rollout, retained in history, expired by revision policy | D58-UC-01, D58-UC-02 |
| ContainerTermination | Kubernetes pod status and runtime evidence, owned by kubelet | Pod UID plus container name plus restart ordinal | Opaque node UID and runtime container ID | Namespace | Reason, exit code, timestamps, and resource revision describe the same container lifetime | Lives with pod status; exported incident copy follows evidence retention | D58-UC-01, D58-UC-02 |
| IncidentEvidence | Incident store, owned by operations | Incident ID plus evidence ID | Opaque pod UID, deployment revision, trace ID, and metrics query ID | Service ownership key | Claim must link positive, negative, and unaffected-control observations from one environment and interval | Sealed at review, retained by audit policy, then deleted or legally held | D58-UC-01, D58-UC-02 |
Diagnose from symptom to enforcing boundary
The same outage can present as a 502, a restart, or a Pending replacement, so one signal cannot identify the failed boundary. Use a short evidence ladder and stop when a competing explanation remains possible.
| Observation | Meaning | What it does not prove | Next discriminating check |
|---|---|---|---|
| Reader sees 502/503 | No healthy backend answered through the edge path | Memory was the cause | Pod readiness, endpoints, and request trace |
Previous container shows OOMKilled | Kernel ended that container lifetime after an out-of-memory condition | Leak versus legitimate peak; node health | Limit, usage curve, application profile, node conditions |
Node has MemoryPressure | Kubelet observed a configured pressure threshold | This container crossed its own limit | Eviction events and node available-memory series |
| Replacement is Pending | Scheduler found no eligible placement | Runtime memory exhaustion | Scheduler events, requests, taints, affinity, allocatable remainder |
Commands and manifests versus physical effects
A command is useful only when the operator can say which state it reads or changes underneath. This mapping prevents a YAML edit from being mistaken for new hardware.
kubectl get pod enterprise-workflow-api-abc -n workflow-platform -o jsonpath='{.status.containerStatuses[0].lastState.terminated}'
kubectl describe pod enterprise-workflow-api-abc -n workflow-platform
kubectl top pod enterprise-workflow-api-abc -n workflow-platform --containers
kubectl describe node worker-3
kubectl rollout status deployment/enterprise-workflow-api -n workflow-platform
resources:
requests:
memory: 384Mi
limits:
memory: 768Mi
| Code or action | Kubernetes or software effect | Hardware/runtime effect | Customer proof |
|---|---|---|---|
| Read previous termination | API server returns kubelet-reported status for the prior container lifetime | No memory changes; evidence is read | Correlate failure time with reader error |
Read kubectl top | Metrics API returns recent usage samples if a metrics pipeline exists | Samples kernel accounting; it does not reserve RAM | Compare measured peak with limit and replay |
Change requests.memory | New pod template asks scheduler to reserve a different node budget | No DRAM is allocated immediately | Replacement either schedules or stays Pending with evidence |
Change limits.memory | Runtime configures a different cgroup ceiling for replacement containers | No RAM is added; kernel permits charges only up to the new boundary | Replay completes below limit with stable latency and restarts |
| Roll back Deployment | Controller creates pods from an earlier template revision | Processes are replaced on eligible nodes | Healthy endpoints and customer probes recover |
Recovery sequence and decision rule
Pressure to restore service can erase evidence or introduce an unsafe resize, so recovery and diagnosis must interleave. Preserve the old pod status and interval first, restore through the least invasive reversible action, then test the hypothesis.
- Capture the failed request time, pod UID, previous termination, events, resource spec, node condition, and traffic/usage interval.
- Restore availability with a known-good rollback, traffic shedding, or additional healthy replicas when capacity permits.
- Classify the boundary: container cgroup, node pressure, or scheduler placement.
- Profile memory growth and decide whether the peak is legitimate, reducible, or leaking.
- Change one resource or application variable through a new revision.
- Replay representative traffic; compare reader errors, latency, usage, restarts, and an unaffected control.
Decision rule: raise a limit only for a measured legitimate peak with node headroom; fix the application for unbounded growth; add compatible nodes when justified requests cannot fit. A bigger machine can postpone a leak, but it cannot turn an unbounded process into a bounded one.
Key takeaways
An OOM incident is a chain from a customer request to a Linux enforcement event, with Kubernetes recording desired and observed state around it. A reliable operator names the boundary, preserves immutable evidence, applies one reversible change, and measures the same customer path again.
- Requests affect placement; limits affect runtime enforcement; neither adds RAM.
OOMKilled, node-pressure eviction, and Pending placement require different actions.- Pod UID, revision, interval, and control probes make the root-cause claim falsifiable.
Checklist
A recovery is incomplete if the enterprise AI workflow platform appears healthy but the evidence cannot show why or whether the failure will recur. Confirm each item against a real incident record.
- [ ] Captured failed request, pod UID, previous termination, events, and node conditions.
- [ ] Separated container OOM, node pressure, and unschedulable placement.
- [ ] Preserved original evidence before restarting or replacing the workload.
- [ ] Mapped every configuration change to its scheduler, kernel, or hardware effect.
- [ ] Replayed traffic and recorded positive, negative, and unaffected-control results.