# KubeDiagrams: turning Kubernetes manifests into architecture diagrams you can actually edit

> A Python diagram generator that reads manifests, kustomizations, Helm charts, helmfiles and live cluster state, and exports to more formats than most tools attempt.

**philippemerle/KubeDiagrams** — Generate Kubernetes architecture diagrams from Kubernetes manifest files, kustomization files, Helm charts, helmfiles, and actual cluster state

- Repository: https://github.com/philippemerle/KubeDiagrams
- Website: https://kubediagrams.lille.inria.fr/
- Stars: 2,710 · Forks: 179
- Language: JavaScript
- License: Apache-2.0
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/philippemerle-kubediagrams

## One tool for five different sources of cluster truth

Kubernetes diagrams usually start from a manifest, and that is where they tend to stop being useful. A manifest is a partial description of intent. It does not tell you which operator will create a Deployment, which webhook config will reject an admission request, or which of the four Ingress objects actually wins the routing. The consequence is that most diagram tools produce a picture of what somebody wrote down rather than a picture of what a cluster will do.

KubeDiagrams accepts five inputs, and this is the core of the design: Kubernetes manifest files, kustomization files, Helm charts, helmfile descriptors, and actual cluster state. The last one is what separates it from the pack. Pointing the tool at a running cluster is the only way to draw the resources that no human wrote down, and the examples directory shows exactly that kind of diagram, including a rendered instance of Cassandra taken from a deployment rather than from a YAML file.

Because all five inputs land in one renderer, the question of which input is correct becomes a question about which one you trust for the purpose, not about which tool to install. A chart tells you what a release intends to create. A kustomization tells you what the overlay produces. Cluster state tells you what survived admission and scheduling. Those are three different questions, and a single generator that accepts all three lets you answer them without maintaining three diagrams.

The README is unusually candid that it is not the only tool in this space, pointing readers to a separate comparison list of other Kubernetes diagram generators. Its claim of difference is specific rather than general: built-in resource coverage, any custom resources, customizable clustering, arbitrary relationships, declarative custom diagrams, an interactive viewer, a web app, and a JetBrains IDE plugin.

## The GitHub language field says JavaScript, and the project is Python

The GitHub language field reports the primary language as JavaScript. The README badge asks for Python 3.9 or newer, the package on PyPI is built with setuptools, and the container image is a Python base. All of those can be true at once, and here they are, because the tree explains it: the repository holds an interactive viewer and a web app alongside the generator itself.

That is worth pausing on, because it is a fairly common shape for a project that outgrows its original form. The generator is a Python library and a pair of console entry points, and the surrounding directories are browser code. When a repository ships both, the language field reports whichever tree is largest by bytes of code, and the web frontends tend to win on raw size. So the metadata is not wrong, it is answering a narrower question than the one a visitor is asking.

The dependency list in setup.py explains the rendering approach more directly. Four packages do the real work:

```python
install_requires=[
    "PyYAML",
    "diagrams",
    "pygraphviz==1.14",
    "graphviz2drawio",
]
```

`pygraphviz` pinned to an exact version is the line that deserves attention, because it is a binding to a C library rather than a pure Python package. That single pin is the reason the Dockerfile needs a full compile toolchain in its build stage, and it is the reason a pip-only install can fail on a machine without Graphviz headers. A container image or a system package for Graphviz is the safer route.

The entry points are registered as scripts rather than as a package, with `bin/kube-diagrams` and `bin/helm-diagrams` named separately. That naming choice hints at the intended workflow: the same engine is reachable through a general command and through one that knows about Helm release structure, rather than one command with a flag that switches modes.

## Nine output formats, and only three of them matter long term

The README lists D2, DOT, draw.io, GIF, JPEG, Mermaid, PDF, PNG, SVG and TIFF as supported output formats. Read as a menu this looks like sprawl. Read as a set of categories it is much smaller, because the formats split into three groups that serve three different purposes.

The first group is what a reader looks at. PNG, JPEG, GIF, PDF, SVG and TIFF all render to a picture, and the difference between them is resolution, transparency and file size. They are the right output for a slide deck, a design document or a pull request comment. None of them can be edited afterward, which is the limitation that matters if a diagram needs a correction two weeks later.

The second group is what a tool reads. DOT is the native language of Graphviz, so anything that can consume Graphviz, including docs-as-code tooling, can render a KubeDiagrams result. D2 is a newer declarative language that has gained real adoption for this kind of work, and its value here is that it diffs readably, which a rendered picture does not.

