从 Kubernetes YAML 到架构图

一步步把 Kubernetes YAML 转成架构图:盘点对象、追踪选择器和引用、去掉噪音,并让图保持最新。

2026/10/16

从 Kubernetes YAML 到架构图

一个包含十几份清单的 namespace,部署起来很容易,讲清楚却很难。YAML 告诉 API 服务器它需要的一切,却不会告诉新同事哪个 Service 位于哪个 Deployment 前面,也不会说明 checkout API 为什么要调用 payments。本文给出一套可重复的方法,手工把 Kubernetes YAML 转成架构图:盘点对象、从特定字段读出关系、决定省略什么、完成布局,并让图保持最新。最后,我们会在 Archboard 中用 Kubernetes 节点包重建这张图。

这里没有魔法:你读取字段,画出连线。这正是重点。图应该表达意图,而意图需要由你来补充。

第 1 步:盘点对象

从渲染后的清单开始,而不是模板。如果你使用 Helm 或 Kustomize,先渲染,才能看到真正被应用的内容:

helm template shop ./charts/shop -f values-prod.yaml > rendered.yaml
kubectl kustomize overlays/prod > rendered.yaml

如果工作负载已经在运行,就直接询问集群,并明确列出资源类型:

kubectl get deploy,svc,ing,cm,secret,pvc,hpa,networkpolicy -n shop

不要依赖 kubectl get all。all 类别包括 Pod、Service、Deployment、ReplicaSet、StatefulSet、DaemonSet、Job、CronJob 和 HPA,但不包括 Ingress、ConfigMap、Secret、PVC、NetworkPolicy 和 ServiceAccount。其中好几个恰恰承载着你要画的连线。

对承载关系的对象,取出完整的 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

把盘点结果写成一份扁平清单:类型、名称、namespace。这份清单就是你画图时的检查表。

示例:把一个服务的 Kubernetes YAML 转成图

下面是 shop namespace 中一个服务的小型但典型的配置:

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

五个对象,一个被引用但未展示的 Secret,以及一个藏在配置值里的依赖。

第 2 步:在字段中找出关系

Kubernetes 对象很少通过 ID 互相引用。它们通过名称引用,更常见的是通过 label。label 和选择器就是粘合剂;开始之前,值得重读一遍 Kubernetes 关于 labels 和选择器的文档。

按流量顺序遍历清单:

  • Ingress → Service。 每个 path 中的 backend.service.name 和 port.number 直接指明 Service。host 和 path 成为连线的标签。
  • Service → Deployment。 Service 从不直接点名 Deployment。它的 spec.selector 与 Deployment 的 spec.template.metadata.labels 中的 label 匹配。这里 app: checkout-api 匹配,所以画出这条连线。如果不确定,kubectl get endpointslices -n shop 会显示 Service 实际选中的 Pod 地址;没有 endpoint 说明选择器什么都没匹配到,或者匹配到的 Pod 还没有 IP。
  • Deployment → ConfigMap / Secret / PVC。 查看 envFrom、env[].valueFrom 和 volumes[](configMap、secret、persistentVolumeClaim.claimName)。
  • HPA → Deployment。 spec.scaleTargetRef 指明目标。
  • NetworkPolicy。 spec.podSelector 选出它保护的 Pod;ingress[].from 说明谁可以与它们通信,egress[].to 说明它们可以连接到哪里。
  • 隐藏的依赖。 PAYMENTS_URL 指向 payments.shop.svc.cluster.local。没有任何字段把 checkout 和 payments 连起来,但这个调用真实存在。这正是工具会漏掉、而人最需要的那条连线。

从 YAML 字段到图元素

YAML 字段 图元素
metadata.namespace 包住对象的 Namespace 框
kind: Deployment Deployment 节点,副本数作为标签
Ingress rules[].host + paths[].path Ingress 节点,出向连线上标注 host/path
Ingress backend.service.name 连线 Ingress → Service
Service selector ↔ 模板 labels 连线 Service → Deployment
Service port → targetPort 连线标签,例如 80 → 8080
envFrom / volumes[].configMap 连线 ConfigMap → Deployment
secretRef / volumes[].secret 连线 Secret → Deployment
persistentVolumeClaim.claimName 连线 PVC → Deployment
HPA scaleTargetRef Deployment 旁的 HPA 节点,标签 3–10
NetworkPolicy podSelector、ingress[].from 所保护工作负载旁的 NetworkPolicy 节点
配置值中的 Service DNS 名称 指向被依赖 Service 的连线

第 3 步:决定省略什么

什么都画的图,等于什么都没说。以下规则很实用:

  • 副本数是标签,不是方框。 只画一个 Deployment 节点,并在上面写 3–10 replicas (HPA)。三个一模一样的 Pod 方框只会增加噪音,而且 HPA 一扩缩就不再准确。
  • 隐藏 ReplicaSet。 它们只是滚动发布的实现细节。
  • 只在必要时画 Pod,例如独立的 Pod,或者在解释如何调度到 Node 时。
  • 折叠样板内容。 ServiceAccount、默认 RBAC 和镜像拉取用的 Secret,通常放在一条注释里,而不是画在画布上。
  • 保留能解释决策的内容。 如果 checkout 无法直接访问数据库是因为某个 NetworkPolicy,那它就应该留在图上。

