这是本节的多页打印视图。 点击此处打印.

返回本页常规视图.

文档样式概述

本节的主题是提供有关写作风格、内容格式和组织以及如何使用 特定于 Kubernetes 文档的 Hugo 定制代码的指导。

1 - 文档内容指南

本页包含 Kubernetes 文档的一些指南。

如果你不清楚哪些事情是可以做的,请加入到 Kubernetes Slack#sig-docs 频道提问! 你可以在 https://slack.k8s.io 注册到 Kubernetes Slack。

关于为 Kubernetes 文档创建新内容的更多信息, 可参考样式指南

概述

Kubernetes 网站(包括其文档)源代码位于 kubernetes/website 仓库中。

kubernetes/website/content/<语言代码>/docs 目录下, 绝大多数 Kubernetes 文档都是特定于 Kubernetes 项目的。

可以发布的内容

只有当以下条件满足时,Kubernetes 文档才允许第三方项目的内容:

  • 内容所描述的软件在 Kubernetes 项目内
  • 内容所描述的软件不在 Kubernetes 项目内,却是让 Kubernetes 正常工作所必需的
  • 内容是被 kubernetes.io 域名收编的,或者是其他位置的标准典型内容

第三方内容

Kubernetes 文档包含 Kubernetes 项目下的多个项目的应用示例。 这里的 Kubernetes 项目指的是 KubernetesKubernetes SIGs GitHub 组织下的那些项目。

链接到 Kubernetes 项目中活跃的内容是一直允许的。

Kubernetes 需要某些第三方内容才能正常工作。例如容器运行时(containerd、CRI-O、Docker)、 联网策略(CNI 插件)、 Ingress 控制器 以及日志等。

只有对应的第三方开源软件(OSS)是运行 Kubernetes 所必需的, 才可以在文档中包含指向这些 Kubernetes 项目之外的软件的链接。

双重来源的内容

只要有可能,Kubernetes 文档就应该指向标准典型的信息源而不是直接托管双重来源的内容。

双重来源的内容需要双倍(甚至更多)的投入才能维护,而且通常很快就会变得停滞不前。

更多信息

如果你对允许出现的内容有疑问,请加入到 Kubernetes Slack#sig-docs 频道提问!

接下来

2 - 文档样式指南

本页讨论 Kubernetes 文档的样式指南。 这些仅仅是指南而不是规则。 你可以自行决定,且欢迎使用 PR 来为此文档提供修改意见。

关于为 Kubernetes 文档贡献新内容的更多信息, 可以参考文档内容指南

样式指南的变更是 SIG Docs 团队集体决定。 如要提议更改或新增条目,请先将其添加到下一次 SIG Docs 例会的议程表上,并按时参加会议讨论。

语言

Kubernetes 文档已经被翻译为多个语种 (参见 本地化 README)。

本地化 Kubernetes 文档描述了如何为一种新的语言提供本地化文档。

英语文档使用美国英语的拼写和语法。

文档格式标准

对 API 对象使用大写驼峰式命名法

当你与指定的 API 对象进行交互时, 使用大写驼峰式命名法, 也被称为帕斯卡拼写法(PascalCase)。 你可以在 API 参考中看到不同的大小写形式,例如 "configMap"。 在编写通用文档时,最好使用大写驼峰形式,将之称作 "ConfigMap"。

通常在讨论 API 对象时,使用 句子式大写

下面的例子关注的是大小写问题。关于如何格式化 API 对象名称的更多信息, 可参考相关的代码风格指南。

使用 Pascal 风格大小写来给出 API 对象的约定
可以不可以
该 HorizontalPodAutoscaler 负责...该 Horizontal pod autoscaler 负责...
每个 PodList 是一个 Pod 组成的列表。每个 Pod List 是一个由 Pod 组成的列表。
该 Volume 对象包含一个 hostPath 字段。此卷对象包含一个 hostPath 字段。
每个 ConfigMap 对象都是某个名字空间的一部分。每个 configMap 对象是某个名字空间的一部分。
要管理机密数据,可以考虑使用 Secret API。要管理机密数据,可以考虑使用秘密 API。

在占位符中使用尖括号

用尖括号表示占位符,让读者知道占位符表示的是什么。例如:

显示有关 Pod 的信息:

kubectl describe pod <Pod 名称> -n <名字空间>

如果名字空间被忽略,默认为 default,你可以省略 '-n' 参数。

用粗体字表现用户界面元素

以粗体表示用户界面元素
可以不可以
点击 Fork点击 "Fork"。
选择 Other选择 "Other"。

定义或引入新术语时使用斜体

新术语约定
可以不可以
每个 集群 是一组节点 ...每个“集群”是一组节点 ...
这些组件构成了 控制面这些组件构成了 控制面

使用代码样式表现文件名、目录和路径

文件名、目录和路径约定
可以不可以
打开 envars.yaml 文件打开 envars.yaml 文件
进入到 /docs/tutorials 目录进入到 /docs/tutorials 目录
打开 /_data/concepts.yaml 文件打开 /_data/concepts.yaml 文件

在引号内使用国际标准标点

标点符号约定
可以不可以
事件记录中都包含对应的“stage”。事件记录中都包含对应的“stage。”
此副本称作一个“fork”。此副本称作一个“fork。”

行间代码格式

为行间代码、命令使用代码样式

对于 HTML 文档中的行间代码,使用 <code> 标记。在 Markdown 文档中,使用反引号(`)。 然而,StatefulSet 或 ConfigMap 这些 API 类别是直接书写的(不用反引号);这样允许使用表示所有格的撇号。

行间代码、命令和 API 对象约定
可以不可以
kubectl run 命令会创建一个 Pod。"kubectl run" 命令会创建一个 Pod。
每个节点上的 kubelet 都会获得一个 Lease…每个节点上的 kubelet 都会获得一个 Lease
一个 PersistentVolume 代表持久存储…一个 PersistentVolume 代表持久存储…
CustomResourceDefinition 的 .spec.group 字段…CustomResourceDefinition.spec.group 字段…
在声明式管理中,使用 kubectl apply在声明式管理中,使用 "kubectl apply"。
用三个反引号来(```)标示代码示例用其他语法来标示代码示例。
使用单个反引号来标示行间代码。例如:var example = true使用两个星号(**)或者一个下划线(_)来标示行间代码。例如:var example = true
在多行代码块之前和之后使用三个反引号标示隔离的代码块。使用多行代码块来创建示意图、流程图或者其他表示。
使用符合上下文的有意义的变量名。使用诸如 'foo'、'bar' 和 'baz' 这类无意义且无语境的变量名。
删除代码中行尾空白。在代码中包含行尾空白,因为屏幕抓取工具通常也会抓取空白字符。

为对象字段名和名字空间使用代码风格

对象字段名约定
可以不可以
在配置文件中设置 replicas 字段的值。在配置文件中设置 "replicas" 字段的值。
exec 字段的值是一个 ExecAction 对象。"exec" 字段的值是一个 ExecAction 对象。
kube-system 名字空间中以 DaemonSet 形式运行此进程。在 kube-system 名字空间中以 DaemonSet 形式运行此进程。

用代码样式书写 Kubernetes 命令工具和组件名

Kubernetes 命令工具和组件名
可以不可以
kubelet 维持节点稳定性。kubelet 负责维护节点稳定性。
kubectl 处理 API 服务器的定位和身份认证。kubectl 处理 API 服务器的定位和身份认证。
使用该证书运行进程 kube-apiserver --client-ca-file=FILENAME使用证书运行进程 kube-apiserver --client-ca-file=FILENAME。

用工具或组件名称开始一句话

工具或组件名称使用约定
可以不可以
The kubeadm tool bootstraps and provisions machines in a cluster.kubeadm tool bootstraps and provisions machines in a cluster.
The kube-scheduler is the default scheduler for Kubernetes.kube-scheduler is the default scheduler for Kubernetes.

尽量使用通用描述而不是组件名称

组件名称与通用描述
可以不可以
Kubernetes API 服务器提供 OpenAPI 规范。apiserver 提供 OpenAPI 规范。
聚合 API 是下级 API 服务器。聚合 API 是下级 APIServer。

使用普通样式表达字符串和整数字段值

对于字符串或整数,使用正常样式,不要带引号。

字符串和整数字段值约定
可以不可以
imagePullPolicy 设置为 Always。imagePullPolicy 设置为 "Always"。
image 设置为 nginx:1.16。image 设置为 nginx:1.16
replicas 字段值设置为 2。replicas 字段值设置为 2

然而,在读者可能会将某些值与 API 类别混淆时,请考虑为这些值添加引号。

引用 Kubernetes API 资源

本节讨论我们如何在文档中引用 API 资源。

有关 “资源” 的阐述

Kubernetes 使用单词 resource 一词来指代 API 资源。 例如,URL 路径 /apis/apps/v1/namespaces/default/deployments/my-app 表示 "default" 名字空间中名为 "my-app" 的 Deployment。 在 HTTP 的术语中,名字空间是一个资源, 就像所有 Web URL 都标识一个资源。

Kubernetes 文档在讨论 CPU 和内存请求以及限制也使用“资源(resource)”一词。 将 API 资源称为 "API 资源" 往往是一个好的做法;这有助于避免与 CPU 和内存资源或其他类别的资源混淆。

如果你使用资源名称的小写复数形式,例如 deploymentsconfigmaps, 请提供额外的书面上下文来帮助读者理解你的用意。 如果你使用术语时所处的上下文中使用驼峰编码(UpperCamelCase)的名称也可行,且术语存在歧义的风险, 应该考虑使用 UpperCamelCase 形式的 API 类别。

何时使用 Kubernetes API 术语