The third group is the one that changes how a team uses the tool, and it is the newest. Editable draw.io export arrived in v0.8.0, the current release, and Mermaid output support arrived in the same version. Mermaid in particular is the format to pick if the diagram is going to live in a Markdown file, since a fenced Mermaid block is reviewable in a pull request, versioned with the code, and rendered wherever the repository already renders Markdown. An image committed to a repository goes stale the moment the manifests change; a Mermaid block next to the manifests can be regenerated and compared.

Being explicit about which of these the author prioritizes is useful. v0.8.0 is mostly about output and access rather than about parsing: editable draw.io export, Mermaid support, Gateway API resource kinds, four more built-in kinds, draw.io integration and a cluster tab in the web app, and the JetBrains plugin. The direction of travel is from generating pictures to producing editable artifacts inside existing tooling.

## Six distribution channels for a tool that is really four tools

KubeDiagrams is available as a Python package on PyPI, a container image on Docker Hub, a kubectl plugin, a Nix flake, and a GitHub Action, plus a freely hosted online service. That list is longer than most projects of this size would attempt, and it is worth being clear that these are not six equivalent front doors.

The PyPI package and the container image serve people running the tool locally. The container image is the more reliable of the two, because it wraps the Graphviz dependency that the pip install leaves to the host. The Dockerfile is small enough to read in full, which tells you most of what the image does:

```dockerfile
FROM docker.io/alpine/helm:3 AS helm

FROM docker.io/python:3.13-alpine AS base
RUN apk update && apk add graphviz bash
RUN apk update && apk add graphviz bash
RUN apk add --no-cache build-base graphviz-dev
RUN pip install --upgrade pip && pip install PyYAML diagrams pygraphviz==1.14 graphviz2drawio
RUN apk del build-base graphviz-dev
ADD bin /usr/local/bin/
COPY --from=helm /usr/bin/helm /usr/local/bin/helm
WORKDIR /work
```

Two decisions stand out. The build toolchain is installed and then removed in the same layer sequence, so the image ships without a compiler, which matters because the image is meant to parse Helm charts and therefore needs the helm binary too. The helm binary is copied from a separate stage rather than installed, so it comes from a purpose-built Alpine image rather than from a package manager.

The remaining three channels target automation rather than people. A kubectl plugin means `kubectl` can run a diagram against live cluster state without a second install step. A GitHub Action means a repository can regenerate its diagram on push, which is the only channel that makes the output formats worth having actually sustainable. A Nix flake pins the whole dependency graph including Graphviz, which removes the exact problem that the pinned `pygraphviz` version creates for everyone else.

The online service hosted by Inria Lille is the outlier here and the one most people will meet first. It is a hosted instance of the same tool, free to use, which means you can produce a diagram before deciding whether to install anything. For a project whose whole value is making a cluster legible to people who do not operate it, a hosted front door that requires no local setup is arguably the most important of the six.

## Twenty-five example directories that double as a test corpus

The examples directory is the largest single part of the repository, and it is the part that says the most about what the tool actually handles. There are twenty-five of them, and they include Argo, Bank of Anthos, Cassandra, cert-manager, Istio, k0s, Gateway API, an OpenTelemetry demo, an online boutique, a teastore, deathstarbench, External Secrets, and several 5G-related chart collections.

What makes that list useful rather than decorative is the variety of input type in it. Some entries are plain manifests, some are Helm charts, some are helmfile descriptors, and at least one, kube-prometheus-stack, is a chart large and messy enough that the resulting diagram is genuinely hard to produce by hand. That last case is the argument for the project. Kube Prometheus Stack expands into a large set of workloads, services, webhook configurations and monitoring components, and no human is going to keep a picture of that current by hand.

Several examples exist because an issue asked for them. v0.6.0 added an inside-workloads example to show the internal structure of workloads, meaning pods, volumes, containers, mounted volumes, and the config maps and secrets they reference. That is a nesting level below the cluster view, and it only became worth building because somebody needed to see inside a pod rather than just see that a Deployment exists. v0.7.0 added an External Secrets Operator example for the same reason.