第 4 步:完成布局

把南北向流量从左到右排列:客户端 → Ingress → Service → Deployment → 下游 Service 和数据存储。配置(ConfigMap、Secret)放在它所服务的工作负载下方,扩缩(HPA)放在上方。把每个 namespace 画成一个框,这样跨 namespace 的调用就会以“穿出框”的连线形式凸显出来。连线上要标注协议和端口,而不只是箭头。

自动可视化工具与手绘架构图

生态中有些工具会从 API 服务器读取集群的实时状态,并把它渲染成图。它们对“此刻正在运行什么”非常准确,排障时很有用。代价是:它们会显示每一个 ReplicaSet、Pod 和 endpoint,看不到藏在环境变量里的依赖,也无法表达意图,比如某个组件为什么存在、接下来计划做什么。手绘的图不那么完整,但对新人上手、设计评审和故障处理时的背景说明更有用。很多团队两者并用。

第 5 步:保持最新

只有和清单一起变化的图才值得信任:

  • 把图文件放在清单旁边,在同一个 pull request 中评审。
  • 在 PR 模板里加一行:“是否修改了 Ingress、Service 选择器、HPA 或 NetworkPolicy?请更新架构图。”
  • 在定期评审时重新运行第 1 步的盘点命令,并与图进行对比。

在 Archboard 中重建示例

在 Archboard 中,你可以根据刚刚整理好的清单来画图,决定哪些内容应该出现在图上,并使用与 Kubernetes kind 对应的节点:

  1. 使用 Google 或 GitHub 登录,并新建一张图。
  2. 从 Kubernetes 节点包中添加一个 Namespace。它以框的形式呈现,命名为 shop。
  3. 在框外左侧,添加一个 Core 的 Box 或 Text 表示客户端。
  4. 在框内从左到右放置 Ingress、Service 和 Deployment。连接它们的端口,并给连线加上 shop.example.com/api/checkout 和 80 → 8080 的标签。
  5. 在 Deployment 下方添加 ConfigMap 和 Secret 并连接。在上方添加一个标签为 3–10, CPU 70% 的 HPA。
  6. 为 payments 添加第二个 Service,并从 Deployment 连过去,让隐藏的依赖变得可见。
  7. 在画布上放一个 Markdown 块,用围栏代码块写入关键的 YAML 片段,或写一段简短的“为什么”说明。
  8. 把图导出为 JSON,并提交到清单旁边;再导出 SVG 或 PNG 用于 README。
shop namespace 的 Kubernetes 架构图:客户端通过 HTTPS 访问 shop-ingress,流量路由到 checkout 的 Service 和 Deployment;该 Deployment 由 HPA 扩缩容,通过 ConfigMap 和 Secret 配置,并调用 payments Service。

9 个组件 · 7 个连接

在 Archboard 中打开
图表内容
  • shop
  • Clients
  • checkout-api
  • checkout-config
  • checkout-db-credentials
  • payments
  • HTTPS
  • shop.example.com/api/checkout
  • 80 → 8080
  • PAYMENTS_URL
  • CPU 70%
  • envFrom
本文中的 shop namespace:Ingress → Service → Deployment,以及 HPA、ConfigMap、Secret 和隐藏的 payments 依赖。

这个示例在 Free 方案每张图 15 个图表节点的限制之内;便签和文本单独计算,最多 150 个。参考布局可以打开 /examples/kubernetes-ingress-flow 和 /examples/kubernetes-microservices;使用此示例 可以把其中任意一个复制到你的工作区,就像上面这张图的 在 Archboard 中打开 一样。更多模式见 /use-cases/kubernetes。

常见问题

Archboard 能导入我的 Kubernetes YAML 吗? 可以,作为起点。把渲染后的清单或 kubectl get -o yaml 的输出粘贴到免费的Kubernetes YAML 转图表工具:它会把命名空间画成框,并按 YAML 中的定义连接 Ingress、Service、工作负载、ConfigMap、Secret 和卷。查看无需账号;使用免费账号即可在 Archboard 中将结果作为新图表打开,或在编辑器中使用 从 YAML 导入… 将其添加到现有图表中。它不会与你的 YAML 保持同步,因此本文的步骤仍可用于检查结果并保持图表最新。

每个 Pod 都要画出来吗? 通常不需要。一个带副本数标签的 Deployment 节点更清晰,而且在 HPA 扩缩时依然准确。

Helm chart 怎么办? 先用 helm template 渲染,然后画渲染结果,而不是模板。

如何找出没有出现在任何字段里的依赖? 在 ConfigMap 和 env 值中搜索 svc.cluster.local 等主机名,然后与各服务的负责人确认。

免费开始 — 1 个席位,无需信用卡。

相关文章

← 返回博客

一分钟打开画布

使用 Google 或 GitHub 登录。单席位免费,团队加入后再升级。