supervisor:GetSummary, and both understand since plus offset, which is what lets you replay an incident rather than only watch the present.
The window is the tool
since sets the length of the window; offset shifts it into the past. since=1h is the last hour; since=1h&offset=2h is the hour that ended two hours ago. The forensics tabs expose this as a 24-hour scrubber you can drag and resize, and the same values live in the URL (?since=&offset=) so a link carries the exact frame you were looking at.
When you know roughly when something happened, set since to the incident’s duration and walk offset backwards a window at a time. The counts snap into place the moment you cover it.
Required arguments
Some views are deliberately un-callable without a subject, because an unscoped answer would be meaningless. They return 400 rather than an empty list:
Every view additionally takes
since, offset and cluster.
Ingress: who is reaching this
GET .../security/flows/ingress-forensics/clients ranks the clients that reached the supervisor’s L7 ingress in the window, and resolves each one to an identity where it can:
identity turns a bare address into something you can act on — a guest cluster node, a standalone VM, or ext/… for a genuinely external client. denied is merged in from the L4 layer, because a client blocked by a network policy never reaches the proxy and would otherwise be invisible here: a row with many denied and few requests is somebody knocking on a closed door.
Pick a client and ingress-forensics/endpoints?ip=… shows exactly what it touched:
ingress-forensics/timeline gives the shape over time — one bucket per minute with requests, errors and distinct clients:
ingress-forensics/sankey renders the client-to-backend fan-out for the same scope.
Worked example — who is hammering this service
1
Scope to the service
Open Ingress Forensics and set
ns and wl to the workload under load. The client table is now only clients that reached it.2
Find the shape of the spike
Read the timeline. A flat line at a high rate is a misconfigured client; a step change points at a deploy; a sawtooth is a retry loop.
3
Rank the clients
Sort by
requests. If one clientIp dominates, its identity usually names the culprit outright. If denied dominates instead, the traffic is being blocked and the client is retrying — that is a policy question, not a capacity one.4
Confirm what it asked for
Drill in with the client’s IP.
uniquePaths and the endpoint rows show whether it hits one hot path or sprays; errors separates “successfully hammering” from “failing and retrying”.5
Replay to find the start
Walk
offset backwards until the client disappears from the table. That boundary is when the behaviour began.Direct-to-VM ingress
L7 forensics can only see traffic that passed through the ingress proxy. A VM exposed by a LoadBalancer Service is reached directly, so there are no HTTP paths, status codes, latencies or real client IPs for it — nothing is on the wire to record them.ingress-forensics/vm covers that gap at L4: per (client, VM, port, protocol) it reports flows, denials and the connection outcome, with client identities resolved through IPAM. When you need the full L7 picture for a VM, POST .../security/flows/ingress-forensics/vm/promote wires it onto the shared Gateway — it creates a ClusterIP Service <vm>-gw selecting the VM on the requested port and attaches a hostname listener with TLS termination and a certificate, so from the next request the VM appears in the client table with complete L7 detail. The request body takes namespace, vm, port, hostname and an optional clusterIssuer; all but the issuer are required. This is the one write in the forensics area and it is gated on vm:Expose, not supervisor:GetSummary. See VM networking for the exposure model it builds on.
Egress: where does this go
GET .../security/flows/egress-forensics/workloads ranks workloads by outbound activity, with the forwarded/dropped split front and centre:
dropped here is the single most actionable number in the Security area: the workload is trying to reach something it is not allowed to reach, repeatedly, and nothing in its own logs necessarily says so.
With ns and wl you get the destinations:
method, host and path are populated only for destinations seen at L7; a plain TCP destination leaves them empty and identifies itself through destIdentity and destIpSample instead. egress-forensics/groups rolls the same data up by parent domain, which turns a dozen subdomains into one line — and returns an empty list when a workload’s egress is entirely L4, since there are no domains to roll up. egress-forensics/timeline and egress-forensics/sankey complete the set.
Cluster-internal destinations are excluded from all egress views. The exclusion is computed from the live pod and service CIDRs of whichever context you selected — the supervisor’s own ranges, or a guest cluster’s spec.clusterNetwork when you scope with cluster= — so a guest with unusual CIDRs does not have its in-cluster traffic misreported as external.
Worked example — where does this workload phone home
1
Start from the ranking
Open Egress Forensics without a workload selected. The table ranks every egressing workload;
uniqueParentDomains separates “talks to one API” from “talks to the whole internet”.2
Select the workload
Its destinations appear, ranked by requests, with
forwarded and dropped per destination.3
Group before you judge
Switch to the parent-domain rollup. Fifty rows of CDN subdomains usually collapse into one vendor, and the outlier that remains is the interesting one.
4
Attribute the drops
For any destination with
dropped > 0, the policy that did it is on the Network policies side: check coverage for the workload, then flow matches for the suspected policy.5
Prove it is not new
Shift
offset back a day. A destination that is present in every window is a dependency; one that appears only recently deserves the attention.When forensics is empty
An empty forensics table has three ordinary causes, in order of likelihood: the window is wrong, the scope is wrong (ns/wl naming a workload that does not exist in that window), or the traffic never passed a point that could observe it — direct-to-VM ingress for the L7 views, cluster-internal destinations for the egress views. Only after those should you suspect ingestion; freshness settles that in one call.
Celum AI drives both sides through
get_forensics, which takes a view argument for each of the eleven variants above and enforces the same required arguments. Pair it with get_l7_events for the individual requests behind a count, and get_flow_denials when the interesting number is what was blocked.