The Container Was Rebuilt — But the Suspicious Behaviour Returned
The team deleted a suspicious pod in Azure Kubernetes Service.
Kubernetes immediately created another one.
Minutes later, the same unexpected outbound connection appeared.
“We rebuilt the container, Agent Foskett.”
“Excellent. Did you remove the problem?”
“We removed the pod.”
Agent Foskett looked at the deployment manifest. “Ah. You deleted the actor. The script is still running.” ☕

Case file: The behaviour that survived the rebuild
A fictional investigation into AKS pod recreation, Kubernetes controllers, container image integrity, runtime detection and workload identity.
The alert came back
An operator deleted the affected pod. The deployment controller restored the desired replica count, and the replacement pod initially looked healthy. At 02:27 UTC, similar runtime behaviour was reported again.
This is a fictional training case. Times, names, indicators and findings are illustrative. Real alert names, log fields and telemetry coverage vary by enabled Defender plans, AKS configuration, agent versions and data collection settings.
A pod is disposable. Its configuration is not
A recurring alert could reflect a compromised image, a malicious or misconfigured startup script, a mounted persistent volume, an injected sidecar, an abused init container, a compromised application dependency or an external actor repeatedly exploiting the workload. Recurrence alone does not identify which explanation is correct.
Preserve evidence before deleting anything else
Avoid relying on a pod name alone: replacement pods often have different names and UIDs. Compare owner references and immutable image digests. A mutable tag such as
latest cannot establish that two pods ran the same image bytes.KQL: Identify replacement pods and their controller lineage
KubePodInventory can help reconstruct pod transitions. Column availability and ingestion frequency depend on the environment. This query looks at one namespace and pod-name prefix; confirm the prefix and time range before running. Inventory is sampled state, not a complete Kubernetes API audit trail.- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
// Log Analytics / Sentinel: requires KubePodInventory ingestion
let lookback = 24h;
let targetNamespace = "production";
let podPrefix = "orders-api-";
KubePodInventory
| where TimeGenerated > ago(lookback)
| where Namespace == targetNamespace
| where Name startswith podPrefix
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated),
States=make_set(PodStatus, 10),
Nodes=make_set(Computer, 10)
by ClusterName, Namespace, Name, PodUid
| order by FirstSeen ascKQL: Look for suspicious container output
ContainerLogV2, start with the affected namespace and a tight time window. Search terms below are triage hints, not proof of compromise: legitimate diagnostic tools and application messages can match them.Defender for Containers runtime alerts and, where deployed, endpoint/runtime sensor telemetry should be used to validate process and network claims.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
// Log Analytics / Sentinel: requires ContainerLogV2 ingestion
let startTime = datetime(2026-10-22T02:00:00Z);
let endTime = datetime(2026-10-22T03:00:00Z);
ContainerLogV2
| where TimeGenerated between (startTime .. endTime)
| where PodNamespace == "production"
| where PodName startswith "orders-api-"
| extend Message = tostring(LogMessage)
| where Message has_any ("curl", "wget", "sh", "token", "metadata")
| project TimeGenerated, PodNamespace, PodName,
ContainerName, LogSource, Message
| order by TimeGenerated ascKQL: Correlate Defender alerts with the affected workload
SecurityAlert. The Entities payload varies by alert type; do not assume a stable pod-ID property. Start with the alert time and inspect the alert name, provider and raw entities, then correlate confirmed identifiers back to the cluster and workload.The example deliberately leaves the entity payload visible rather than inventing a universal Kubernetes schema.
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
// Microsoft Sentinel: requires relevant SecurityAlert ingestion
let startTime = datetime(2026-10-22T02:00:00Z);
let endTime = datetime(2026-10-22T03:00:00Z);
SecurityAlert
| where TimeGenerated between (startTime .. endTime)
| where ProviderName has "Azure" or ProductName has "Defender"
| project TimeGenerated, AlertName, AlertSeverity,
ProviderName, ProductName, CompromisedEntity,
Entities, ExtendedProperties, SystemAlertId
| order by TimeGenerated ascWhat did the Kubernetes audit trail say?
Check the configured destination and table format first. Resource-specific tables and the legacy
AzureDiagnostics table have different schemas. In the AKS control plane, inspect create, update, patch and delete events for the Deployment, ReplicaSet, ConfigMaps, Secrets and service accounts. Compare the event identity, request source, timestamp and actual spec changes. A successful API call does not, by itself, prove malicious intent.The clue was in the Deployment, not the replacement pod
The fictional audit trail showed that the Deployment template had been patched through an overprivileged automation identity shortly before the first alert. The replacement pod was faithfully executing the modified specification. The investigation then focused on how that identity was used and whether its permissions extended beyond this namespace.
Was workload identity involved?
In this case, no evidence showed that an Azure token had been used to access another resource. The confirmed issue was unauthorised modification of the Kubernetes Deployment via an automation identity with excessive Kubernetes permissions. The team treated potential Azure identity abuse as a separate hypothesis until corroborating sign-in and resource-access evidence could be collected.
A six-stage evidence timeline
Containment: fix the source of truth
Restore the Deployment from a verified approved manifest, pin and validate the intended image digest, inspect referenced ConfigMaps, Secrets, init containers and volumes, and redeploy through a trusted pipeline. Monitor the replacement workload for the original indicators and new unexpected behaviour. Deleting pods repeatedly is not remediation if the controlling specification remains compromised.
Defensive lessons for AKS teams
Separate the evidence sources: inventory shows what existed, audit logs show control-plane changes, container logs show application output, and runtime sensors may show process or network activity. No single data source tells the whole story.
Agent Foskett closes the case
“And Kubernetes rebuilt it exactly as instructed.”
“So the container wasn’t ignoring us?”
“No. It was obeying the wrong instructions.”
Agent Foskett closed the incident report.
“Next time, investigate the recipe before ordering another cake.” ☕😂
The Logs Already Knew!

