Einen Namespace mit einem Dutzend Manifesten zu deployen ist leicht, ihn zu erklären schwer. Das YAML sagt dem API-Server alles, was er braucht, aber es sagt einer neuen Kollegin nicht, welcher Service vor welchem Deployment steht oder warum die Checkout-API mit Payments spricht. Dieser Guide ist eine wiederholbare Methode, um von Kubernetes-YAML zum Diagramm zu kommen, und zwar von Hand: Objekte inventarisieren, Beziehungen aus bestimmten Feldern lesen, entscheiden, was wegfällt, das Layout aufbauen und das Diagramm aktuell halten. Am Ende baust du das Ergebnis in Archboard mit dem Kubernetes-Pack nach.
Hier gibt es keine Magie: Du liest Felder und zeichnest Kanten. Genau darum geht es. Das Diagramm soll Absicht festhalten, und Absicht fügst du selbst hinzu.
Schritt 1: Objekte inventarisieren
Starte mit den gerenderten Manifesten, nicht mit den Templates. Wenn du Helm oder Kustomize nutzt, rendere zuerst, damit du siehst, was tatsächlich angewendet wird:
helm template shop ./charts/shop -f values-prod.yaml > rendered.yaml
kubectl kustomize overlays/prod > rendered.yaml
Läuft der Workload bereits, frag den Cluster und nenne die Kinds explizit:
kubectl get deploy,svc,ing,cm,secret,pvc,hpa,networkpolicy -n shop
Verlass dich nicht auf kubectl get all. Die Kategorie all umfasst Pods, Services, Deployments, ReplicaSets, StatefulSets, DaemonSets, Jobs, CronJobs und HPAs, lässt aber Ingress, ConfigMap, Secret, PVC, NetworkPolicy und ServiceAccount aus. Mehrere davon tragen genau die Kanten, die du zeichnen willst.
Für die Objekte mit Beziehungen holst du dir die vollständige Spec:
kubectl get ingress -n shop -o yaml
kubectl get svc -n shop -o custom-columns=NAME:.metadata.name,SELECTOR:.spec.selector
kubectl get pods -n shop --show-labels
Schreib das Inventar als flache Liste auf: Kind, Name, Namespace. Diese Liste ist deine Checkliste fürs Zeichnen.
Beispiel: Kubernetes-YAML zum Diagramm für einen Service
Ein kleines, aber typisches Set für einen Service im Namespace shop:
apiVersion: apps/v1
kind: Deployment
metadata:
name: checkout-api
namespace: shop
spec:
selector:
matchLabels:
app: checkout-api
template:
metadata:
labels:
app: checkout-api
tier: backend
spec:
containers:
- name: api
image: registry.example.com/shop/checkout-api:1.14.2
ports:
- containerPort: 8080
resources:
requests:
cpu: 250m
envFrom:
- configMapRef:
name: checkout-config
- secretRef:
name: checkout-db-credentials
---
apiVersion: v1
kind: Service
metadata:
name: checkout-api
namespace: shop
spec:
selector:
app: checkout-api
ports:
- port: 80
targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: shop
namespace: shop
spec:
ingressClassName: nginx
rules:
- host: shop.example.com
http:
paths:
- path: /api/checkout
pathType: Prefix
backend:
service:
name: checkout-api
port:
number: 80
---
apiVersion: v1
kind: ConfigMap
metadata:
name: checkout-config
namespace: shop
data:
PAYMENTS_URL: http://payments.shop.svc.cluster.local
LOG_LEVEL: info
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: checkout-api
namespace: shop
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: checkout-api
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Fünf Objekte, ein referenziertes, aber nicht gezeigtes Secret und eine Abhängigkeit, die sich in einem Konfigurationswert versteckt.
Schritt 2: Beziehungen in den Feldern finden
Kubernetes-Objekte verweisen selten per ID aufeinander. Sie verweisen per Name oder, häufiger, per Label. Labels und Selektoren sind der Klebstoff; die Kubernetes-Doku zu Labels und Selektoren lohnt sich vor dem Start noch einmal.
Geh die Liste in Traffic-Reihenfolge durch:
- Ingress → Service.
backend.service.nameundport.numberin jedem Pfad benennen den Service direkt. Host und Pfad werden zum Kantenlabel. - Service → Deployment. Ein Service nennt nie ein Deployment. Sein
spec.selectorpasst auf die Labels inspec.template.metadata.labelsdes Deployments. Hier passtapp: checkout-api, also zeichnest du die Kante. Im Zweifel zeigtkubectl get endpointslices -n shopdie Pod-Adressen, die der Service tatsächlich ausgewählt hat; keine Endpoints heißt, der Selektor trifft nichts oder die passenden Pods haben noch keine IP. - Deployment → ConfigMap / Secret / PVC. Schau auf
envFrom,env[].valueFromundvolumes[](configMap,secret,persistentVolumeClaim.claimName). - HPA → Deployment.
spec.scaleTargetRefbenennt das Ziel. - NetworkPolicy.
spec.podSelectorwählt die Pods, die sie schützt;ingress[].fromsagt, wer mit ihnen sprechen darf, undegress[].to, wohin sie sich verbinden dürfen. - Versteckte Abhängigkeiten.
PAYMENTS_URLzeigt aufpayments.shop.svc.cluster.local. Kein Feld verbindet Checkout mit Payments, aber der Aufruf ist real. Das ist die Kante, die Tools übersehen und die Menschen am dringendsten brauchen.
Vom YAML-Feld zum Diagrammelement
| YAML-Feld | Diagrammelement |
|---|---|
metadata.namespace |
Namespace-Frame um die Objekte |
kind: Deployment |
Deployment-Node, Replicas als Label |
Ingress rules[].host + paths[].path |
Ingress-Node, Host/Pfad an der ausgehenden Kante |
Ingress backend.service.name |
Kante Ingress → Service |
Service selector ↔ Template-labels |
Kante Service → Deployment |
Service port → targetPort |
Kantenlabel, z. B. 80 → 8080 |
envFrom / volumes[].configMap |
Kante ConfigMap → Deployment |
secretRef / volumes[].secret |
Kante Secret → Deployment |
persistentVolumeClaim.claimName |
Kante PVC → Deployment |
HPA scaleTargetRef |
HPA-Node neben dem Deployment, Label 3–10 |
NetworkPolicy podSelector, ingress[].from |
NetworkPolicy-Node neben dem geschützten Workload |
| Service-DNS-Namen in Konfigurationswerten | Kante zum abhängigen Service |
Schritt 3: Entscheiden, was wegfällt
Ein Diagramm, das alles zeigt, zeigt nichts. Regeln, die sich bewähren:
- Replica-Zahlen sind Labels, keine Boxen. Zeichne einen Deployment-Node und schreib
3–10 replicas (HPA)daran. Drei identische Pod-Boxen erzeugen Rauschen und sind falsch, sobald der HPA skaliert. - ReplicaSets ausblenden. Sie sind ein Implementierungsdetail von Rollouts.
- Pods nur zeichnen, wenn sie zählen, etwa bei eigenständigen Pods oder wenn du das Scheduling auf Nodes erklärst.
- Boilerplate zusammenfassen. ServiceAccounts, Standard-RBAC und Image-Pull-Secrets gehören meist in eine Notiz, nicht auf den Canvas.
- Behalten, was eine Entscheidung erklärt. Wenn eine NetworkPolicy der Grund ist, warum Checkout die Datenbank nicht direkt erreicht, bleibt sie drin.
Schritt 4: Layout aufbauen
Leg Nord-Süd-Traffic von links nach rechts an: Clients → Ingress → Service → Deployment → nachgelagerte Services und Datenspeicher. Konfiguration (ConfigMap, Secret) kommt unter den Workload, den sie versorgt; Skalierung (HPA) darüber. Zeichne jeden Namespace als Frame, damit namespaceübergreifende Aufrufe als Kanten auffallen, die einen Frame verlassen. Beschrifte Kanten mit Protokoll und Port, nicht nur mit Pfeilen.
Automatische Visualisierer vs. gezeichnetes Diagramm
Einige Tools im Ökosystem lesen den Live-Zustand des Clusters vom API-Server und stellen ihn als Graph dar. Sie sind exakt darin, was gerade läuft, und nützlich beim Debuggen. Der Trade-off: Sie zeigen jedes ReplicaSet, jeden Pod und jeden Endpoint, sie sehen keine Abhängigkeit, die in einer Umgebungsvariable steckt, und sie transportieren keine Absicht, etwa warum etwas existiert oder was geplant ist. Ein gezeichnetes Diagramm ist weniger vollständig und nützlicher für Onboarding, Design-Reviews und Incident-Kontext. Viele Teams nutzen beides.
Schritt 5: Aktuell halten
Ein Diagramm ist nur vertrauenswürdig, wenn es sich mit den Manifesten ändert:
- Leg die Diagrammdatei neben die Manifeste und reviewe sie im selben Pull Request.
- Ergänze eine Zeile im PR-Template: „Ändert sich ein Ingress, Service-Selektor, HPA oder eine NetworkPolicy? Diagramm aktualisieren.“
- Führ bei regelmäßigen Reviews die Inventar-Befehle aus Schritt 1 erneut aus und vergleiche mit der Zeichnung.
Das Beispiel in Archboard nachbauen
In Archboard zeichnest du auf Basis der Inventur, die du gerade erstellt hast, entscheidest, was ins Diagramm gehört, und nutzt Nodes, die den Kubernetes-Kinds entsprechen:
- Melde dich mit Google oder GitHub an und leg ein Diagramm an.
- Füge aus dem Kubernetes-Pack einen Namespace hinzu. Er wird als Frame gezeichnet; nenn ihn
shop. - Links außerhalb des Frames fügst du eine Core-Box oder einen Text für die Clients hinzu.
- Platziere im Frame Ingress, Service und Deployment von links nach rechts. Verbinde ihre Ports und beschrifte die Kanten mit
shop.example.com/api/checkoutund80 → 8080. - Füge ConfigMap und Secret unter dem Deployment hinzu und verbinde sie. Setz darüber einen HPA mit dem Label
3–10, CPU 70%. - Füge einen zweiten Service für
paymentshinzu und verbinde ihn vom Deployment aus, damit die versteckte Abhängigkeit sichtbar wird. - Leg einen Markdown-Block auf den Canvas, mit dem wichtigsten YAML-Ausschnitt in einem Fenced-Codeblock oder einer kurzen „Warum“-Notiz.
- Exportiere das Diagramm als JSON und committe es neben die Manifeste; exportiere SVG oder PNG für das README.
Diagramminhalt
- shop
- Clients
- checkout-api
- checkout-config
- checkout-db-credentials
- payments
- HTTPS
- shop.example.com/api/checkout
- 80 → 8080
- PAYMENTS_URL
- CPU 70%
- envFrom
Das passt in das Limit des Free-Plans von 15 Diagramm-Nodes pro Diagramm; Notizen und Texte zählen separat, bis zu 150. Als Referenz-Layouts öffnest du /examples/kubernetes-ingress-flow und /examples/kubernetes-microservices; Dieses Beispiel verwenden kopiert jedes der beiden in deinen Workspace, so wie In Archboard öffnen es für das Diagramm oben tut. Weitere Muster findest du unter /use-cases/kubernetes.
FAQ
Kann Archboard mein Kubernetes-YAML importieren?
Ja, als Ausgangspunkt. Füge gerenderte Manifeste oder die Ausgabe von kubectl get -o yaml in das kostenlose Tool Kubernetes-YAML zu Diagramm ein: Es zeichnet Namespaces als Rahmen und verbindet Ingress, Services, Workloads, ConfigMaps, Secrets und Volumes so, wie das YAML sie definiert. Zum Ansehen brauchst du kein Konto; mit einem kostenlosen Konto öffnest du das Ergebnis in Archboard als neues Diagramm oder fügst es im Editor mit Aus YAML importieren… zu einem bestehenden hinzu. Es bleibt nicht mit deinem YAML synchron, daher helfen die Schritte in diesem Beitrag weiterhin, das Ergebnis zu prüfen und aktuell zu halten.
Soll ich jeden Pod zeichnen? Meist nicht. Ein Deployment-Node mit Replica-Label ist klarer und bleibt korrekt, wenn der HPA skaliert.
Was ist mit Helm-Charts?
Rendere sie zuerst mit helm template und zeichne die Ausgabe, nicht die Templates.
Wie finde ich Abhängigkeiten, die in keinem Feld stehen?
Durchsuche ConfigMaps und env-Werte nach svc.cluster.local und anderen Hostnamen und bestätige sie mit den Service-Ownern.