Repository navigation
Commit 6713f57
authored
Topology routing: per-Pod Service membership, default backends, private Knative, and every Internet entrypoint (#2045)
The traffic view drew routes that don't exist and dropped some that do:
- A Service selecting only stable Pods was drawn to canary Pods too.
- An Ingress with only a default backend had no edge, and its drawer
warned "Traffic will not be routed".
- A private Knative Service looked reachable from the Internet.
- Every Traefik IngressRoute, Knative Service, Istio Gateway and Contour
HTTPProxy was disconnected from the Internet node. The traffic view
always groups by namespace for layout, even under "No Grouping", and
regrouping rebuilt Internet edges only to Ingresses and Gateways.
These come from an audit of every place Radar builds topology edges;
this PR fixes the routing and membership findings.
## What changed
**Pod membership is per Pod, not per group.** Pods group by app label,
so one group can hold stable and canary Pods that different Services
select. The traffic view took the union of the group's Services and drew
every one to every Pod.
- Membership is now recorded per Pod (`PodGroup.PodServiceIDs`).
- Individual Pod edges and summary-mode health counts use each Pod's own
Services.
- When a Service selects only part of a group, its edge to the group is
labelled, e.g. "5 of 7 pods". Expanding the group reconnects each Pod
only to its own Services, through the same `ownerIds` the resources view
uses for mixed-owner groups.
**Selectors require their keys.** A selector value of `""` matches only
Pods that carry the label with an empty value, as in Kubernetes. Radar
read a missing key as `""`, so a Service selecting `role: ""` was drawn
to Pods without the label. This applies to every selector match in
topology.
**Every Internet entrypoint stays connected.** Regrouping the Internet
node now moves each original Internet edge, whatever the entrypoint
kind, and leaves an ungrouped entrypoint on the original node. The logic
moved into a pure, tested helper, `internet-groups.ts`.
**Ingress default backends.** Several readers ignored
`spec.defaultBackend`. One extraction
(`configrefs.IngressBackendServices`: the default backend plus every
rule path, each Service once) now feeds:
- Topology, in both views. The same edge ID used to be emitted once per
path.
- AI resource context.
- The missing-Service check, which no longer reports one Service once
per path and now checks the default backend.
The Ingress drawer shows a **Default Backend** row, for a Service or a
resource backend, and no longer warns for an Ingress that routes
everything to its default backend.
**Private Knative Services.** A Knative Service is private when it has
the label `networking.knative.dev/visibility=cluster-local`, or when its
published URL is its cluster-local address (`status.url` host equals
`status.address.url` host). Knative builds a private Route's URL from
the same cluster-local template as its address, on any cluster domain,
so this also covers a label set on the Route. A DomainMapping that
targets the Service or its Route publishes it again. Private Services
get no Internet edge ([private
services](https://knative.dev/docs/serving/services/private-services/),
[DomainMapping](https://knative.dev/docs/serving/services/custom-domains/)).
The node says why:
- A cluster-local Service carries a **Cluster-local** badge. Radar
withholds it if DomainMappings can't be read, because the Service may be
mapped.
- A mapped Service shows its custom domain as its subtitle. The tooltip
lists every mapped domain and the internal address.
**Traefik ServersTransport configures a route; it doesn't replace its
backend.** A backend with `serversTransport` used to become route →
transport → Service, so the Service lost the route from its Routes,
focused topology stopped at the transport, and two routes sharing a
transport looked joined. Now:
- The route always routes to its backend.
- The transport is configuration of each route that uses it, drawn even
when the backend Service is missing.
- The transport resolves where Traefik resolves it: an HTTP backend's
namespace, a TCP route's own namespace. A TraefikService backend ignores
`serversTransport`, so it gets no transport edge.
## Result on a live cluster
A kind cluster with 7 `shop` Pods (5 stable, 2 canary) behind three
Services, 3 `cart` Pods behind stable and canary Services, Ingresses
with a default backend, three repeated paths and missing Services,
Traefik routes sharing a transport, and public, private and
domain-mapped Knative Services. Same cluster, `main` vs this PR:
| Traffic view, before | Traffic view, after |
|---|---|
| 
| 
|
| Ingress drawer, before | Ingress drawer, after |
|---|---|
| 
| 
|
- The "5 of 7" and "2 of 7" labels match the Services' EndpointSlices
exactly, as do the per-Pod `ownerIds`.
- A missing-Service audit on one Ingress went from `gone` three times to
`ghost-default` and `gone` once each.
On a real Knative 1.23 install (EKS), the traffic view looks like this:

## Testing
- Builder-level Go tests for each fix:
- stable/canary Services against small groups, large groups and summary
mode;
- transports shared by two routes, with a missing backend, across
namespaces, and on a TraefikService backend;
- a default-backend-only Ingress and a triplicated path, in both views;
- public, labelled, URL-private, custom-cluster-domain, unpublished and
domain-mapped Knative Services, including the node's badge and domains,
and a failed DomainMapping list;
- selectors with an empty value, against Pods with and without the
label.
- An audit check test, an Ingress drawer render test, and unit tests for
the regrouping helper.
- Each new test fails with its fix reverted.
- Full suites pass: `pkg` and `internal` Go tests, `make tsc`, the
shared UI and web unit suites.
## Notes
- **Not fixed here:** every Istio Gateway and Gateway API Gateway still
gets an Internet edge, including Knative's cluster-local gateway.
Telling an external gateway from an internal one means reading its
Service type and listeners, which is a design question. It's tracked in
RAD-695, with these known gaps that predate this PR:
- provider-qualified transport references (`ns-name@kubernetescrd`) and
transports inside TraefikService weighted or mirroring lists aren't
resolved;
- app grouping doesn't move Internet edges for entrypoints the layout
assigns to an app by inference.
- An IngressRoute's backend still files under Pods in the drawer; #2049
moves it to Routes To.
- **Version skew:** a newer UI against an older Radar keeps that Radar's
membership decisions. An older UI against this Radar ignores the
partial-membership label.1 parent d66825d commit 6713f57
18 files changed
Lines changed: 898 additions & 224 deletions
File tree
- packages/k8s-ui/src/components
- resources/renderers
- topology
- pkg
- audit
- configrefs
- resourcecontext
- topology
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
16 | 17 | | |
17 | 18 | | |
18 | 19 | | |
19 | | - | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
20 | 24 | | |
21 | 25 | | |
22 | 26 | | |
| |||
50 | 54 | | |
51 | 55 | | |
52 | 56 | | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
53 | 80 | | |
54 | 81 | | |
55 | 82 | | |
56 | 83 | | |
57 | | - | |
| 84 | + | |
58 | 85 | | |
59 | 86 | | |
60 | 87 | | |
| |||
87 | 114 | | |
88 | 115 | | |
89 | 116 | | |
90 | | - | |
| 117 | + | |
91 | 118 | | |
92 | 119 | | |
93 | 120 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | | - | |
| 2 | + | |
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
21 | 38 | | |
22 | 39 | | |
23 | 40 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
200 | 200 | | |
201 | 201 | | |
202 | 202 | | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
203 | 229 | | |
204 | 230 | | |
205 | 231 | | |
| |||
488 | 514 | | |
489 | 515 | | |
490 | 516 | | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
491 | 521 | | |
492 | 522 | | |
493 | 523 | | |
| |||
558 | 588 | | |
559 | 589 | | |
560 | 590 | | |
561 | | - | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
562 | 595 | | |
563 | 596 | | |
564 | 597 | | |
| |||
664 | 697 | | |
665 | 698 | | |
666 | 699 | | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
| 705 | + | |
| 706 | + | |
667 | 707 | | |
668 | 708 | | |
669 | 709 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
| 35 | + | |
35 | 36 | | |
36 | 37 | | |
37 | 38 | | |
| |||
548 | 549 | | |
549 | 550 | | |
550 | 551 | | |
551 | | - | |
552 | | - | |
553 | | - | |
554 | | - | |
555 | | - | |
556 | | - | |
557 | | - | |
558 | | - | |
559 | | - | |
560 | | - | |
561 | | - | |
562 | | - | |
563 | | - | |
564 | | - | |
565 | | - | |
566 | | - | |
567 | | - | |
568 | | - | |
569 | | - | |
570 | | - | |
571 | | - | |
572 | | - | |
573 | | - | |
574 | | - | |
575 | | - | |
576 | | - | |
577 | | - | |
578 | | - | |
579 | | - | |
580 | | - | |
581 | | - | |
582 | | - | |
583 | | - | |
584 | | - | |
585 | | - | |
586 | | - | |
587 | | - | |
588 | | - | |
589 | | - | |
590 | | - | |
591 | | - | |
592 | | - | |
593 | | - | |
594 | | - | |
595 | | - | |
596 | | - | |
597 | | - | |
598 | | - | |
599 | | - | |
600 | | - | |
601 | | - | |
602 | | - | |
603 | | - | |
604 | | - | |
605 | | - | |
606 | | - | |
607 | | - | |
608 | | - | |
609 | | - | |
610 | | - | |
611 | | - | |
612 | | - | |
613 | | - | |
614 | | - | |
615 | | - | |
616 | | - | |
617 | | - | |
618 | | - | |
619 | | - | |
620 | 552 | | |
621 | 553 | | |
622 | 554 | | |
| |||
636 | 568 | | |
637 | 569 | | |
638 | 570 | | |
639 | | - | |
| 571 | + | |
640 | 572 | | |
641 | 573 | | |
642 | 574 | | |
643 | 575 | | |
644 | 576 | | |
645 | | - | |
| 577 | + | |
646 | 578 | | |
647 | 579 | | |
648 | 580 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
0 commit comments