The same release shows the tool being improved by being surprised. v0.6.0 added reporting for warnings when no resource matches a Prometheus selector, and added custom edges between specific pods and services in the Grafana setup. Both are the kind of fix that only appears once someone points the tool at a real chart, and they are a reasonable signal about how the project develops: features come from concrete cases rather than from a roadmap.

The naming convention is also consistent enough to be useful. Directories are named after what is being diagrammed, not after a feature, which means the example set doubles as a directory of chart and manifest shapes that have been exercised against the parser.

## Maintained steadily, with a version number that runs ahead

Activity on the repository is consistent rather than bursty. The last recorded push was 2026-09-21, and the three releases in view are v0.6.0 in September 2025, v0.7.0 in February 2026, and v0.8.0 in July 2026. That is roughly one release every four to five months, which for an infrastructure tool maintained alongside a hosted service is a healthy rhythm rather than a sign of abandonment. Eleven open issues on a repository of this size is low.

One detail needs care, and it is the kind of thing that trips people up. setup.py declares version 0.9.0 while the newest tagged release is v0.8.0. Those two facts are not in conflict, they describe different things: the package file records what master will become, and the tag records what has been cut. The practical implication is that installing from source gives you a version number higher than any release you can download, so bug reports that include a version string need to say which of the two was used. A third badge, the Socket one, still reads 0.6.0, which is simply a stale badge and says nothing about the current state.

The release notes also reveal the shape of the maintainership. v0.7.0 contains one academic item (a VISSOFT 2025 paper and slides), two contributed examples from named contributors, the addition of the hosted online service, the web app contributed by another named developer, and a werkzeug bump by dependabot. That is a project where a research group provides the core and outside contributors add coverage and features. The v0.8.0 notes are almost entirely first-party feature work, which is a shift in balance worth noting if you are following the project.

The CNCF Landscape badge is the other signal worth reading carefully. It confirms the tool is catalogued in the cloud native landscape, which is a form of legitimacy that matters for infrastructure software, and it does not mean the project is under CNCF governance or carries CNCF patent commitments. Nobody at CNCF is going to support this tool. The maintainer is one person at Inria Lille, and the 179 forks and 2,710 stars are the community's answer to that.

## Conclusion

KubeDiagrams earns its 2,710 stars by treating a cluster as something you can read rather than something you can only query. Accepting manifests, kustomizations, Helm charts, helmfiles and live state in one tool means the diagram can be regenerated from the same source of truth as the deployment, which is the only version of a cluster diagram that stays honest. The export list is what turns a picture into an artifact: an editable draw.io file and a Mermaid block can be committed and diffed, while PNG and SVG are for documents. The version numbering is the one loose end, since setup.py carries 0.9.0 while the newest tagged release is v0.8.0, so treat master as ahead of the releases rather than equal to them.

## FAQ

### What input formats does KubeDiagrams accept?

It accepts Kubernetes manifest files, kustomization files, Helm charts, helmfile descriptors, and actual cluster state. Accepting live cluster state is the distinguishing one, because it can render resources that no human wrote down, such as anything an operator or admission webhook created.

### Which output format should I use for a diagram that lives in a repository?

Mermaid, or editable draw.io if you want a diagram people can restructure. Both arrived in v0.8.0. A Mermaid fence sits next to the manifests in a Markdown file, so it can be regenerated and reviewed in a pull request, while a PNG committed on its own goes stale the moment the manifests change.

### Why do I need Helm charts if I already have manifests?

A chart and a manifest describe different things. A chart tells you what a release intends to create, including the many resources a single values file expands into, and helmfiles describe how several such releases relate to one another. Feeding the chart to KubeDiagrams shows the shape of the release as installed rather than as hand-written.

### Why does installing KubeDiagrams from pip fail on my machine?

It depends on pygraphviz, pinned to 1.14, which is a binding to a C library and needs Graphviz headers to build. Use the container image, or install Graphviz through your system package manager first. The Nix flake avoids the problem by pinning the whole graph including Graphviz.

## Sources

- [License: Apache-2.0](https://github.com/philippemerle/KubeDiagrams/blob/main/LICENSE)
- [philippemerle/KubeDiagrams on GitHub](https://github.com/philippemerle/KubeDiagrams)
- [Project website](https://kubediagrams.lille.inria.fr/)
- [README](https://github.com/philippemerle/KubeDiagrams/blob/main/README.md)
- [Releases](https://github.com/philippemerle/KubeDiagrams/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/philippemerle-kubediagrams