不同 Kubernetes API 术语的说明如下:

  • API 类别 :API URL 中使用的名称(如 podsnamespaces)。 API 类别有时也称为 资源类型
  • API 资源 :API 类别的单个实例(如 podsecret
  • 对象 :作为 “意向记录” 的资源。对象是集群特定部分的期望状态, 该状态由 Kubernetes 控制平面负责维护。 Kubernetes API 中的所有对象也都是资源。

为了清晰起见,在 Kubernetes 文档中引用 API 资源时可以使用 "资源" 或 "对象"。 例如:写成 "Secret 对象" 而不是 "Secret"。 如果仅大写就能明确含义,那么无需添加额外的单词。

当修改有助于避免误解时,那就考虑修改表述。 一个常见的情况是当你想要某个句子以 "Secret" 这种 API 类别开头时; 因为英语和其他几种语言会对句首的第一个字母大写,所以读者无法确定你说的是 API 类别还是一般概念。 此时重新构词有助于让句子更清晰。

API 资源名称

始终使用大写驼峰式命名法 (也称为 PascalCase)来表达 API 资源名称。不要使用代码格式书写 API 类别。

不要将 API 对象的名称切分成多个单词。 例如请使用 PodTemplateList 而非 Pod Template List。

有关 PascalCase 和代码格式的更多信息, 请查看对 API 对象使用大写驼峰式命名法针对内嵌代码、命令与 API 对象使用代码样式

有关 Kubernetes API 术语的更多信息, 请查看 Kubernetes API 术语的相关指南。

代码段格式

不要包含命令行提示符

命令行提示符约定
可以不可以
kubectl get pods$ kubectl get pods

将命令和输出分开

例如:

验证 Pod 已经在你所选的节点上运行:

kubectl get pods --output=wide

输出类似于:

NAME     READY     STATUS    RESTARTS   AGE    IP           NODE
nginx    1/1       Running   0          13s    10.200.0.4   worker0

为 Kubernetes 示例给出版本

代码示例或者配置示例如果包含版本信息,应该与对应的文字描述一致。

如果所给的信息是特定于具体版本的,需要在 任务模板教程模板prerequisites 小节定义 Kubernetes 版本。 页面保存之后,prerequisites 小节会显示为开始之前

如果要为任务或教程页面指定 Kubernetes 版本,可以在文件的前言部分包含 min-kubernetes-server-version 信息。

如果示例 YAML 是一个独立文件,找到并审查包含该文件的主题页面。 确认使用该独立 YAML 文件的主题都定义了合适的版本信息。 如果独立的 YAML 文件没有在任何主题中引用,可以考虑删除该文件, 而不是继续更新它。

例如,如果你在编写一个教程,与 Kubernetes 1.8 版本相关。那么你的 Markdown 文件的文件头应该开始起来像这样:

---
title: <教程标题>
min-kubernetes-server-version: v1.8
---

在代码和配置示例中,不要包含其他版本的注释信息。 尤其要小心不要在示例中包含不正确的注释信息,例如:

apiVersion: v1 # 早期版本使用...
kind: Pod
...

Kubernetes.io 术语列表

以下特定于 Kubernetes 的术语和词汇在使用时要保持一致性。

Kubernetes.io 词汇表
术语用法
KubernetesKubernetes 的首字母要保持大写。
DockerDocker 的首字母要保持大写。
SIG DocsSIG Docs 是正确拼写形式,不要用 SIG-DOCS 或其他变体。
On-premisesOn-premises 或 On-prem 而不是 On-premise 或其他变体。
cloud nativeCloud native 或 cloud native 适合句子结构,而不是 cloud-native 或 Cloud Native。
open sourceOpen source 或 open source 适合句子结构,而不是 open-source 或 Open Source。

短代码(Shortcodes)

Hugo 短代码(Shortcodes) 有助于创建比较漂亮的展示效果。我们的文档支持三个不同的这类短代码。 注意 {{< note >}}小心 {{< caution >}}警告 {{< warning >}}

  1. 将要突出显示的文字用短代码的开始和结束形式包围。

  2. 使用下面的语法来应用某种样式:

    {{< note >}}
    不需要前缀;短代码会自动添加前缀(注意:、小心:等)
    {{< /note >}}
    

    输出的样子是:

注释(Note)

使用短代码 {{< note >}} 来突出显示某种提示或者有助于读者的信息。

例如:

{{< note >}}
在这类短代码中仍然 _可以_ 使用 Markdown 语法。
{{< /note >}}

输出为:

你可以在列表中使用 {{< note >}}

1. 在列表中使用 note 短代码

1. 带嵌套 note 的第二个条目

   {{< note >}}
   警告、小心和注意短代码可以嵌套在列表中,但是要缩进四个空格。
   参见[常见短代码问题](#common-shortcode-issues)。
   {{< /note >}}

1. 列表中第三个条目

1. 列表中第四个条目

其输出为:

  1. 在列表中使用 note 短代码

  2. 带嵌套 note 的第二个条目

  1. 列表中第三个条目

  2. 列表中第四个条目

小心(Caution)

使用 {{< caution >}} 短代码来引起读者对某段信息的重视,以避免遇到问题。

例如:

{{< caution >}}
此短代码样式仅对标记之上的一行起作用。
{{< /caution >}}

其输出为:

警告(Warning)

使用 {{< warning >}} 来表明危险或者必须要重视的一则信息。

例如:

{{< warning >}}
注意事项
{{< /warning >}}

其输出为:

常见的短代码问题

编号列表

短代码会打乱编号列表的编号,除非你在信息和标志之前都缩进四个空格。

例如:

1. 预热到 350˚F
1. 准备好面糊,倒入烘烤盘
    {{< note >}}给盘子抹上油可以达到最佳效果。{{< /note >}}
1. 烘烤 20 到 25 分钟,或者直到满意为止。

其输出结果为:

  1. 预热到 350˚F
  2. 准备好面糊,倒入烘烤盘
  3. 烘烤 20 到 25 分钟,或者直到满意为止。

Include 语句

如果短代码出现在 include 语境中,会导致网站无法构建。 你必须将他们插入到上级文档中,分别将开始标记和结束标记插入到 include 语句之前和之后。 例如:

{{< note >}}
{{< include "task-tutorial-prereqs.md" >}}
{{< /note >}}

Markdown 元素

换行

使用单一换行符来隔离块级内容,例如标题、列表、图片、代码块以及其他元素。 这里的例外是二级标题,必须有两个换行符。 二级标题紧随一级标题(或标题),中间没有段落或文字。

两行的留白有助于在代码编辑器中查看整个内容的结构组织。

适当时在 Markdown 文档中手动换行。由于 git 工具和 GitHub 网站是逐行生成文件差异的,手动换行可以帮助审阅者轻松找到 PR 中所做的更改并提供反馈。 它还可以帮助下游本地化团队,使其按行跟踪上游更改。例如,换行可以发生在句子或标点符号的末尾。 一个例外是 Markdown 链接或短代码应位于一行中。

大标题和小标题

访问文档的读者可能会使用屏幕抓取程序或者其他辅助技术。 屏幕抓取器是一种线性输出设备, 它们每次输出页面上的一个条目。 如果页面上内容过多,你可以使用标题来为页面组织结构。 页面的良好结构对所有读者都有帮助,使得他们更容易浏览或者过滤感兴趣的内容。

标题约定
可以不可以
更新页面或博客在前言部分中的标题。使用一级标题。因为 Hugo 会自动将页面前言部分的标题转化为一级标题。
使用编号的标题以便内容组织有一个更有意义的结构。使用四级到六级标题,除非非常有必要这样。如果你要编写的内容有非常多细节,可以尝试拆分成多个不同页面。
在非博客内容页面中使用井号(#使用下划线 ---=== 来标记一级标题。
页面正文中的小标题采用正常语句的大小写。例如:Extend kubectl with plugins页面正文中的小标题采用首字母大写的大标题式样。例如:Extend Kubectl With Plugins
头部的页面标题采用大标题的式样。例如:title: Kubernetes API Server Bypass Risks头部的页面标题采用正常语句的大小写。例如不要使用 title: Kubernetes API server bypass risks
将相关链接放在正文中。在标题中包含超链接(<a href=""></a>)。
使用井号或哈希符号(#)表示标题。使用粗体文本或其他指示符来拆分段落。

段落

段落约定
可以不可以
尝试不要让段落超出 6 句话。用空格来缩进第一段。例如,段落前面的三个空格⋅⋅⋅会将段落缩进。
使用三个连字符(---)来创建水平线。使用水平线来分隔段落内容。例如,在故事中切换场景或者在上下文中切换主题。使用水平线来装饰页面。
链接约定
可以不可以
插入超级链接时给出它们所链接到的目标内容的上下文。例如:你的机器上某些端口处于开放状态。参见检查所需端口了解更详细信息。使用“点击这里”等模糊的词语。例如:你的机器上某些端口处于打开状态。参见这里了解详细信息。
编写 Markdown 风格的链接:[链接文本](URL)。例如:[Hugo 短代码](/zh-cn/docs/contribute/style/hugo-shortcodes/#table-captions),输出是 Hugo 短代码编写 HTML 风格的超级链接:<a href="/media/examples/link-element-example.css" target="_blank">访问我们的教程!</a>,或者创建会打开新 Tab 页签或新窗口的链接。例如:[网站示例](https://example.com){target="_blank"}

列表

将一组相互关联的内容组织到一个列表中,以便表达这些条目彼此之间有先后顺序或者某种相互关联关系。 当屏幕抓取器遇到列表时,无论该列表是否有序,它会告知用户存在一组枚举的条目。 用户可以使用箭头键来上下移动,浏览列表中条目。 网站导航链接也可以标记成列表条目,因为说到底他们也是一组相互关联的链接而已。

  • 如果列表中一个或者多个条目是完整的句子,则在每个条目末尾添加句号。 出于一致性考虑,一般要么所有条目要么没有条目是完整句子。

  • 在编号列表中,使用数字 1(1.)。

  • 对非排序列表,使用加号(+)、星号(*)、或者减号(-)。

  • 在每个列表之后留一个空行。

  • 对于嵌套的列表,相对缩进四个空格(例如,⋅⋅⋅⋅)。

  • 列表条目可能包含多个段落。每个后续段落都要缩进或者四个空格或者一个制表符。

表格

数据表格的语义用途是呈现表格化的数据。 用户可以快速浏览表格,但屏幕抓取器需要逐行地处理数据。 表格标题可以用来给数据表提供一个描述性的标题。 辅助技术使用 HTML 表格标题元素来在页面结构中辨识表格内容。

内容最佳实践

本节包含一些建议的最佳实践,用来开发清晰、明确一致的文档内容。

使用现在时态

使用现在时态
可以不可以
此命令启动代理。此命令将启动一个代理。

例外:如果需要使用过去时或将来时来表达正确含义时,是可以使用的。

使用主动语态

使用主动语态
可以不可以
你可以使用浏览器来浏览 API。API 可以被使用浏览器来浏览。
YAML 文件给出副本个数。副本个数是在 YAML 文件中给出的。

例外:如果主动语态会导致句子很难构造时,可以使用被动语态。

使用简单直接的语言

使用简单直接的语言。避免不必要的短语,例如说“请”。

使用简单直接语言
可以不可以
要创建 ReplicaSet,...如果你想要创建 ReplicaSet,...
参看配置文件。请自行查看配置文件。
查看 Pod。使用下面的命令,我们将会看到 Pod。

将读者称为“你”

将读者称为“你”
可以不可以
你可以通过 ... 创建一个 Deployment。通过...我们将创建一个 Deployment。
在前面的输出中,你可以看到...在前面的输出中,我们可以看到...

避免拉丁短语

尽可能使用英语而不是拉丁语缩写。

避免拉丁语短语
可以不可以
例如,...e.g., ...
也就是说,...i.e., ...

例外:使用 etc. 表示等等。

应避免的模式

避免使用“我们”

在句子中使用“我们”会让人感到困惑,因为读者可能不知道这里的“我们”指的是谁。

要避免的模式
可以不可以
版本 1.4 包含了 ...在 1.4 版本中,我们添加了 ...
Kubernetes 为 ... 提供了一项新功能。我们提供了一项新功能...
本页面教你如何使用 Pod。在本页中,我们将会学到如何使用 Pod。

避免使用俚语或行话

对某些读者而言,英语是其外语。 避免使用一些俚语或行话有助于他们更方便的理解内容。

避免使用俚语或行话
可以不可以
Internally, ...Under the hood, ...
Create a new cluster.Turn up a new cluster.

避免关于将来的陈述

要避免对将来作出承诺或暗示。如果你需要讨论的是 Alpha 功能特性, 可以将相关文字放在一个单独的标题下,标识为 Alpha 版本信息。

此规则的一个例外是对未来版本中计划移除的已废弃功能选项的文档。 此类文档的例子之一是已弃用 API 迁移指南

避免使用很快就会过时的表达

避免使用一些很快就会过时的陈述,例如“目前”、“新的”。 今天而言是新的功能,过了几个月之后就不再是新的了。

避免使用很快过时的表达
可以不可以
在版本 1.4 中,...在当前版本中,...
联邦功能特性提供 ...新的联邦功能特性提供 ...

避免使用隐含用户对某技术有一定理解的词汇

避免使用“只是”、“仅仅”、“简单”、“很容易地”、“很简单”这类词汇。 这些词并没有提升文档的价值。

避免无意义词汇的注意事项
可以不可以
在 ... 中包含一个命令只需要在... 中包含一个命令
运行容器 ...只需运行该容器...
你可以移除...你可以很容易地移除...
这些步骤...这些简单的步骤...

编辑器配置文件

Kubernetes 项目维护一个 EditorConfig 文件,用于设置文本编辑器(例如 VS Code)中的常见样式首选项。 如果你想确保你的贡献与项目的其余部分样式保持一致,则可以使用此文件。 要查看该文件,请参阅项目仓库根目录的 .editorconfig

接下来

3 - 图表指南

本指南为你展示如何创建、编辑和分享基于 Mermaid JavaScript 库的图表。 Mermaid.js 允许你使用简单的、类似于 Markdown 的语法来在 Markdown 文件中生成图表。 你也可以使用 Mermaid 来创建 .svg.png 图片文件,将其添加到你的文档中。

本指南的目标受众是所有希望了解 Mermaid 的用户,以及那些想了解如何创建图表并将其添加到 Kubernetes 文档中的用户。

图 1 概要介绍的是本节所涉及的话题。

flowchart LR subgraph m[Mermaid.js] direction TB S[ ]-.- C[使用 Markdown 来
构造图表] --> D[在线
编辑器] end A[为什么图表
很有用] --> m m --> N[3 种创建
图表的方法] N --> T[示例] T --> X[样式
与标题] X --> V[提示] classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; classDef spacewhite fill:#ffffff,stroke:#fff,stroke-width:0px,color:#000 class A,C,D,N,X,m,T,V box class S spacewhite %% you can hyperlink Mermaid diagram nodes to a URL using click statements click A "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgc3ViZ3JhcGggbVtNZXJtYWlkLmpzXVxuICAgIGRpcmVjdGlvbiBUQlxuICAgICAgICBTWyBdLS4tXG4gICAgICAgIENbYnVpbGQ8YnI-ZGlhZ3JhbXM8YnI-d2l0aCBtYXJrZG93bl0gLS0-XG4gICAgICAgIERbb24tbGluZTxicj5saXZlIGVkaXRvcl1cbiAgICBlbmRcbiAgICBBW1doeSBhcmUgZGlhZ3JhbXM8YnI-dXNlZnVsP10gLS0-IG1cbiAgICBtIC0tPiBOWzMgeCBtZXRob2RzPGJyPmZvciBjcmVhdGluZzxicj5kaWFncmFtc11cbiAgICBOIC0tPiBUW0V4YW1wbGVzXVxuICAgIFQgLS0-IFhbU3R5bGluZzxicj5hbmQ8YnI-Y2FwdGlvbnNdXG4gICAgWCAtLT4gVltUaXBzXVxuICAgIFxuIFxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIHNwYWNld2hpdGUgZmlsbDojZmZmZmZmLHN0cm9rZTojZmZmLHN0cm9rZS13aWR0aDowcHgsY29sb3I6IzAwMFxuICAgIGNsYXNzIEEsQyxELE4sWCxtLFQsViBib3hcbiAgICBjbGFzcyBTIHNwYWNld2hpdGUiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9" _blank click C "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgc3ViZ3JhcGggbVtNZXJtYWlkLmpzXVxuICAgIGRpcmVjdGlvbiBUQlxuICAgICAgICBTWyBdLS4tXG4gICAgICAgIENbYnVpbGQ8YnI-ZGlhZ3JhbXM8YnI-d2l0aCBtYXJrZG93bl0gLS0-XG4gICAgICAgIERbb24tbGluZTxicj5saXZlIGVkaXRvcl1cbiAgICBlbmRcbiAgICBBW1doeSBhcmUgZGlhZ3JhbXM8YnI-dXNlZnVsP10gLS0-IG1cbiAgICBtIC0tPiBOWzMgeCBtZXRob2RzPGJyPmZvciBjcmVhdGluZzxicj5kaWFncmFtc11cbiAgICBOIC0tPiBUW0V4YW1wbGVzXVxuICAgIFQgLS0-IFhbU3R5bGluZzxicj5hbmQ8YnI-Y2FwdGlvbnNdXG4gICAgWCAtLT4gVltUaXBzXVxuICAgIFxuIFxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIHNwYWNld2hpdGUgZmlsbDojZmZmZmZmLHN0cm9rZTojZmZmLHN0cm9rZS13aWR0aDowcHgsY29sb3I6IzAwMFxuICAgIGNsYXNzIEEsQyxELE4sWCxtLFQsViBib3hcbiAgICBjbGFzcyBTIHNwYWNld2hpdGUiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9" _blank click D "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgc3ViZ3JhcGggbVtNZXJtYWlkLmpzXVxuICAgIGRpcmVjdGlvbiBUQlxuICAgICAgICBTWyBdLS4tXG4gICAgICAgIENbYnVpbGQ8YnI-ZGlhZ3JhbXM8YnI-d2l0aCBtYXJrZG93bl0gLS0-XG4gICAgICAgIERbb24tbGluZTxicj5saXZlIGVkaXRvcl1cbiAgICBlbmRcbiAgICBBW1doeSBhcmUgZGlhZ3JhbXM8YnI-dXNlZnVsP10gLS0-IG1cbiAgICBtIC0tPiBOWzMgeCBtZXRob2RzPGJyPmZvciBjcmVhdGluZzxicj5kaWFncmFtc11cbiAgICBOIC0tPiBUW0V4YW1wbGVzXVxuICAgIFQgLS0-IFhbU3R5bGluZzxicj5hbmQ8YnI-Y2FwdGlvbnNdXG4gICAgWCAtLT4gVltUaXBzXVxuICAgIFxuIFxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIHNwYWNld2hpdGUgZmlsbDojZmZmZmZmLHN0cm9rZTojZmZmLHN0cm9rZS13aWR0aDowcHgsY29sb3I6IzAwMFxuICAgIGNsYXNzIEEsQyxELE4sWCxtLFQsViBib3hcbiAgICBjbGFzcyBTIHNwYWNld2hpdGUiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9" _blank click N "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgc3ViZ3JhcGggbVtNZXJtYWlkLmpzXVxuICAgIGRpcmVjdGlvbiBUQlxuICAgICAgICBTWyBdLS4tXG4gICAgICAgIENbYnVpbGQ8YnI-ZGlhZ3JhbXM8YnI-d2l0aCBtYXJrZG93bl0gLS0-XG4gICAgICAgIERbb24tbGluZTxicj5saXZlIGVkaXRvcl1cbiAgICBlbmRcbiAgICBBW1doeSBhcmUgZGlhZ3JhbXM8YnI-dXNlZnVsP10gLS0-IG1cbiAgICBtIC0tPiBOWzMgeCBtZXRob2RzPGJyPmZvciBjcmVhdGluZzxicj5kaWFncmFtc11cbiAgICBOIC0tPiBUW0V4YW1wbGVzXVxuICAgIFQgLS0-IFhbU3R5bGluZzxicj5hbmQ8YnI-Y2FwdGlvbnNdXG4gICAgWCAtLT4gVltUaXBzXVxuICAgIFxuIFxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIHNwYWNld2hpdGUgZmlsbDojZmZmZmZmLHN0cm9rZTojZmZmLHN0cm9rZS13aWR0aDowcHgsY29sb3I6IzAwMFxuICAgIGNsYXNzIEEsQyxELE4sWCxtLFQsViBib3hcbiAgICBjbGFzcyBTIHNwYWNld2hpdGUiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9" _blank click T "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgc3ViZ3JhcGggbVtNZXJtYWlkLmpzXVxuICAgIGRpcmVjdGlvbiBUQlxuICAgICAgICBTWyBdLS4tXG4gICAgICAgIENbYnVpbGQ8YnI-ZGlhZ3JhbXM8YnI-d2l0aCBtYXJrZG93bl0gLS0-XG4gICAgICAgIERbb24tbGluZTxicj5saXZlIGVkaXRvcl1cbiAgICBlbmRcbiAgICBBW1doeSBhcmUgZGlhZ3JhbXM8YnI-dXNlZnVsP10gLS0-IG1cbiAgICBtIC0tPiBOWzMgeCBtZXRob2RzPGJyPmZvciBjcmVhdGluZzxicj5kaWFncmFtc11cbiAgICBOIC0tPiBUW0V4YW1wbGVzXVxuICAgIFQgLS0-IFhbU3R5bGluZzxicj5hbmQ8YnI-Y2FwdGlvbnNdXG4gICAgWCAtLT4gVltUaXBzXVxuICAgIFxuIFxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIHNwYWNld2hpdGUgZmlsbDojZmZmZmZmLHN0cm9rZTojZmZmLHN0cm9rZS13aWR0aDowcHgsY29sb3I6IzAwMFxuICAgIGNsYXNzIEEsQyxELE4sWCxtLFQsViBib3hcbiAgICBjbGFzcyBTIHNwYWNld2hpdGUiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9" _blank click X "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgc3ViZ3JhcGggbVtNZXJtYWlkLmpzXVxuICAgIGRpcmVjdGlvbiBUQlxuICAgICAgICBTWyBdLS4tXG4gICAgICAgIENbYnVpbGQ8YnI-ZGlhZ3JhbXM8YnI-d2l0aCBtYXJrZG93bl0gLS0-XG4gICAgICAgIERbb24tbGluZTxicj5saXZlIGVkaXRvcl1cbiAgICBlbmRcbiAgICBBW1doeSBhcmUgZGlhZ3JhbXM8YnI-dXNlZnVsP10gLS0-IG1cbiAgICBtIC0tPiBOWzMgeCBtZXRob2RzPGJyPmZvciBjcmVhdGluZzxicj5kaWFncmFtc11cbiAgICBOIC0tPiBUW0V4YW1wbGVzXVxuICAgIFQgLS0-IFhbU3R5bGluZzxicj5hbmQ8YnI-Y2FwdGlvbnNdXG4gICAgWCAtLT4gVltUaXBzXVxuICAgIFxuIFxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIHNwYWNld2hpdGUgZmlsbDojZmZmZmZmLHN0cm9rZTojZmZmLHN0cm9rZS13aWR0aDowcHgsY29sb3I6IzAwMFxuICAgIGNsYXNzIEEsQyxELE4sWCxtLFQsViBib3hcbiAgICBjbGFzcyBTIHNwYWNld2hpdGUiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9" _blank click V "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgc3ViZ3JhcGggbVtNZXJtYWlkLmpzXVxuICAgIGRpcmVjdGlvbiBUQlxuICAgICAgICBTWyBdLS4tXG4gICAgICAgIENbYnVpbGQ8YnI-ZGlhZ3JhbXM8YnI-d2l0aCBtYXJrZG93bl0gLS0-XG4gICAgICAgIERbb24tbGluZTxicj5saXZlIGVkaXRvcl1cbiAgICBlbmRcbiAgICBBW1doeSBhcmUgZGlhZ3JhbXM8YnI-dXNlZnVsP10gLS0-IG1cbiAgICBtIC0tPiBOWzMgeCBtZXRob2RzPGJyPmZvciBjcmVhdGluZzxicj5kaWFncmFtc11cbiAgICBOIC0tPiBUW0V4YW1wbGVzXVxuICAgIFQgLS0-IFhbU3R5bGluZzxicj5hbmQ8YnI-Y2FwdGlvbnNdXG4gICAgWCAtLT4gVltUaXBzXVxuICAgIFxuIFxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIHNwYWNld2hpdGUgZmlsbDojZmZmZmZmLHN0cm9rZTojZmZmLHN0cm9rZS13aWR0aDowcHgsY29sb3I6IzAwMFxuICAgIGNsYXNzIEEsQyxELE4sWCxtLFQsViBib3hcbiAgICBjbGFzcyBTIHNwYWNld2hpdGUiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOnRydWV9" _blank

图 1. 本节中涉及的话题。

开始使用 Mermaid 之前,你需要以下准备:

你为什么应该在代码中使用图表

图表可以增进文档的清晰度,便于理解。对于用户和贡献者而言都有好处。

用户获得的好处有:

  • 较为友好的初次体验:非常详尽的、只包含文本的欢迎页面对用户而言是蛮恐怖的, 尤其是初次接触 Kubernetes 的用户。
  • 快速理解概念:图表可以帮助用户理解复杂主题下的要点。 你的图表可以作为一种可视化的学习指南,将用户带入主题的细节。
  • 便于记忆:对某些人而言,图形(图像)要比文字更容易记忆。

对贡献者而言的好处有:

  • 帮助确立所贡献文档的结构和内容。例如, 你可以先提供一个覆盖所有顶层要点的图表,然后再逐步展开细节。
  • 培养用户社区并提升其能力。容易理解的文档,附以图表,能够吸引新的用户, 尤其是那些因为预见到复杂性而不愿参与的用户。

你需要考虑你的目标受众。除了一些有经验的 Kubernetes 用户外,你还会遇到很多刚接触 Kubernetes 的用户。即使一张简单的图表也可以帮助新用户吸收 Kubernetes 概念。 他们会变得更为大胆和自信,进一步地了解 Kubernetes 及其文档。

Mermaid

Mermaid 是一个开源的 JavaScript 库, 可以帮助你创建、编辑并很容易地分享图表。这些图表使用简单的、类似 Markdown 的语法开发,并可内嵌到 Markdown 文件中。

下面是 Mermaid 的一些特性:

  • 简单的编码语法
  • 包含基于 Web 的工具,便于你编制和预览你的图表
  • 支持包括流程图、状态图、时序图在内的多种格式
  • 可以通过共享图表的 URL 来与同事方便地合作
  • 有丰富的形状、线条、主题和样式可供选择

使用 Mermaid 的一些好处如下:

  • 不需要使用另外的、非 Mermaid 的图表工具
  • 与现有的 PR 工作流结合的很好。你可以将 Mermaid 代码视为你的 PR 中所包含的 Markdown 文本
  • 简单的工具生成简单的图表。你不需要精心制作或雕琢过于复杂或详尽的图片。 保持简单就好。

Mermaid 提供一种简单的、开放且透明的方法,便于 SIG 社区为新的或现有的文档添加、 编辑图表并展开协作。

在线编辑器

Mermaid 在线编辑器是一个基于 Web 的工具,允许你创建、编辑和审阅图表。

在线编辑器的功能主要有:

  • 显示 Mermaid 代码和渲染的图表。
  • 为所保存的每个图表生成一个 URL。该 URL 显示在你的浏览器的 URL 字段中。 你可以将 URL 分享给同事,便于他人访问和更改图表。
  • 提供将图表下载为 .svg.png 文件的选项。

创建图表的方法

图 2 给出三种生成和添加图表的方法。

graph TB A[贡献者] B[向 .md 文件

中内嵌
Mermaid 代码] C[Mermaid+SVG

将 Mermaid 所生成的
SVG 文件添加到 .md 文件] D[外部工具

添加外部工具
所生成的 SVG
文件到 .md 文件] A --> B A --> C A --> D classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; class A,B,C,D box %% 你可以使用 click 语句为 Mermaid 节点设置指向某 URL 的超链接 click A "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBBW0NvbnRyaWJ1dG9yXVxuICAgIEJbSW5saW5lPGJyPjxicj5NZXJtYWlkIGNvZGU8YnI-YWRkZWQgdG8gLm1kIGZpbGVdXG4gICAgQ1tNZXJtYWlkK1NWRzxicj48YnI-QWRkIG1lcm1haWQtZ2VuZXJhdGVkPGJyPnN2ZyBmaWxlIHRvIC5tZCBmaWxlXVxuICAgIERbRXh0ZXJuYWwgdG9vbDxicj48YnI-QWRkIGV4dGVybmFsLXRvb2wtPGJyPmdlbmVyYXRlZCBzdmcgZmlsZTxicj50byAubWQgZmlsZV1cblxuICAgIEEgLS0-IEJcbiAgICBBIC0tPiBDXG4gICAgQSAtLT4gRFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3giLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank click B "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBBW0NvbnRyaWJ1dG9yXVxuICAgIEJbSW5saW5lPGJyPjxicj5NZXJtYWlkIGNvZGU8YnI-YWRkZWQgdG8gLm1kIGZpbGVdXG4gICAgQ1tNZXJtYWlkK1NWRzxicj48YnI-QWRkIG1lcm1haWQtZ2VuZXJhdGVkPGJyPnN2ZyBmaWxlIHRvIC5tZCBmaWxlXVxuICAgIERbRXh0ZXJuYWwgdG9vbDxicj48YnI-QWRkIGV4dGVybmFsLXRvb2wtPGJyPmdlbmVyYXRlZCBzdmcgZmlsZTxicj50byAubWQgZmlsZV1cblxuICAgIEEgLS0-IEJcbiAgICBBIC0tPiBDXG4gICAgQSAtLT4gRFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3giLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank click C "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBBW0NvbnRyaWJ1dG9yXVxuICAgIEJbSW5saW5lPGJyPjxicj5NZXJtYWlkIGNvZGU8YnI-YWRkZWQgdG8gLm1kIGZpbGVdXG4gICAgQ1tNZXJtYWlkK1NWRzxicj48YnI-QWRkIG1lcm1haWQtZ2VuZXJhdGVkPGJyPnN2ZyBmaWxlIHRvIC5tZCBmaWxlXVxuICAgIERbRXh0ZXJuYWwgdG9vbDxicj48YnI-QWRkIGV4dGVybmFsLXRvb2wtPGJyPmdlbmVyYXRlZCBzdmcgZmlsZTxicj50byAubWQgZmlsZV1cblxuICAgIEEgLS0-IEJcbiAgICBBIC0tPiBDXG4gICAgQSAtLT4gRFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3giLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank click D "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBBW0NvbnRyaWJ1dG9yXVxuICAgIEJbSW5saW5lPGJyPjxicj5NZXJtYWlkIGNvZGU8YnI-YWRkZWQgdG8gLm1kIGZpbGVdXG4gICAgQ1tNZXJtYWlkK1NWRzxicj48YnI-QWRkIG1lcm1haWQtZ2VuZXJhdGVkPGJyPnN2ZyBmaWxlIHRvIC5tZCBmaWxlXVxuICAgIERbRXh0ZXJuYWwgdG9vbDxicj48YnI-QWRkIGV4dGVybmFsLXRvb2wtPGJyPmdlbmVyYXRlZCBzdmcgZmlsZTxicj50byAubWQgZmlsZV1cblxuICAgIEEgLS0-IEJcbiAgICBBIC0tPiBDXG4gICAgQSAtLT4gRFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3giLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank

图 2. 创建图表的方法

内嵌(Inline)

图 3 给出的是使用内嵌方法来添加图表所遵循的步骤。

graph LR A[1. 使用在线编辑器
来创建或编辑
图表] --> B[2. 将图表的 URL
保存到某处] --> C[3. 将 Mermaid 代码
复制到 markdown 文件中] --> D[4. 添加图表标题] classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; class A,B,C,D box %% 你可以使用 click 语句为 Mermaid 节点设置指向某 URL 的超链接 click A "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggTFJcbiAgICBBWzEuIFVzZSBsaXZlIGVkaXRvcjxicj4gdG8gY3JlYXRlL2VkaXQ8YnI-ZGlhZ3JhbV0gLS0-XG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdIC0tPlxuICAgIENbMy4gQ29weSBNZXJtYWlkIGNvZGU8YnI-dG8gcGFnZSBtYXJrZG93biBmaWxlXSAtLT5cbiAgICBEWzQuIEFkZCBjYXB0aW9uXVxuIFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank click B "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggTFJcbiAgICBBWzEuIFVzZSBsaXZlIGVkaXRvcjxicj4gdG8gY3JlYXRlL2VkaXQ8YnI-ZGlhZ3JhbV0gLS0-XG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdIC0tPlxuICAgIENbMy4gQ29weSBNZXJtYWlkIGNvZGU8YnI-dG8gcGFnZSBtYXJrZG93biBmaWxlXSAtLT5cbiAgICBEWzQuIEFkZCBjYXB0aW9uXVxuIFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank click C "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggTFJcbiAgICBBWzEuIFVzZSBsaXZlIGVkaXRvcjxicj4gdG8gY3JlYXRlL2VkaXQ8YnI-ZGlhZ3JhbV0gLS0-XG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdIC0tPlxuICAgIENbMy4gQ29weSBNZXJtYWlkIGNvZGU8YnI-dG8gcGFnZSBtYXJrZG93biBmaWxlXSAtLT5cbiAgICBEWzQuIEFkZCBjYXB0aW9uXVxuIFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank click D "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggTFJcbiAgICBBWzEuIFVzZSBsaXZlIGVkaXRvcjxicj4gdG8gY3JlYXRlL2VkaXQ8YnI-ZGlhZ3JhbV0gLS0-XG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdIC0tPlxuICAgIENbMy4gQ29weSBNZXJtYWlkIGNvZGU8YnI-dG8gcGFnZSBtYXJrZG93biBmaWxlXSAtLT5cbiAgICBEWzQuIEFkZCBjYXB0aW9uXVxuIFxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMsRCBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" _blank

图 3. 内嵌方法的步骤

下面是使用内嵌方法来添加图表时你要执行的步骤:

  1. 使用在线编辑器创建你的图表
  2. 将图表的 URL 保存在某处以便以后访问
  3. 将 Mermaid 代码复制到你的 .md 文件中你希望它出现的位置
  4. 使用 Markdown 文本在图表下方为其添加标题

Hugo 在构造(网站)过程中会运行 Mermaid 代码,将其转换为图表。

下面是一段包含在某 .md 文件中的示例代码片段:

---
title: 我的文档
---
图 17 给出从 A 到 B 的一个简单流程。
这里是其他 markdown 文本
...
{{< mermaid >}} 
    graph TB
    A --> B
{{< /mermaid >}}

图 17. 从 A 到 B

其他文本

有关添加图表标题的细节,参阅如何使用标题

使用内嵌方法的好处有:

  • 可以直接使用在线编辑器工具
  • 很容易在在线编辑器与你的 .md 文件之间来回复制 Mermaid 代码
  • 不需要额外处理 .svg 图片文件
  • 内容文字、图表代码和图表标题都位于同一个 .md 文件中。

你应该使用本地和 Netlify 预览来验证图表是可以正常渲染的。

Mermaid+SVG

图 4 给出的是使用 Mermaid+SVG 方法添加图表所要遵循的步骤:

flowchart LR A[1. 使用在线编辑器
创建或编辑
图表] B[2. 将图表的 URL
保存到别处] C[3. 生成 .svg 文件
并将其下载到
images/ 目录] subgraph w[ ] direction TB D[4. 使用 figure 短代码
来在 .md 文件中
引用 .svg 文件] --> E[5. 添加图表标题] end A --> B B --> C C --> w classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; class A,B,C,D,E,w box click A "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgbGl2ZSBlZGl0b3I8YnI-IHRvIGNyZWF0ZS9lZGl0PGJyPmRpYWdyYW1dXG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdXG4gICAgQ1szLiBHZW5lcmF0ZSAuc3ZnIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSAuc3ZnPGJyPmZpbGUgaW4gcGFnZTxicj4ubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbkEgLS0-IEJcbkIgLS0-IENcbkMgLS0-IHdcblxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzIEEsQixDLEQsRSx3IGJveFxuICAgICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank click B "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgbGl2ZSBlZGl0b3I8YnI-IHRvIGNyZWF0ZS9lZGl0PGJyPmRpYWdyYW1dXG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdXG4gICAgQ1szLiBHZW5lcmF0ZSAuc3ZnIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSAuc3ZnPGJyPmZpbGUgaW4gcGFnZTxicj4ubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbkEgLS0-IEJcbkIgLS0-IENcbkMgLS0-IHdcblxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzIEEsQixDLEQsRSx3IGJveFxuICAgICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank click C "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgbGl2ZSBlZGl0b3I8YnI-IHRvIGNyZWF0ZS9lZGl0PGJyPmRpYWdyYW1dXG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdXG4gICAgQ1szLiBHZW5lcmF0ZSAuc3ZnIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSAuc3ZnPGJyPmZpbGUgaW4gcGFnZTxicj4ubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbkEgLS0-IEJcbkIgLS0-IENcbkMgLS0-IHdcblxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzIEEsQixDLEQsRSx3IGJveFxuICAgICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank click D "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgbGl2ZSBlZGl0b3I8YnI-IHRvIGNyZWF0ZS9lZGl0PGJyPmRpYWdyYW1dXG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdXG4gICAgQ1szLiBHZW5lcmF0ZSAuc3ZnIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSAuc3ZnPGJyPmZpbGUgaW4gcGFnZTxicj4ubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbkEgLS0-IEJcbkIgLS0-IENcbkMgLS0-IHdcblxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzIEEsQixDLEQsRSx3IGJveFxuICAgICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank click E "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgbGl2ZSBlZGl0b3I8YnI-IHRvIGNyZWF0ZS9lZGl0PGJyPmRpYWdyYW1dXG4gICAgQlsyLiBTdG9yZSBkaWFncmFtPGJyPlVSTCBzb21ld2hlcmVdXG4gICAgQ1szLiBHZW5lcmF0ZSAuc3ZnIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSAuc3ZnPGJyPmZpbGUgaW4gcGFnZTxicj4ubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbkEgLS0-IEJcbkIgLS0-IENcbkMgLS0-IHdcblxuICAgIGNsYXNzRGVmIGJveCBmaWxsOiNmZmYsc3Ryb2tlOiMwMDAsc3Ryb2tlLXdpZHRoOjFweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzIEEsQixDLEQsRSx3IGJveFxuICAgICIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank

图 4. Mermaid+SVG 方法的步骤。

使用 Mermaid+SVG 方法来添加图表时你要遵从的步骤:

  1. 使用在线编辑器创建你的图表
  2. 将图表的 URL 保存到某处以便以后访问
  3. 为你的图表生成 .svg 文件,并将其下载到合适的 images/ 目录下
  4. 使用 {{< figure >}} 短代码在 .md 文件中引用该图表
  5. 使用 {{< figure >}} 短代码的 caption 参数为图表设置标题

例如,使用在线编辑器创建一个名为 boxnet 的图表。 将图表的 URL 保存到别处以便以后访问。生成 boxnet.svg 文件并将其下载到合适的 ../images/ 目录下。

在你的 PR 中的 .md 文件内使用 {{< figure >}} 短代码来引用 .svg 图片文件,并为之添加标题。

{{< figure src="/static/images/boxnet.svg" alt="Boxnet 示意图" class="diagram-large" caption="图 14. Boxnet 标题" >}}

关于图表标题的细节,可参阅如何使用标题

你应该使用文本编辑器以注释块的形式在 .svg 图片文件中添加在线编辑器的 URL。 例如,你应该在 .svg 图片文件的开头部分包含下面的内容:

<!-- 要查看或者编辑 Mermaid 代码,可访问下面的 URL:-->
<!-- https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb ... <URL 的其余部分> -->

使用 Mermaid+SVG 方法的好处有:

  • 可以直接使用在线编辑器工具
  • 在线编辑器支持的 Mermaid 特性集合最新
  • 可以利用 kubernetes/website 用来处理 .svg 图片文件的现有方法
  • 工作环境不需要 Mermaid 支持

要使用本地和 Netlify 预览来检查你的图表可以正常渲染。

外部工具

图 5 给出使用外部工具来添加图表时所遵循的步骤。

首先,要使用你的外部工具来创建图表,并将其保存为一个 .svg 文件或 .png 图片文件。 之后,使用 Mermaid+SVG 方法中相同的步骤添加 .svg.png)文件。

flowchart LR A[1. 使用外部工具
来创建或编辑
图表] B[2. 如果可能保存
图表位置供
其他贡献者访问] C[3. 生成 .svg 文件
或 .png 文件
并将其下载到
合适的 images/ 目录] subgraph w[ ] direction TB D[4. 使用 figure 短代码
在你的 .md 文件中
引用该 SVG 或 PNG
文件] --> E[5. 为图表添加标题] end A --> B B --> C C --> w classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; class A,B,C,D,E,w box click A "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgZXh0ZXJuYWw8YnI-dG9vbCB0byBjcmVhdGUvZWRpdDxicj5kaWFncmFtXVxuICAgIEJbMi4gSWYgcG9zc2libGUsIHNhdmU8YnI-ZGlhZ3JhbSBjb29yZGluYXRlczxicj5mb3IgY29udHJpYnV0b3I8YnI-YWNjZXNzXVxuICAgIENbMy4gR2VuZXJhdGUgLnN2ZyA8YnI-b3IucG5nIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmFwcHJvcHJpYXRlPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSBzdmcgb3I8YnI-cG5nIGZpbGUgaW48YnI-cGFnZSAubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbiAgICBBIC0tPiBCXG4gICAgQiAtLT4gQ1xuICAgIEMgLS0-IHdcbiAgICBjbGFzc0RlZiBib3ggZmlsbDojZmZmLHN0cm9rZTojMDAwLHN0cm9rZS13aWR0aDoxcHgsY29sb3I6IzAwMDtcbiAgICBjbGFzcyBBLEIsQyxELEUsdyBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" click B "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgZXh0ZXJuYWw8YnI-dG9vbCB0byBjcmVhdGUvZWRpdDxicj5kaWFncmFtXVxuICAgIEJbMi4gSWYgcG9zc2libGUsIHNhdmU8YnI-ZGlhZ3JhbSBjb29yZGluYXRlczxicj5mb3IgY29udHJpYnV0b3I8YnI-YWNjZXNzXVxuICAgIENbMy4gR2VuZXJhdGUgLnN2ZyA8YnI-b3IucG5nIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmFwcHJvcHJpYXRlPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSBzdmcgb3I8YnI-cG5nIGZpbGUgaW48YnI-cGFnZSAubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbiAgICBBIC0tPiBCXG4gICAgQiAtLT4gQ1xuICAgIEMgLS0-IHdcbiAgICBjbGFzc0RlZiBib3ggZmlsbDojZmZmLHN0cm9rZTojMDAwLHN0cm9rZS13aWR0aDoxcHgsY29sb3I6IzAwMDtcbiAgICBjbGFzcyBBLEIsQyxELEUsdyBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" click C "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgZXh0ZXJuYWw8YnI-dG9vbCB0byBjcmVhdGUvZWRpdDxicj5kaWFncmFtXVxuICAgIEJbMi4gSWYgcG9zc2libGUsIHNhdmU8YnI-ZGlhZ3JhbSBjb29yZGluYXRlczxicj5mb3IgY29udHJpYnV0b3I8YnI-YWNjZXNzXVxuICAgIENbMy4gR2VuZXJhdGUgLnN2ZyA8YnI-b3IucG5nIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmFwcHJvcHJpYXRlPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSBzdmcgb3I8YnI-cG5nIGZpbGUgaW48YnI-cGFnZSAubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbiAgICBBIC0tPiBCXG4gICAgQiAtLT4gQ1xuICAgIEMgLS0-IHdcbiAgICBjbGFzc0RlZiBib3ggZmlsbDojZmZmLHN0cm9rZTojMDAwLHN0cm9rZS13aWR0aDoxcHgsY29sb3I6IzAwMDtcbiAgICBjbGFzcyBBLEIsQyxELEUsdyBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" click D "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgZXh0ZXJuYWw8YnI-dG9vbCB0byBjcmVhdGUvZWRpdDxicj5kaWFncmFtXVxuICAgIEJbMi4gSWYgcG9zc2libGUsIHNhdmU8YnI-ZGlhZ3JhbSBjb29yZGluYXRlczxicj5mb3IgY29udHJpYnV0b3I8YnI-YWNjZXNzXVxuICAgIENbMy4gR2VuZXJhdGUgLnN2ZyA8YnI-b3IucG5nIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmFwcHJvcHJpYXRlPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSBzdmcgb3I8YnI-cG5nIGZpbGUgaW48YnI-cGFnZSAubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbiAgICBBIC0tPiBCXG4gICAgQiAtLT4gQ1xuICAgIEMgLS0-IHdcbiAgICBjbGFzc0RlZiBib3ggZmlsbDojZmZmLHN0cm9rZTojMDAwLHN0cm9rZS13aWR0aDoxcHgsY29sb3I6IzAwMDtcbiAgICBjbGFzcyBBLEIsQyxELEUsdyBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ" click E "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZmxvd2NoYXJ0IExSXG4gICAgQVsxLiBVc2UgZXh0ZXJuYWw8YnI-dG9vbCB0byBjcmVhdGUvZWRpdDxicj5kaWFncmFtXVxuICAgIEJbMi4gSWYgcG9zc2libGUsIHNhdmU8YnI-ZGlhZ3JhbSBjb29yZGluYXRlczxicj5mb3IgY29udHJpYnV0b3I8YnI-YWNjZXNzXVxuICAgIENbMy4gR2VuZXJhdGUgLnN2ZyA8YnI-b3IucG5nIGZpbGU8YnI-YW5kIGRvd25sb2FkIHRvPGJyPmFwcHJvcHJpYXRlPGJyPmltYWdlcy8gZm9sZGVyXVxuICAgIHN1YmdyYXBoIHdbIF1cbiAgICBkaXJlY3Rpb24gVEJcbiAgICBEWzQuIFVzZSBmaWd1cmUgc2hvcnRjb2RlPGJyPnRvIHJlZmVyZW5jZSBzdmcgb3I8YnI-cG5nIGZpbGUgaW48YnI-cGFnZSAubWQgZmlsZV0gLS0-XG4gICAgRVs1LiBBZGQgY2FwdGlvbl1cbiAgICBlbmRcbiAgICBBIC0tPiBCXG4gICAgQiAtLT4gQ1xuICAgIEMgLS0-IHdcbiAgICBjbGFzc0RlZiBib3ggZmlsbDojZmZmLHN0cm9rZTojMDAwLHN0cm9rZS13aWR0aDoxcHgsY29sb3I6IzAwMDtcbiAgICBjbGFzcyBBLEIsQyxELEUsdyBib3hcbiAgICAiLCJtZXJtYWlkIjoie1xuICBcInRoZW1lXCI6IFwiZGVmYXVsdFwiXG59IiwidXBkYXRlRWRpdG9yIjpmYWxzZSwiYXV0b1N5bmMiOnRydWUsInVwZGF0ZURpYWdyYW0iOmZhbHNlfQ"

图 5. 外部工具方法步骤

使用外部工具方法来添加图表时,你要遵从的步骤如下:

  1. 使用你的外部工具来创建图表。
  2. 将图表的位置保存起来供其他贡献者访问。例如,你的工具可能提供一个指向图表的链接, 或者你可以将源码文件(例如一个 .xml 文件)放置到一个公开的仓库, 以便其他贡献者访问。
  3. 生成图表并将其下载为 .svg.png 图片文件,保存到合适的 ../images/ 目录下。
  4. 使用 {{< figure >}} 短代码从 .md 文件中引用该图表。
  5. 使用 {{< figure >}} 短代码的 caption 参数为图表设置标题。

下面是一个用于 images/apple.svg 图表的 {{< figure >}} 短代码:

{{< figure src="/static/images/apple.svg" alt="red-apple-figure" class="diagram-large" caption="图 9. 一个大红苹果" >}} 

如果你的外部绘图工具支持:

  • 你可以将多个 .svg.png 商标、图标或图片整合到你的图表中。 不过,你需要确保你查看了版权并遵守了 Kubernetes 文档关于使用第三方内容的 指南
  • 你应该将图表的源位置保存起来,以便其他贡献者访问。 例如,你的工具可能提供指向图表文件的链接,或者你应该将源代码文件 (例如一个 .xml 文件)放到某处以便其他贡献者访问。

关于 K8s 和 CNCF 商标与图片的详细信息,可参阅 CNCF Artwork

使用外部工具的好处有:

  • 贡献者对外部工具更为熟悉
  • 图表可能需要 Mermaid 所无法提供的细节

不要忘记使用本地和 Netlify 预览来检查你的图表可以正常渲染。

示例

本节给出 Mermaid 的若干样例。

示例 1 - Pod 拓扑分布约束

图 6 展示的是 Pod 拓扑分布约束 页面所出现的图表。

graph TB subgraph "zoneB" n3(Node3) n4(Node4) end subgraph "zoneA" n1(Node1) n2(Node2) end classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; class n1,n2,n3,n4 k8s; class zoneA,zoneB cluster; click n3 "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBzdWJncmFwaCBcInpvbmVCXCJcbiAgICAgICAgbjMoTm9kZTMpXG4gICAgICAgIG40KE5vZGU0KVxuICAgIGVuZFxuICAgIHN1YmdyYXBoIFwiem9uZUFcIlxuICAgICAgICBuMShOb2RlMSlcbiAgICAgICAgbjIoTm9kZTIpXG4gICAgZW5kXG5cbiAgICBjbGFzc0RlZiBwbGFpbiBmaWxsOiNkZGQsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICAgIGNsYXNzRGVmIGNsdXN0ZXIgZmlsbDojZmZmLHN0cm9rZTojYmJiLHN0cm9rZS13aWR0aDoycHgsY29sb3I6IzMyNmNlNTtcbiAgICBjbGFzcyBuMSxuMixuMyxuNCBrOHM7XG4gICAgY2xhc3Mgem9uZUEsem9uZUIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank click n4 "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBzdWJncmFwaCBcInpvbmVCXCJcbiAgICAgICAgbjMoTm9kZTMpXG4gICAgICAgIG40KE5vZGU0KVxuICAgIGVuZFxuICAgIHN1YmdyYXBoIFwiem9uZUFcIlxuICAgICAgICBuMShOb2RlMSlcbiAgICAgICAgbjIoTm9kZTIpXG4gICAgZW5kXG5cbiAgICBjbGFzc0RlZiBwbGFpbiBmaWxsOiNkZGQsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICAgIGNsYXNzRGVmIGNsdXN0ZXIgZmlsbDojZmZmLHN0cm9rZTojYmJiLHN0cm9rZS13aWR0aDoycHgsY29sb3I6IzMyNmNlNTtcbiAgICBjbGFzcyBuMSxuMixuMyxuNCBrOHM7XG4gICAgY2xhc3Mgem9uZUEsem9uZUIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank click n1 "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBzdWJncmFwaCBcInpvbmVCXCJcbiAgICAgICAgbjMoTm9kZTMpXG4gICAgICAgIG40KE5vZGU0KVxuICAgIGVuZFxuICAgIHN1YmdyYXBoIFwiem9uZUFcIlxuICAgICAgICBuMShOb2RlMSlcbiAgICAgICAgbjIoTm9kZTIpXG4gICAgZW5kXG5cbiAgICBjbGFzc0RlZiBwbGFpbiBmaWxsOiNkZGQsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICAgIGNsYXNzRGVmIGNsdXN0ZXIgZmlsbDojZmZmLHN0cm9rZTojYmJiLHN0cm9rZS13aWR0aDoycHgsY29sb3I6IzMyNmNlNTtcbiAgICBjbGFzcyBuMSxuMixuMyxuNCBrOHM7XG4gICAgY2xhc3Mgem9uZUEsem9uZUIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank click n2 "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggVEJcbiAgICBzdWJncmFwaCBcInpvbmVCXCJcbiAgICAgICAgbjMoTm9kZTMpXG4gICAgICAgIG40KE5vZGU0KVxuICAgIGVuZFxuICAgIHN1YmdyYXBoIFwiem9uZUFcIlxuICAgICAgICBuMShOb2RlMSlcbiAgICAgICAgbjIoTm9kZTIpXG4gICAgZW5kXG5cbiAgICBjbGFzc0RlZiBwbGFpbiBmaWxsOiNkZGQsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojMDAwO1xuICAgIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICAgIGNsYXNzRGVmIGNsdXN0ZXIgZmlsbDojZmZmLHN0cm9rZTojYmJiLHN0cm9rZS13aWR0aDoycHgsY29sb3I6IzMyNmNlNTtcbiAgICBjbGFzcyBuMSxuMixuMyxuNCBrOHM7XG4gICAgY2xhc3Mgem9uZUEsem9uZUIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6dHJ1ZX0" _blank

图 6. Pod 拓扑分布约束

代码块:

graph TB
   subgraph "zoneB"
       n3(Node3)
       n4(Node4)
   end
   subgraph "zoneA"
       n1(Node1)
       n2(Node2)
   end
 
   classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
   classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff;
   classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
   class n1,n2,n3,n4 k8s;
   class zoneA,zoneB cluster;

示例 2 - Ingress

图 7 显示的是 Ingress 是什么 页面所出现的图表。

graph LR; client([客户端])-. Ingress 所管理的
负载均衡器 .->ingress[Ingress]; ingress-->|路由规则|service[服务]; subgraph cluster ingress; service-->pod1[Pod]; service-->pod2[Pod]; end classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; class ingress,service,pod1,pod2 k8s; class client plain; class cluster cluster; click client "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggIExSXG4gIGNsaWVudChbY2xpZW50XSktLiBJbmdyZXNzLW1hbmFnZWQgPGJyPiBsb2FkIGJhbGFuY2VyIC4tPmluZ3Jlc3NbSW5ncmVzc107XG4gIGluZ3Jlc3MtLT58cm91dGluZyBydWxlfHNlcnZpY2VbU2VydmljZV07XG4gIHN1YmdyYXBoIGNsdXN0ZXJcbiAgaW5ncmVzcztcbiAgc2VydmljZS0tPnBvZDFbUG9kXTtcbiAgc2VydmljZS0tPnBvZDJbUG9kXTtcbiAgZW5kXG4gIGNsYXNzRGVmIHBsYWluIGZpbGw6I2RkZCxzdHJva2U6I2ZmZixzdHJva2Utd2lkdGg6NHB4LGNvbG9yOiMwMDA7XG4gIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICBjbGFzc0RlZiBjbHVzdGVyIGZpbGw6I2ZmZixzdHJva2U6I2JiYixzdHJva2Utd2lkdGg6MnB4LGNvbG9yOiMzMjZjZTU7XG4gIGNsYXNzIGluZ3Jlc3Msc2VydmljZSxwb2QxLHBvZDIgazhzO1xuICBjbGFzcyBjbGllbnQgcGxhaW47XG4gIGNsYXNzIGNsdXN0ZXIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9" _blank click ingress "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggIExSXG4gIGNsaWVudChbY2xpZW50XSktLiBJbmdyZXNzLW1hbmFnZWQgPGJyPiBsb2FkIGJhbGFuY2VyIC4tPmluZ3Jlc3NbSW5ncmVzc107XG4gIGluZ3Jlc3MtLT58cm91dGluZyBydWxlfHNlcnZpY2VbU2VydmljZV07XG4gIHN1YmdyYXBoIGNsdXN0ZXJcbiAgaW5ncmVzcztcbiAgc2VydmljZS0tPnBvZDFbUG9kXTtcbiAgc2VydmljZS0tPnBvZDJbUG9kXTtcbiAgZW5kXG4gIGNsYXNzRGVmIHBsYWluIGZpbGw6I2RkZCxzdHJva2U6I2ZmZixzdHJva2Utd2lkdGg6NHB4LGNvbG9yOiMwMDA7XG4gIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICBjbGFzc0RlZiBjbHVzdGVyIGZpbGw6I2ZmZixzdHJva2U6I2JiYixzdHJva2Utd2lkdGg6MnB4LGNvbG9yOiMzMjZjZTU7XG4gIGNsYXNzIGluZ3Jlc3Msc2VydmljZSxwb2QxLHBvZDIgazhzO1xuICBjbGFzcyBjbGllbnQgcGxhaW47XG4gIGNsYXNzIGNsdXN0ZXIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9" _blank click service "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggIExSXG4gIGNsaWVudChbY2xpZW50XSktLiBJbmdyZXNzLW1hbmFnZWQgPGJyPiBsb2FkIGJhbGFuY2VyIC4tPmluZ3Jlc3NbSW5ncmVzc107XG4gIGluZ3Jlc3MtLT58cm91dGluZyBydWxlfHNlcnZpY2VbU2VydmljZV07XG4gIHN1YmdyYXBoIGNsdXN0ZXJcbiAgaW5ncmVzcztcbiAgc2VydmljZS0tPnBvZDFbUG9kXTtcbiAgc2VydmljZS0tPnBvZDJbUG9kXTtcbiAgZW5kXG4gIGNsYXNzRGVmIHBsYWluIGZpbGw6I2RkZCxzdHJva2U6I2ZmZixzdHJva2Utd2lkdGg6NHB4LGNvbG9yOiMwMDA7XG4gIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICBjbGFzc0RlZiBjbHVzdGVyIGZpbGw6I2ZmZixzdHJva2U6I2JiYixzdHJva2Utd2lkdGg6MnB4LGNvbG9yOiMzMjZjZTU7XG4gIGNsYXNzIGluZ3Jlc3Msc2VydmljZSxwb2QxLHBvZDIgazhzO1xuICBjbGFzcyBjbGllbnQgcGxhaW47XG4gIGNsYXNzIGNsdXN0ZXIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9" _blank click pod1 "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggIExSXG4gIGNsaWVudChbY2xpZW50XSktLiBJbmdyZXNzLW1hbmFnZWQgPGJyPiBsb2FkIGJhbGFuY2VyIC4tPmluZ3Jlc3NbSW5ncmVzc107XG4gIGluZ3Jlc3MtLT58cm91dGluZyBydWxlfHNlcnZpY2VbU2VydmljZV07XG4gIHN1YmdyYXBoIGNsdXN0ZXJcbiAgaW5ncmVzcztcbiAgc2VydmljZS0tPnBvZDFbUG9kXTtcbiAgc2VydmljZS0tPnBvZDJbUG9kXTtcbiAgZW5kXG4gIGNsYXNzRGVmIHBsYWluIGZpbGw6I2RkZCxzdHJva2U6I2ZmZixzdHJva2Utd2lkdGg6NHB4LGNvbG9yOiMwMDA7XG4gIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICBjbGFzc0RlZiBjbHVzdGVyIGZpbGw6I2ZmZixzdHJva2U6I2JiYixzdHJva2Utd2lkdGg6MnB4LGNvbG9yOiMzMjZjZTU7XG4gIGNsYXNzIGluZ3Jlc3Msc2VydmljZSxwb2QxLHBvZDIgazhzO1xuICBjbGFzcyBjbGllbnQgcGxhaW47XG4gIGNsYXNzIGNsdXN0ZXIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9" _blank click pod2 "https://mermaid-js.github.io/mermaid-live-editor/edit/#eyJjb2RlIjoiZ3JhcGggIExSXG4gIGNsaWVudChbY2xpZW50XSktLiBJbmdyZXNzLW1hbmFnZWQgPGJyPiBsb2FkIGJhbGFuY2VyIC4tPmluZ3Jlc3NbSW5ncmVzc107XG4gIGluZ3Jlc3MtLT58cm91dGluZyBydWxlfHNlcnZpY2VbU2VydmljZV07XG4gIHN1YmdyYXBoIGNsdXN0ZXJcbiAgaW5ncmVzcztcbiAgc2VydmljZS0tPnBvZDFbUG9kXTtcbiAgc2VydmljZS0tPnBvZDJbUG9kXTtcbiAgZW5kXG4gIGNsYXNzRGVmIHBsYWluIGZpbGw6I2RkZCxzdHJva2U6I2ZmZixzdHJva2Utd2lkdGg6NHB4LGNvbG9yOiMwMDA7XG4gIGNsYXNzRGVmIGs4cyBmaWxsOiMzMjZjZTUsc3Ryb2tlOiNmZmYsc3Ryb2tlLXdpZHRoOjRweCxjb2xvcjojZmZmO1xuICBjbGFzc0RlZiBjbHVzdGVyIGZpbGw6I2ZmZixzdHJva2U6I2JiYixzdHJva2Utd2lkdGg6MnB4LGNvbG9yOiMzMjZjZTU7XG4gIGNsYXNzIGluZ3Jlc3Msc2VydmljZSxwb2QxLHBvZDIgazhzO1xuICBjbGFzcyBjbGllbnQgcGxhaW47XG4gIGNsYXNzIGNsdXN0ZXIgY2x1c3RlcjtcbiIsIm1lcm1haWQiOiJ7XG4gIFwidGhlbWVcIjogXCJkZWZhdWx0XCJcbn0iLCJ1cGRhdGVFZGl0b3IiOmZhbHNlLCJhdXRvU3luYyI6dHJ1ZSwidXBkYXRlRGlhZ3JhbSI6ZmFsc2V9" _blank

图 7. Ingress

代码块:

graph LR;
 client([客户端])-. Ingress 所管理的<br>负载均衡器 .->ingress[Ingress];
 ingress-->|路由规则|service[服务];
 subgraph cluster
 ingress;
 service-->pod1[Pod];
 service-->pod2[Pod];
 end
 classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000;
 classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff;
 classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5;
 class ingress,service,pod1,pod2 k8s;
 class client plain;
 class cluster cluster;

示例 3 - K8s 系统流程

图 8 给出的是一个 Mermaid 时序图,展示启动容器时 K8s 组件间的控制流。

K8s system flow diagram

图 8. K8s 系统流程图

代码段:

%%{init:{"theme":"neutral"}}%%
sequenceDiagram
    actor me
    participant apiSrv as 控制面<br><br>api-server
    participant etcd as 控制面<br><br>etcd 数据存储
    participant cntrlMgr as 控制面<br><br>控制器管理器
    participant sched as 控制面<br><br>调度器
    participant kubelet as 节点<br><br>kubelet
    participant container as 节点<br><br>容器运行时
    me->>apiSrv: 1. kubectl create -f pod.yaml
    apiSrv-->>etcd: 2. 保存新状态
    cntrlMgr->>apiSrv: 3. 检查变更
    sched->>apiSrv: 4. 监视未分派的 Pod(s)
    apiSrv->>sched: 5. 通知 nodename=" " 的 Pod
    sched->>apiSrv: 6. 指派 Pod 到节点
    apiSrv-->>etcd: 7. 保存新状态
    kubelet->>apiSrv: 8. 查询新指派的 Pod(s)
    apiSrv->>kubelet: 9. 将 Pod 绑定到节点
    kubelet->>container: 10. 启动容器
    kubelet->>apiSrv: 11. 更新 Pod 状态
    apiSrv-->>etcd: 12. 保存新状态

如何设置图表样式

你可以使用大家都熟悉的 CSS 术语来为一个或多个图表元素设置渲染样式。 你可以在 Mermaid 代码中使用两种类型的语句来完成这一工作:

  • classDef 定义一类样式属性;
  • class 指定 class 所适用的一种或多种元素。

图 7 中,你可以看到这两种示例。

classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; // 定义 k8s 类的样式
class ingress,service,pod1,pod2 k8s; // k8s 类会应用到 ingress、service、pod1 和 pod2 这些元素之上

你可以在你的图表中包含一个或多个 classDefclass 语句。 你也可以在你的图表中为 k8s 组件使用官方的 K8s #326ce5 十六进制颜色代码。

关于样式设置和类的更多信息,可参阅 Mermaid Styling and classes docs

如何使用标题

标题用来为图表提供简要的描述。标题或短描述都可以作为图表标题。 标题不是用来替换你在文档中要提供的解释性文字。 相反,它们是用来在文字与图表之间建立“语境连接”的。

将一些文字和带标题的图表组合到一起,可以为你所想要向用户传递的信息提供一种更为精确的表达。

没有标题的话,用户就必须在图表前后的文字中来回阅读,从而了解其含义。 这会让用户感觉到很沮丧。

图 9 给出合适的标题所需要具备的三要素:图表、图表标题和图表引用。

flowchart A[图表本身

内嵌 Mermaid 或
SVG 图片文件] B[图表标题

添加图表编号和
标题文字] C[图表引用

在文字中用图表
编号引用图表] classDef box fill:#fff,stroke:#000,stroke-width:1px,color:#000; class A,B,C box click A "https://mermaid-js.github.io/mermaid-live-editor/edit#eyJjb2RlIjoiZmxvd2NoYXJ0XG4gICAgQVtEaWFncmFtPGJyPjxicj5JbmxpbmUgTWVybWFpZCBvcjxicj5TVkcgaW1hZ2UgZmlsZXNdXG4gICAgQltEaWFncmFtIENhcHRpb248YnI-PGJyPkFkZCBGaWd1cmUgTnVtYmVyLiBhbmQ8YnI-Q2FwdGlvbiBUZXh0XVxuICAgIENbRGlhZ3JhbSBSZWZlcnJhbDxicj48YnI-UmVmZXJlbmVuY2UgRmlndXJlIE51bWJlcjxicj5pbiB0ZXh0XVxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMgYm94IiwibWVybWFpZCI6IntcbiAgXCJ0aGVtZVwiOiBcImRlZmF1bHRcIlxufSIsInVwZGF0ZUVkaXRvciI6ZmFsc2UsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjpmYWxzZX0" _blank click B "https://mermaid-js.github.io/mermaid-live-editor/edit#eyJjb2RlIjoiZmxvd2NoYXJ0XG4gICAgQVtEaWFncmFtPGJyPjxicj5JbmxpbmUgTWVybWFpZCBvcjxicj5TVkcgaW1hZ2UgZmlsZXNdXG4gICAgQltEaWFncmFtIENhcHRpb248YnI-PGJyPkFkZCBGaWd1cmUgTnVtYmVyLiBhbmQ8YnI-Q2FwdGlvbiBUZXh0XVxuICAgIENbRGlhZ3JhbSBSZWZlcnJhbDxicj48YnI-UmVmZXJlbmVuY2UgRmlndXJlIE51bWJlcjxicj5pbiB0ZXh0XVxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMgYm94IiwibWVybWFpZCI6IntcbiAgXCJ0aGVtZVwiOiBcImRlZmF1bHRcIlxufSIsInVwZGF0ZUVkaXRvciI6ZmFsc2UsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjpmYWxzZX0" _blank click C "https://mermaid-js.github.io/mermaid-live-editor/edit#eyJjb2RlIjoiZmxvd2NoYXJ0XG4gICAgQVtEaWFncmFtPGJyPjxicj5JbmxpbmUgTWVybWFpZCBvcjxicj5TVkcgaW1hZ2UgZmlsZXNdXG4gICAgQltEaWFncmFtIENhcHRpb248YnI-PGJyPkFkZCBGaWd1cmUgTnVtYmVyLiBhbmQ8YnI-Q2FwdGlvbiBUZXh0XVxuICAgIENbRGlhZ3JhbSBSZWZlcnJhbDxicj48YnI-UmVmZXJlbmVuY2UgRmlndXJlIE51bWJlcjxicj5pbiB0ZXh0XVxuXG4gICAgY2xhc3NEZWYgYm94IGZpbGw6I2ZmZixzdHJva2U6IzAwMCxzdHJva2Utd2lkdGg6MXB4LGNvbG9yOiMwMDA7XG4gICAgY2xhc3MgQSxCLEMgYm94IiwibWVybWFpZCI6IntcbiAgXCJ0aGVtZVwiOiBcImRlZmF1bHRcIlxufSIsInVwZGF0ZUVkaXRvciI6ZmFsc2UsImF1dG9TeW5jIjp0cnVlLCJ1cGRhdGVEaWFncmFtIjpmYWxzZX0" _blank

图 9. 标题要素

图表本身

Mermaid+SVG 和外部工具方法都会生成 .svg 图片文件。

下面的 {{< figure >}} 短代码是针对定义在保存于 /images/docs/components-of-kubernetes.svg 中的 .svg 图片文件的。

{{< figure src="/images/docs/components-of-kubernetes.svg" alt="运行于集群中的 Kubernetes Pod" class="diagram-large" caption="图 4. Kubernetes 结构组件" >}}

你需要将 srcaltclasscaption 取值传递给 {{< figure >}} 短代码。 你可以使用 diagram-largediagram-mediumdiagram-small 类来调整图表的尺寸。

关于创建图表的不同方法,可参阅创建图表的方法

图表标题

接下来,添加图表标题。

如果你使用 .svg 图片文件来定义你的图表,你就需要使用 {{< figure >}} 短代码的 caption 参数。

{{< figure src="/images/docs/components-of-kubernetes.svg" alt="运行于集群中的 Kubernetes Pod" class="diagram-large" caption="图 4. Kubernetes 架构组件" >}}

如果你使用内嵌的 Mermaid 代码来定义图表,则你需要使用 Markdown 文本来添加标题。

图 4. Kubernetes 架构组件

添加图表标题时需要考虑的问题:

  • 使用 {{< figure >}} 短代码来为 Mermaid+SVG 和外部工具方法制作的图表添加标题。
  • 对于内嵌方法制作的图表,使用简单的 Markdown 文本来为其添加标题。
  • 在你的图表标题前面添加 图 <编号>.。你必须使用 字样, 并且编号必须对于文档页面中所有图表而言唯一。 在编号之后添加一个英文句号。
  • 将图表标题添加到 图 <编号>. 之后,并且在同一行。 你必须为图表标题添加英文句点作为其结束标志。尽量保持标题文字简短。
  • 图表标题要放在图表之后

图表引用

最后,你可以添加图表引用。图表引用位于你的文档正文中,并且应该出现在图表之前。 这样,用户可以将你的文字与对应的图表关联起来。引用时所给的 图 <编号> 部分要与图表标题中对应部分一致。

你要避免使用空间上的相对引用,例如 ..下面的图片.. 或者 ..下面的图形..

以下是一个参考引用的示例。

图 10 展示的是 Kubernetes 体系结构。其控制面 ...

图表引用是可选的,在有些场合中,添加这类引用是不合适的。 如果你不是很确定,可以在文字中添加图表引用,以判断是否看起来、读起来比较通顺。 如果仍然不确定,可以使用图表引用。

完整全图

图 10 展示的是一个 Kubernetes 架构图表,其中包含了图表本身、图表标题和图表引用。 这里的 {{< figure >}} 短代码负责渲染图表,添加标题并包含可选的 link 参数,以便于你为图表提供超级链接。图表引用也被包含在段落中。

下面是针对此图表的 {{< figure >}} 短代码。

{{< figure src="/images/docs/components-of-kubernetes.svg" alt="运行在集群中的 Kubernetes Pod" class="diagram-large" caption="图 10. Kubernetes 架构" link="https://kubernetes.io/zh-cn/docs/concepts/overview/components/" >}}
运行在集群中的 Kubernetes Pod

图 10. Kubernetes 架构

提示

  • 总是使用在线编辑器来创建和编辑你的图表。

  • 总是使用 Hugo 本地和 Netlify 预览来检查图表在文档中的渲染效果。

  • 提供图表源代码指针,例如 URL、源代码位置或者标明代码时是说明的。

  • 总是提供图表标题。

  • 在问题报告或 PR 中包含 .svg.png 图片与/或 Mermaid 代码会很有帮助。

  • 对于 Mermaid+SVG 方法和外部工具方法而言,尽量使用 .svg 图片文件, 因为这类文件在被放大之后仍能清晰地显示。

  • 对于 .svg 文件的最佳实践是将其加载到一个 SVG 编辑工具中,并使用 “将文字转换为路径”功能完成转换。

  • Mermaid 不支持额外的图表或艺术形式。

  • Hugo Mermaid 短代码在在线编辑器中无法显示。

  • 如果想要在在线编辑器中更改图表,你必须保存它以便为图表生成新的 URL。

  • 点击本节中的图表,你可以查看其源代码及其在在线编辑器中的渲染效果。

  • 查看本页的源代码,diagram-guide.md 文件,可以将其作为示例。

  • 查阅 Mermaid 文档以获得更多的解释和示例。

最重要的一点,保持图表简单。 这样做会节省你和其他贡献者的时间,同时也会方便新的以及有经验的用户阅读。

4 - 撰写新主题

本页面展示如何为 Kubernetes 文档库创建新主题。

准备开始

发起 PR中所述,创建 Kubernetes 文档库的派生副本。

选择页面类型

当你准备编写一个新的主题时,考虑一下最适合你的内容的页面类型:

选择页面类型的说明
类型描述
概念(Concept)概念页面负责解释 Kubernetes 的某方面。例如,概念页面可以描述 Kubernetes Deployment 对象,并解释当部署、扩展和更新时,它作为应用程序所扮演的角色。一般来说,概念页面不包括步骤序列,而是提供任务或教程的链接。概念主题的示例可参见 节点
任务(Task)任务页面展示如何完成特定任务。其目的是给读者提供一系列的步骤,让他们在阅读时可以实际执行。任务页面可长可短,前提是它始终围绕着某个主题展开。在任务页面中,可以将简短的解释与要执行的步骤混合在一起。如果需要提供较长的解释,则应在概念主题中进行。相关联的任务和概念主题应该相互链接。一个简短的任务页面的实例可参见 配置 Pod 使用卷存储。一个较长的任务页面的实例可参见 配置活跃性和就绪性探针
教程(Tutorial)教程页面展示如何实现某个目标,该目标将若干 Kubernetes 功能特性联系在一起。教程可能提供一些步骤序列,读者可以在阅读页面时实际执行这些步骤。或者它可以提供相关代码片段的解释。例如,教程可以提供代码示例的讲解。教程可以包括对 Kubernetes 几个关联特性的简要解释,但有关更深入的特性解释应该链接到相关概念主题。

创建一个新页面

为每个新页面选择其内容类型。 文档站提供了模板或 Hugo Archetypes 来创建新的内容页面。 要创建新类型的页面,请使用要创建的文件的路径,运行 hugo new 命令。例如:

hugo new docs/concepts/my-first-concept.md

选择标题和文件名

选择一个标题,确保其中包含希望搜索引擎发现的关键字。 确定文件名时请使用标题中的单词,由连字符分隔。 例如,标题为使用 HTTP 代理访问 Kubernetes API 的主题的文件名为 http-proxy-access-api.md。 你不需要在文件名中加上 "kubernetes",因为 "kubernetes" 已经在主题的 URL 中了, 例如:

   /docs/tasks/extend-kubernetes/http-proxy-access-api/

在页面前言中添加主题标题

在你的主题中,在前言(front-matter) 中设置一个 title 字段。 前言是位于页面顶部三条虚线之间的 YAML 块。下面是一个例子:

---
title: 使用 HTTP 代理访问 Kubernetes API
---

选择目录

根据页面类型,将新文件放入其中一个子目录中:

  • /content/en/docs/tasks/
  • /content/en/docs/tutorials/
  • /content/en/docs/concepts/

你可以将文件放在现有的子目录中,也可以创建一个新的子目录。

将主题放在目录中

目录是使用文档源的目录结构动态构建的。 /content/en/docs/ 下的顶层目录用于创建顶层导航条目, 这些目录和它们的子目录在网站目录中都有对应条目。

每个子目录都有一个 _index.md 文件,它表示的是该子目录内容的主页面。 _index.md 文件不需要模板。它可以包含各子目录中主题的概述内容。

默认情况下,目录中的其他文件按字母顺序排序。这一般不是最好的顺序。 要控制子目录中主题的相对排序,请将页面头部的键 weight: 设置为整数值。 通常我们使用 10 的倍数,添加后续主题时 weight 值递增。 例如,weight10 的主题将位于 weight20 的主题之前。

在主题中嵌入代码

如果你想在主题中嵌入一些代码,可以直接使用 Markdown 代码块语法将代码嵌入到文件中。 建议在以下场合(并非详尽列表)使用嵌入代码:

  • 代码显示来自命令的输出,例如 kubectl get deploy mydeployment -o json | jq '.status'
  • 代码不够通用,用户无法验证。例如,你可以嵌入 YAML 文件来创建一个依赖于特定 FlexVolume 实现的 Pod。
  • 该代码是一个不完整的示例,因为其目的是突出展现某个大文件中的部分内容。 例如,在描述 RoleBinding 的方法时,你可以在主题文件中直接提供一个短的代码段。
  • 由于某些其他原因,该代码不适合用户验证。 例如,当使用 kubectl edit 命令描述如何将新属性添加到资源时, 你可以提供一个仅包含要添加的属性的简短示例。

引用来自其他文件的代码

在主题中引用代码的另一种方法是创建一个新的、完整的示例文件(或文件组), 然后在主题中引用这些示例。当示例是通用的和可重用的,并且你希望读者自己验证时, 使用此方法引用示例 YAML 文件。

添加新的独立示例文件(如 YAML 文件)时,将代码放在 <LANG>/examples/ 的某个子目录中, 其中 <LANG> 是该主题的语言。在主题文件中使用 code_sample 短代码:

{{% code_sample file="<RELPATH>/my-example-yaml>" %}}

<RELPATH> 是要引用的文件的路径,相对于 examples 目录。以下 Hugo 短代码引用了位于 /content/en/examples/pods/storage/gce-volume.yaml 的 YAML 文件。

{{% code_sample file="pods/storage/gce-volume.yaml" %}}

显示如何从配置文件创建 API 对象

如果需要演示如何基于配置文件创建 API 对象,请将配置文件放在 <LANG>/examples 下的某个子目录中。

在主题中展示以下命令:

kubectl create -f https://k8s.io/examples/pods/storage/gce-volume.yaml

有关使用此技术的主题的示例, 请参见运行单实例有状态的应用

向主题添加图片

将图片文件放入 /images 目录。首选的图片格式是 SVG。

接下来

5 - 页面内容类型

Kubernetes 文档包含以下几种页面内容类型:

  • 概念(Concept)
  • 任务(Task)
  • 教程(Tutorial)
  • 参考(Reference)

内容章节

每种页面内容类型都有一些使用 Markdown 注释和 HTML 标题定义的章节。 你可以使用 heading 短代码将内容标题添加到你的页面中。 注释和标题有助于维护对应页面内容类型的结构组织。

定义页面内容章节的 Markdown 注释示例:

<!-- overview -->
<!-- body -->

要在内容页面中创建通用的标题,可以使用 heading 短代码加上标题字符串。

标题字符串示例:

  • whatsnext
  • prerequisites
  • objectives
  • cleanup
  • synopsis
  • seealso
  • options

例如,要创建一个 whatsnext 标题,添加 heading 短代码并指定 "whatsnext" 字符串:

## {{% heading "whatsnext" %}}

你可以像下面这样声明一个 prerequisites 标题:

## {{% heading "prerequisites" %}}

短代码 heading 需要一个字符串参数。 该字符串参数要与 i18n/<语言>.toml 文件中以其为前缀的某个变量匹配。 例如:

i18n/en.toml:

[whatsnext_heading]
other = "What's next"

i18n/ko.toml:

[whatsnext_heading]
other = "다음 내용"

内容类型

每种内容类型都非正式地定义了期望的页面结构组织。 请按照所建议的页面章节来创建内容页面。

概念

概念页面用来解释 Kubernetes 的某些方面。例如,概念页面可以用来描述 Kubernetes 中的 Deployment 对象,解释其作为应用的角色如何部署、扩缩和更新。 通常,概念页面不需要包含步骤序列,但包含指向任务或教程的链接。

要编写一个新的概念页面,在 /content/en/docs/concepts 目录下面的子目录中新建一个 Markdown 文件。 该文件具有以下特点。

概念页面分为三个章节:

页面章节
overview(概述)
body(正文)
whatsnext(接下来)

其中的 overviewbody 章节在概念页面中显示为注释。 你可以使用 heading 短代码向页面添加 wahtsnext 节。

在为每个章节撰写内容时,遵从一些规定:

  • 使用二级和三级标题(H2、H3)来组织内容;
  • overview 节中,使用一段文字概括当前主题的上下文;
  • body 节中,详细解释对应概念;
  • 对于 whatsnext 节,提供一个项目符号列表(最多 5 个),帮助读者进一步学习掌握概念。

注解页面是一个已经上线的概念页面的例子。

任务(Task)

任务页面讲解如何完成某项工作,通常包含由为数不多的几个步骤组成的序列。 任务页面的讲解文字很少,不过通常会包含指向概念主题的链接,以便读者能够了解相关的背景和知识。

编写新的任务页面时,在 /content/en/docs/tasks 目录下的子目录中创建一个新的 Markdown 文件。 该文件特点如下。

页面章节
overview(概述)
prerequisites(准备工作)
steps(步骤)
discussion(讨论)
whatsnext(接下来)

其中的 overviewstepsdiscussion 节在任务页面中显示为注释。 你可以使用 heading 短代码添加 prerequisiteswhatsnext 小节。

在每个小节内撰写内容时注意以下规定:

  • 最低使用二级标题(H2,标题行前带两个 # 字符)。每个小节都会由模板自动给出标题。
  • overview 节中,用一个段落为整个任务主题设定语境;
  • prerequisites 节中,尽可能使用项目符号列表。 额外的环境准备条件要加在 include 短代码之后。 默认的环境准备条件是拥有一个在运行的 Kubernetes 集群。
  • steps 节中,使用编号符号列表。
  • discussion 节中,使用正常文字内容来对 steps 节中内容展开叙述。
  • whatsnext 节中,使用项目符号列表(不超过 5 项),列举读者可能接下来有兴趣阅读的主题。

已上线的任务主题示例之一是使用 HTTP 代理访问 Kubernetes API

教程(Tutorial)

教程页面描述如果完成一个比单一任务规模更大的目标。通常教程页面会有多个小节, 每个小节由一系列步骤组成。例如,每个教程可能提供对代码示例的讲解, 便于用户了解 Kubernetes 的某个功能特性。教程可以包含表面层面的概念解释, 对于更深层面的概念主题应该使用链接。

撰写新的教程页面时,在 /content/en/docs/tutorials 目录下面的子目录中创建新的 Markdown 文件。该文件有以下特点。

页面节区
overview(概述)
prerequisites(环境准备)
objectives(目标)
lessoncontent(教程内容)
cleanup(清理工作)
whatsnext(接下来)

教程页面的 overviewobjectiveslessoncontent 小节显示为注释形式。 你可以使用 heading 短代码根据需要添加 prerequisitescleanupwhatsnext 小节。

在每个小节中编写内容时,请注意以下规定:

  • 最低使用二级标题(H2,标题前面有两个 # 字符)。模板会自动为每个小节设置标题。
  • overview 节中,用一个段落为整个主题设定语境;
  • prerequisites 节中,尽可能使用项目符号列表。 额外的环境准备条件要加在已包含的条件之后。
  • objectives 节中,使用项目符号列表。
  • lessoncontent 节中,结合使用编号符号列表和叙述性文字。
  • cleanup 节中,使用编号符号列表来描述任务结束后清理集群状态所需要的步骤。
  • whatsnext 节中,使用项目符号列表(不超过 5 项),列举读者可能接下来有兴趣阅读的主题。

已发布的教程主题的一个例子是 使用 Deployment 运行无状态应用.

参考(Reference)

组件工具的参考页面给出的是某个 Kubernetes 组件工具的描述和参数选项输出。 每个页面都是使用组件工具命令基于脚本生成的。

每个工具参考页面可能包含以下小节:

页面小节
synopsis(用法)
options(选项)
options from parent commands(从父命令集成的选项)
examples(示例)
seealso(参考)

已发布的工具参考页面示例包括:

接下来

6 - 内容组织

本网站使用了 Hugo。在 Hugo 中,内容组织是一个核心概念。

页面列表

页面顺序

文档侧方菜单、文档页面浏览器等以 Hugo 的默认排序顺序列出。Hugo 会按照权重(从 1 开始)、 日期(最新的排最前面)排序,最后按链接标题排序。

有鉴于此,如果你想将一个页面或一个章节前移,请在页面头部设置一个较高的权重:

title: My Page
weight: 10

文档主菜单

文档主菜单是从 docs/ 下面的章节构建的。 这些章节在其章节内容文件 _index.md 的头部设置了 main_menu 标志:

main_menu: true

注意,链接标题来自页面的 linkTitle 字段,因此如果希望它与页面标题不同,请在内容文件中更改它:

main_menu: true
title: Page Title
linkTitle: Title used in links

文档侧方菜单

文档侧方菜单是基于 docs/ 下面的当前章节的内容树构建的。

菜单默认显示所有的章节和它们的页面。

如果你不想列出某个章节或页面,请在页面头部将 toc_hide 标志设置为 true

toc_hide: true

当导航到具有内容的章节时,网站将显示出指定的章节或页面(例如 _index.md)。 否则,将显示该章节里的第一个页面。

文档浏览器

文档主页上的页面浏览器是基于 docs section 下一层的所有章节和页面构建的。

如果你不想列出某个章节或页面,请在页面头部将 toc_hide 标志设置为 true

toc_hide: true

主菜单

右上菜单中的网站链接(也出现在页脚中)是通过页面查找构建的。 这是为了确保页面实际存在。因此,如果案例分析章节在网站(或者其本地化版本)中不存在, 则不会出现对应的链接。

页面包

除了独立的内容页面(Markdown 文件), Hugo 还支持页面包

一个例子是定制的 Hugo 短代码(shortcodes)。 它被认为是 leaf bundle(叶子包)。 目录下的所有内容,包括 index.md,都是包的一部分。此外还包括页面间相对链接、可被处理的图像等:

zh-cn/docs/home/contribute/includes
├── example1.md
├── example2.md
├── index.md
└── podtemplate.json

另一个广泛使用的例子是 includes 包。 这类包在页面头部设置 headless: true,意味着它没有得到自己的 URL。它只用于其他页面。

zh-cn/includes
├── default-storage-class-prereqs.md
├── index.md
├── partner-script.js
├── partner-style.css
├── task-tutorial-prereqs.md
├── user-guide-content-moved.md
└── user-guide-migration-notice.md

有关包中文件的一些重要说明:

  • 已翻译的包会从上面的语言继承所有缺失的、非内容文件。这一设计可以避免重复。
  • 包中的所有文件都是 Hugo 所指的 Resources,即使某个语言不支持头部设置(YAML 文件等), 你也可以为每个语言提供诸如参数和标题等元数据。 参见页面资源元数据
  • Resource.RelPermalink 中获得的值是相对于当前页面的。 参见 Permalinks

样式

本网站的样式表的 SASS 源文件存放在 src/sass 下面, 并通过 Hugo 自动构建。

接下来

7 - 定制 Hugo 短代码

本页面将介绍 Hugo 自定义短代码,可以用于 Kubernetes Markdown 文档书写。

关于短代码的更多信息可参见 Hugo 文档

功能状态

在本站的 Markdown 页面(.md 文件)中,你可以加入短代码来展示所描述的功能特性的版本和状态。

功能状态示例

下面是一个功能状态代码段的演示,表明这个功能已经在最新版 Kubernetes 中稳定了。

{{< feature-state state="stable" >}}

会转换为:

特性状态: Kubernetes v1.31 [stable]

state 的可选值如下:

  • alpha
  • beta
  • deprecated
  • stable

功能状态代码

所显示的 Kubernetes 默认为该页或站点版本。 修改 for_k8s_version 短代码参数可以调整要显示的版本。例如:

{{< feature-state for_k8s_version="v1.10" state="beta" >}}

会转换为:

特性状态: Kubernetes v1.10 [beta]

从描述文件中检索特征状态

要动态确定特性的状态,请使用 feature_gate_name 短代码参数,此参数将从 content/en/docs/reference/command-line-tools-reference/feature-gates/ 中相应的特性门控描述文件中提取特性的详细状态信息。

例如:

{{< feature-state feature_gate_name="NodeSwap" >}}

会转换为:

特性状态: Kubernetes v1.30 [beta] (enabled by default: true)

特性门控介绍

在此站点上的 Markdown 页面(.md 文件)中,你可以添加短代码来显示短代码的描述。

特性门控 Demo 演示

下面是特性状态片段的 Demo,它显示该特性在最新的 Kubernetes 版本中处于稳定状态。

{{< feature-gate-description name="DryRun" >}}

会转换为:

DryRun:

启用在服务器端对请求进行 试运行(Dry Run), 以便在不提交的情况下测试验证、合并和变更。

词汇

有两种词汇表提示:glossary_tooltipglossary_definition

你可以通过加入术语词汇的短代码,来自动更新和替换相应链接中的内容 (我们的词汇库) 在浏览在线文档时,术语会显示为超链接的样式,当鼠标移到术语上时,其解释就会显示在提示框中。

除了包含工具提示外,你还可以重用页面内容中词汇表中的定义。

词汇术语的原始数据保存在词汇目录, 每个内容文件对应相应的术语解释。

词汇演示

例如下面的代码在 Markdown 中将会转换为 cluster,然后在提示框中显示。

{{< glossary_tooltip text="cluster" term_id="cluster" >}}

这是一个简短的词汇表定义:

{{< glossary_definition prepend="A cluster is" term_id="cluster" length="short" >}}

呈现为:

A cluster is 一组工作机器,称为节点, 会运行容器化应用程序。每个集群至少有一个工作节点。

你也可以包括完整的定义:

{{< glossary_definition term_id="cluster" length="all" >}}

呈现为:

一组工作机器,称为节点, 会运行容器化应用程序。每个集群至少有一个工作节点。

工作节点会托管 Pod,而 Pod 就是作为应用负载的组件。 控制平面管理集群中的工作节点和 Pod。 在生产环境中,控制平面通常跨多台计算机运行, 一个集群通常运行多个节点,提供容错性和高可用性。

你可以使用 api-reference 短代码链接到 Kubernetes API 参考页面,例如: Pod Pod 参考文件:

{{< api-reference page="workload-resources/pod-v1" >}}

本语句中 page 参数的内容是 API 参考页面的 URL 后缀。

你可以通过指定 anchor 参数链接到页面中的特定位置,例如到 PodSpec 参考,或页面的 environment-variables 部分:

{{< api-reference page="workload-resources/pod-v1" anchor="PodSpec" >}}
{{< api-reference page="workload-resources/pod-v1" anchor="environment-variables" >}}

你可以通过指定 text 参数来更改链接的文本, 例如通过链接到页面的 环境变量部分:

{{< api-reference page="workload-resources/pod-v1" anchor="environment-variables" text="环境变量" >}}

表格标题

通过添加表格标题,你可以让表格能够被屏幕阅读器读取。 要向表格添加标题(Caption), 可用 table 短代码包围表格定义,并使用 caption 参数给出表格标题。

下面是一个例子:

{{< table caption="配置参数" >}}
参数      | 描述        | 默认值
:---------|:------------|:-------
`timeout` | 请求的超时时长 | `30s`
`logLevel` | 日志输出的级别 | `INFO`
{{< /table >}}

所渲染的表格如下:

配置参数
参数描述默认值
timeout请求的超时时长30s
logLevel日志输出的级别INFO

如果你查看表格的 HTML 输出结果,你会看到 <table> 元素后面紧接着下面的元素:

<caption style="display: none;">配置参数</caption>

标签页

在本站的 Markdown 页面(.md 文件)中,你可以加入一个标签页集来显示 某解决方案的不同形式。

标签页的短代码包含以下参数:

  • name:标签页上显示的名字。
  • codelang:如果要在 tab 短代码中加入内部内容,需要告知 Hugo 使用的是什么代码语言,方便代码高亮。
  • include:标签页中所要包含的文件。如果标签页是在 Hugo 的 叶子包中定义, Hugo 会在包内查找文件(可以是 Hugo 所支持的任何 MIME 类型文件)。 否则,Hugo 会在当前路径的相对路径下查找所要包含的内容页面。 注意,在 include 页面中不能包含短代码内容,必须要使用自结束(self-closing)语法。 例如 {{< tab name="Content File #1" include="example1" />}}。 如果没有在 codelang 进行声明的话,Hugo 会根据文件名推测所用的语言。 默认情况下,非内容文件将会被代码高亮。
  • 如果内部内容是 Markdown,你必须要使用 % 分隔符来包装标签页。 例如,{{% tab name="Tab 1" %}}This is **markdown**{{% /tab %}}
  • 可以在标签页集中混合使用上面的各种变形。

下面是标签页短代码的示例。

标签页演示:代码高亮

{{< tabs name="tab_with_code" >}}
{{< tab name="Tab 1" codelang="bash" >}}
echo "This is tab 1."
{{< /tab >}}
{{< tab name="Tab 2" codelang="go" >}}
println "This is tab 2."
{{< /tab >}}
{{< /tabs >}}

会转换为:


echo "This is tab 1."


println "This is tab 2."

标签页演示:内联 Markdown 和 HTML

{{< tabs name="tab_with_md" >}}
{{% tab name="Markdown" %}}
这是**一些 markdown。**
{{< note >}}
它甚至可以包含短代码。
{{< /note >}}
{{% /tab %}}
{{< tab name="HTML" >}}
<div>
	<h3>纯 HTML</h3>
	<p>这是一些 <i>纯</i> HTML。</p>
</div>
{{< /tab >}}
{{< /tabs >}}

会转换为:

这是一些 markdown。

纯 HTML

这是一些 HTML。

标签页演示:文件嵌套

{{< tabs name="tab_with_file_include" >}}
{{< tab name="Content File #1" include="example1" />}}
{{< tab name="Content File #2" include="example2" />}}
{{< tab name="JSON File" include="podtemplate" />}}
{{< /tabs >}}

会转换为:

这是一个内容文件示例,位于一个includes叶子包中。

这是另一个内容文件示例,位于一个includes叶子包中。

  {
    "apiVersion": "v1",
    "kind": "PodTemplate",
    "metadata": {
      "name": "nginx"
    },
    "template": {
      "metadata": {
        "labels": {
          "name": "nginx"
        },
        "generateName": "nginx-"
      },
      "spec": {
         "containers": [{
           "name": "nginx",
           "image": "dockerfile/nginx",
           "ports": [{"containerPort": 80}]
         }]
      }
    }
  }

源代码文件

你可以使用 {{% code_sample %}} 短代码将文件内容嵌入代码块中, 以允许用户下载或复制其内容到他们的剪贴板。 当示例文件的内容是通用的、可复用的,并且希望用户自己尝试使用示例文件时, 可以使用此短代码。

这个短代码有两个命名参数:languagefile, 必选参数 file 用于指定要显示的文件的路径, 可选参数 language 用于指定文件的编程语言。 如果未提供 language 参数,短代码将尝试根据文件扩展名推测编程语言。

例如:

{{% code_sample language="yaml" file="application/deployment-scale.yaml" %}}

输出是:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 4 # 将副本数从 2 更新为 4
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.16.1
        ports:
        - containerPort: 80

添加新的示例文件(例如 YAML 文件)时,在 <LANG>/examples/ 子目录之一中创建该文件,其中 <LANG> 是页面的语言。 在你的页面的 Markdown 文本中,使用 code 短代码:

{{% code_sample file="<RELATIVE-PATH>/example-yaml>" %}}

其中 <RELATIVE-PATH> 是要包含的示例文件的路径,相对于 examples 目录。 以下短代码引用位于 /content/en/examples/configmap/configmaps.yaml 的 YAML 文件。

{{% code_sample file="configmap/configmaps.yaml" %}}

传统的 {{% codenew %}} 短代码将被替换为 {{% code_sample %}}。 在新文档中使用 {{% code_sample %}}

第三方内容标记

运行 Kubernetes 需要第三方软件。例如:你通常需要将 DNS 服务器 添加到集群中,以便名称解析工作。

当我们链接到第三方软件或以其他方式提及它时,我们会遵循内容指南 并标记这些第三方项目。

使用这些短代码会向使用它们的任何文档页面添加免责声明。

列表

对于有关几个第三方项目的列表,请添加:

{{% thirdparty-content %}}

在包含所有项目的段落标题正下方。

项目

如果你有一个列表,其中大多数项目引用项目内软件(例如:Kubernetes 本身,以及单独的 Descheduler 组件),那么可以使用不同的形式。

添加短代码:

在项目之前,或在特定项目的段落下方添加此短代码:

{{% thirdparty-content single="true" %}}

详细信息

你可以使用短代码呈现 <details> HTML 元素:

{{< details summary="有关 widgets 的更多信息" >}}
frobnicator 扩展 API 使用示例运行文本实现 **widgets**
没有哪个人会因为痛苦本身就是令人愉悦的,而选择痛苦,
尽管他们有时因为追求某种快乐而不得不承受痛苦。
但这并不是说他们喜欢痛苦本身,而是因为通过忍受痛苦,他们可以得到更大的快乐。
{{< /details >}}

渲染结果如下:

有关 widgets 的更多信息

frobnicator 扩展 API 使用示例运行文本实现 widgets

没有哪个人会因为痛苦本身就是令人愉悦的,而选择痛苦, 尽管他们有时因为追求某种快乐而不得不承受痛苦。 但这并不是说他们喜欢痛苦本身,而是因为通过忍受痛苦,他们可以得到更大的快乐。

版本号信息

要在文档中生成版本号信息,可以从以下几种短代码中选择。每个短代码可以基于站点配置文件 hugo.toml 中的版本参数生成一个版本号取值。最常用的参数为 latestversion

{{< param "version" >}}

{{< param "version" >}} 短代码可以基于站点参数 version 生成 Kubernetes 文档的当前版本号取值。短代码 param 允许传入一个站点参数名称,在这里是 version

转换为:

v1.31

{{< latest-version >}}

{{< latest-version >}} 返回站点参数 latest 的取值。每当新版本文档发布时,该参数均会被更新。 因此,参数 latestversion 并不总是相同。

转换为:

v1.31

{{< latest-semver >}}

{{< latest-semver >}} 短代码可以生成站点参数 latest 不含前缀 v 的版本号取值。

转换为:

1.31

{{< version-check >}}

{{< version-check >}} 会检查是否设置了页面参数 min-kubernetes-server-version 并将其与 version 进行比较。

转换为:

要获知版本信息,请输入 kubectl version.

{{< latest-release-notes >}}

{{< latest-release-notes >}} 短代码基于站点参数 latest 生成不含前缀 v 的版本号取值,并输出该版本更新日志的超链接地址。

转换为:

https://git.k8s.io/kubernetes/CHANGELOG/CHANGELOG-1.31.md

接下来