See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
Three layers, one state, one diagram
The bottom layer is cloud: a managed cluster, node pools, networking, an identity or two. The middle layer is the kubernetes provider: namespaces, deployments, services, ingresses declared as Terraform resources. The top layer is Helm, and it is unusually simple to draw, because the provider ships a single resource, helm_release, which is the whole layer.
Keeping all three in one repository is a deliberate choice with a real payoff: one plan, one state, one approval path instead of a terraform apply followed by a separate helm upgrade. The cost is that the repository now mixes infrastructure and application concerns, and a reader needs the boundary drawn for them.
What each layer looks like once parsed
Managed clusters are recognized per provider and drawn with the right mark: aws_eks_cluster with the EKS icon and its version attribute, azurerm_kubernetes_cluster with the AKS icon carrying kubernetes_version and sku_tier, google_container_cluster labelled GKE cluster with the Kubernetes icon.
On the Kubernetes side, kubernetes_deployment is treated as a major resource and carries its replicas, while kubernetes_service, kubernetes_namespace, and ingress resources are minor, which means several of them collapse into one node with the count and the member names rather than filling the canvas with squares.
helm_release is major and carries chart, version, and repository on the node. That is precisely what a reader wants to know about a platform chart, and it is the one place where a diagram beats reading the code, because those three values are usually spread across a locals block, a variable, and a for_each.
drawn node description on the box ----------------------------- -------------------------------------- EKS cluster (aws_eks_cluster) version = 1.29 nginx-ingress (helm_release) chart nginx-ingress-controller 4.10.1 external-dns (helm_release) chart external-dns 1.14.5 app (kubernetes_deployment) replicas = 3 Supporting resources x6 services, namespaces, config maps
Where the arrows come from, and where they do not
Arrows come from references inside resource arguments, resolved through module outputs to the resources they actually reach. A helm_release whose values reference module.eks.cluster_name, or a kubernetes_deployment placed in a namespace created by kubernetes_namespace, gets a real labelled edge.
One honest gap is worth planning around. When a helm_release is tied to its cluster only through provider configuration, the common pattern where the helm provider block reads module.eks.cluster_endpoint, that relationship lives in a provider block rather than in the resource, and it does not become an arrow. If you want the dependency visible, reference the cluster from the release itself or route it through a resource that does.
The analysis is also not a cluster scan. There is no kubeconfig, no cluster API call, and no chart rendering, so a release is drawn as the release rather than expanded into the workloads the chart contains. For the objects side of the story, the manifest pipeline is covered in living diagrams from Kubernetes manifests.
Which type lands where, and why some do not land at all
The classification is a table of known types plus keyword rules for everything else, applied in a fixed order, so the same repository produces the same picture on every sync. Managed clusters, kubernetes_deployment, and helm_release are the known majors. A node carries at most three attribute values, taken in a priority order set per type.
What falls out of the rules is worth planning around. The first keyword rule matches names containing role, permission, grant, member, iam, or acl, so kubernetes_cluster_role_binding is classified as wiring and counted rather than drawn, before any Kubernetes rule gets a chance to look at it. The second rule catches secret, so kubernetes_secret is counted too, which is the right answer for a diagram and worth knowing if you were expecting a box.
One sharp edge: the known-type table is keyed on the unsuffixed names. A repository written against kubernetes_deployment_v1 rather than kubernetes_deployment still gets the Kubernetes mark, because the provider fallback supplies it, but it is treated as supporting detail and its replica count is not printed on the node.
declared in .tf drawn as
------------------------------- ------------------------------------
aws_eks_cluster major, EKS icon, version on the box
azurerm_kubernetes_cluster major, AKS icon, kubernetes_version
and sku_tier on the box
google_container_cluster major, "GKE cluster", Kubernetes icon
helm_release major, Helm icon, chart + version +
repository on the box
kubernetes_deployment major, replicas on the box
kubernetes_service / _namespace minor, rolled up with a count
kubernetes_config_map minor, Kubernetes mark
kubernetes_secret wiring: counted in a note, no box
kubernetes_cluster_role_binding wiring: counted in a note, no boxFAQ
Does this read my cluster or my kubeconfig?
Are Helm charts expanded into the objects they install?
Which Kubernetes resources get their own box?
Why is there no arrow between my helm_release and the cluster?
Can the infrastructure layer and the application layer stay on one canvas?