Skip to content

Refactor to relationship-based resource grouping for improved diagram layout #19

@vieitesss

Description

@vieitesss

Motivation

The current k8s-d2 implementation organizes resources by type within each namespace: all workloads together, all services together, all PVCs together. This creates a fundamental mismatch with how Kubernetes resources actually relate to each other, causing arrow crossings that worsen as we add more connection types.

When a namespace contains multiple applications, arrows must cross long distances between type-based sections (service section → workload section → PVC section). For production namespaces with 10-20 workloads, this becomes a tangled web that defeats the purpose of visualization.

The problem compounds with each new feature from the roadmap:

  • Ingress → Service → Workload → PVC = arrows spanning 4 type-based sections
  • ConfigMaps, Secrets, NetworkPolicies add more crossings

The fundamental issue: users think in terms of logical applications (frontend = deployment + service + ingress), but the diagram groups by resource type. This cognitive mismatch makes diagrams harder to understand, especially when users ask "Which resources belong to the frontend application?" and related resources are scattered across the diagram.

Additionally, the current hardcoded grid-columns: 3 inside namespaces prevents D2's pathfinding algorithms from working. According to D2 documentation, grids impose positioning outside the layout engine's control, resulting in center-center straight segments with no smart routing to avoid overlaps.

Proposal

Refactor the rendering logic from type-based grouping to relationship-based grouping, where each workload and its related resources (services, PVCs, and future ConfigMaps/Secrets) are rendered together in a logical group.

Approach:

Each workload becomes the center of a group containing:

  • The workload itself (Deployment/StatefulSet/DaemonSet)
  • Services targeting this workload
  • PVCs used by this workload
  • Future: ConfigMaps, Secrets referenced by this workload

Groups are rendered as D2 sub-containers with direction: down to keep connections within the group. Orphaned resources (services without workloads, unbound PVCs) go into a separate _unmatched group.

Implementation:

  • Add buildResourceGroups() function to analyze relationships before rendering
  • Add findOrphans() function to identify unmatched resources
  • Refactor renderNamespaceIndented() to render groups instead of types
  • Change namespace grid-columns: 2 for wider application groups

Benefits:

  • Minimal arrow crossings (connections stay within groups)
  • Matches user mental model (each box = logical application)
  • Scales to future features (ConfigMaps, Ingress, NetworkPolicies group naturally)
  • Self-documenting (grouping shows which resources work together)

Success criteria:

  • Related resources appear together in labeled groups
  • Orphaned resources clearly identified
  • Generated D2 is valid and backwards compatible
  • Works for namespaces with 1-20+ workloads

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions