POST /pod/traffic
Insert a single observed traffic event. The kguardian controller
calls this directly when a network event arrives from one of the
eBPF ring buffers; external integrations rarely need it (prefer
POST /pod/traffic/batch below for bulk).
Duplicate events (same pod_ip, pod_port, traffic_type,
traffic_in_out_ip, traffic_in_out_port, ip_protocol,
decision) are deduped server-side and reported back as the
inserted-or-Null result. The audit forwarder (when
evaluator.enabled: true) is fired only for events that were
genuinely new.
Request
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"pod_name": "my-app-7d9f6b8c4-x5z2w",
"pod_namespace": "production",
"pod_ip": "10.244.1.5",
"pod_port": "8080",
"ip_protocol": "TCP",
"traffic_type": "INGRESS",
"traffic_in_out_ip": "10.244.2.10",
"traffic_in_out_port": "52341",
"decision": "ALLOW",
"time_stamp": "2026-05-12T10:32:14.123456"
}
traffic_type is "INGRESS" (matches the upstream NetworkPolicy
casing) or "EGRESS"; decision is "ALLOW" (eBPF observed an
allow) or "DROP" (NetworkPolicy dropped the flow before it
reached the destination, observed via the netpolicy-drop probe).
POST /pod/traffic/batch
Bulk variant taking a JSON array of the same shape. The controller
batches up to 100 events at a time (or one second elapsed since
last flush, whichever first); call sites talking to a remote
broker should use this path to amortise the round-trip.
Response is an integer count of the rows actually inserted after
dedup.
GET /pod/traffic
Get every observed traffic row. Returns rows ordered
(time_stamp DESC, uuid DESC) — newest first, with the UUID
primary key as a tiebreak for microsecond-collision rows from a
single batch ingest.
Currently unbounded — no LIMIT, no pagination. On a busy cluster
with months of retained traffic this can be tens of MB to GB of
JSON. Prefer the per-pod variant for any interactive use.
Example
curl http://localhost:9090/pod/traffic
Response
[
{
"uuid": "234e5678-e89b-12d3-a456-426614174001",
"pod_name": "my-app",
"pod_namespace": "production",
"pod_ip": "10.244.1.5",
"pod_port": "35821",
"ip_protocol": "TCP",
"traffic_type": "EGRESS",
"traffic_in_out_ip": "10.244.3.15",
"traffic_in_out_port": "5432",
"decision": "ALLOW",
"time_stamp": "2026-05-12T10:32:14.123456"
}
]
GET /pod/traffic/{name}
Get traffic for a single pod by name. The actix route captures
name directly — no separate namespace path segment — so:
curl http://localhost:9090/pod/traffic/my-app-7d9f6b8c4-x5z2w
Same row shape as GET /pod/traffic above; same ordering.
A name that doesn’t match any rows returns 404 with body
"No data found". The frontend’s per-pod traffic view handles
this transparently by falling back to an empty list.