Topology and traffic

A Kubernetes topology map, with the traffic your mesh already measures

PodSteer draws a namespace, several namespaces or the whole cluster as one map: workloads, pods, Services, Ingresses, Gateway API routes, autoscalers, budgets and policies, joined only by relationships that exist in the cluster. Switch on observed traffic and the same map shows request rates, errors and latency from the Prometheus your service mesh or eBPF tool already feeds — with nothing installed in the cluster.

What is on the map

The Topology page draws the sidebar's namespace selection — one namespace, several, or all of them — rather than one object's neighbourhood. Every line is a relationship Kubernetes has: an owner reference, a Service or budget selecting pods, an Ingress or route sending to a Service, an autoscaler scaling its target, a pod running as its ServiceAccount.

  • Deployments, StatefulSets, DaemonSets and CronJobs, their ReplicaSets and Jobs, and the pods they own.
  • Services and Ingresses, and Gateway API Gateways and routes when the cluster serves that API.
  • HorizontalPodAutoscalers, PodDisruptionBudgets and NetworkPolicies, drawn as what they select.
  • ServiceAccounts, and the ConfigMaps, Secrets and PersistentVolumeClaims pods name — as names from the template, never read.
  • Custom resources that own something, such as an Argo Rollout over its ReplicaSets, taken from owner references.
The Topology page for the storefront namespace, grouped by application with ReplicaSets switched off: framed groups for catalog, catalog-migrate, checkout, image-resizer, orders-db, recommendations and reviews, and the tops of search-indexer, shopper and storefront below them. Inside, Deployments, a StatefulSet, Services, pods, a ConfigMap, a Secret, a ServiceAccount, an autoscaler, a disruption budget and volume claims, joined by lines labelled via ReplicaSet, runs as and claim template; finding badges mark the image-resizer, recommendations and reviews pods. The Topology page for the storefront namespace, grouped by application with ReplicaSets switched off: framed groups for catalog, catalog-migrate, checkout, image-resizer, orders-db, recommendations and reviews, and the tops of search-indexer, shopper and storefront below them. Inside, Deployments, a StatefulSet, Services, pods, a ConfigMap, a Secret, a ServiceAccount, an autoscaler, a disruption budget and volume claims, joined by lines labelled via ReplicaSet, runs as and claim template; finding badges mark the image-resizer, recommendations and reviews pods.
A namespace, drawn as one map. Every line is a relationship Kubernetes has, and the assessment's findings sit on the boxes they are about.

Reading a large map

  • Group by namespace, by app label or by any label you name, and collapse a group into one box that keeps complete counts and its worst state. Grouped by application, tick which applications are drawn.
  • Switch a kind or a kind of line off, in one row that scrolls sideways; every toggle carries the full count for the scope, not only what is drawn.
  • Search for an object and the map centres on it.
  • What is not drawn, and what each traffic status means, is explained in the page's help panel rather than under the map.
  • PodSteer shows its findings on the map: a box carries a badge when the assessment has something to say about it.
  • Click a box and its details open in a drawer over the map, which stays where you left it.
  • Above 3,000 pods, pods are folded into counted boxes per workload, and the map says it did.
  • Save everything drawn as a PNG, including the traffic column beside the map.

It holds still while you read it

The map is drawn when you open it and when you ask, never on a timer. When something in the scope changes, a Changed — Refresh badge says so instead of moving the boxes under your pointer. Live mode is there if you want it, off by default: it redraws after the changes settle and never re-fits the view, so what you were looking at stays where it was. Lines move in the direction of the dependency, and traffic lines faster the busier they are; the motion stops under reduced motion and above 200 lines.

Observed traffic, from the Prometheus you already run

Traffic is a layer over the map, not a line PodSteer infers. It is read from your cluster's own Prometheus, only when you switch on the toolbar's traffic toggle, from the metrics Istio, Linkerd, Beyla or OpenTelemetry eBPF Instrumentation, Caretta or Cilium's Hubble already publish there. Each line carries the request or connection rate, the error rate and p50, p95 and p99 latency where the source exposes them, over 5 minutes, 15 minutes or an hour, and the panel shows the exact PromQL it sent.

Querying the monitoring stack is off until you turn it on for a cluster, and you choose which discovered Prometheus answers under Settings → Clusters. The query travels through your API server's own service proxy on your kubeconfig's credentials. When the monitoring backend itself refuses that proxy — linkerd-viz's Prometheus does, by design — PodSteer opens a short-lived local port-forward for that one request and closes it when the answer arrives. Nothing is installed: when no source is found, the panel names what would be needed.

The storefront topology with every application group collapsed and observed traffic switched on, read from Istio over the last 5 minutes: lines from the shopper group to the groups it calls, a red line to recommendations, whose requests fail, and lines from platform/traffic-sim, drawn as a dashed box because it lives outside the namespace. The traffic options are open: 11 lines from Istio, the 5m window selected, and the PromQL PodSteer sent behind What PodSteer asked. The storefront topology with every application group collapsed and observed traffic switched on, read from Istio over the last 5 minutes: lines from the shopper group to the groups it calls, a red line to recommendations, whose requests fail, and lines from platform/traffic-sim, drawn as a dashed box because it lives outside the namespace. The traffic options are open: 11 lines from Istio, the 5m window selected, and the PromQL PodSteer sent behind What PodSteer asked.
Observed traffic over the map. Rates, errors and latency from the Prometheus the mesh already feeds, drawn over the relationships rather than instead of them.

What it does not do.

  • Traffic needs a Prometheus that scrapes a service mesh or an eBPF tool — Istio, Linkerd, Beyla or OBI, Caretta, or Hubble's metrics. Without one there is a map and no traffic.
  • PodSteer never installs a traffic source, and does not read Hubble Relay's flow API: Hubble traffic comes only from Hubble's Prometheus metrics.
  • A NetworkPolicy is drawn as what it selects. PodSteer does not evaluate whether traffic is allowed or blocked; that depends on every policy in the namespace and on the CNI enforcing them.
  • A topology is one cluster. There is no map spanning several clusters, and a monitoring backend holding other clusters' series is refused for traffic, because a workload of the same name elsewhere would be counted as yours.
  • Some counts are what the source reports, double counts included: Istio can count a request twice when a proxy lacks its peer's metadata, and Hubble counts a cross-node flow from both nodes.
  • Traffic is grouped by pairs of workloads, never by pod, and more than 5,000 pairs is refused rather than drawn.
  • ConfigMaps, Secrets and claims are names taken from pod templates; a missing one is drawn as a name, not checked.
  • The PNG export is a desktop-application feature: it saves through the system's file dialog.

Cluster assessment

Ranked findings instead of a pod list: crash loops, OOM kills, pods that will never schedule, sizing problems — each with what to do about it.

Multi-cluster

Real tabs, one cluster each; one table across every open cluster; clusters found through your own cloud CLI.

Operator panels

Built-in views for cert-manager, KEDA, External Secrets, Argo Rollouts, Trivy, Karpenter, Gateway API and more — no plugin API, nothing to install.