编写软件模板与 TechDocs
目标
亲手编写 Backstage 软件模板的三个层次——parameters、steps、output,并创建 TechDocs 所需的 mkdocs 配置和骨架实体。最后,把该模板将生成的工作负载部署到真实集群中并确认结果。
为什么重要
脚手架的价值不在于减少输入,而在于让经过验证的路径成为默认选择。平台团队曾经踩过的坑——例如需要特定的 CRD 版本,或必须使用某条绕行路径——一旦固化到骨架和文档中,其他人就不必重蹈覆辙。结构本身也很重要。parameters 使用 JSON Schema,因此错误输入会在表单阶段被拦截;steps 是可复用操作的组合,因此创建新模板时不必重新实现仓库创建和目录注册。还有一点容易忽略:执行 publish:github 的不是用户浏览器,而是 Backstage 后端。令牌只保存在服务器上,因此通过门户提供自助服务,比把令牌发给所有开发者更安全。本环境中没有 Backstage,因此模板以文件形式编写,评分也会读取文件;只有最后一步会使用真实集群。
步骤
- 编写
/root/cba-template/template.yaml——apiVersion: scaffolder.backstage.io/v1beta3、kind: Template、metadata.name: node-service、metadata.title可填写任意值、metadata.tags的第一项为nodejs、spec.owner: group:team-platform、spec.type: service。 - 在同一文件中添加
spec.parameters——数组第一项包含title(任意值);required为[name, owner];properties.name包含type: string、pattern: '^[a-z0-9-]+$'和title;properties.owner包含type: string和title。 - 在同一文件中添加
spec.steps——必须恰好有 3 项,依次为id: fetch(action 为fetch:template,input.url: ./skeleton,input.values.name使用 name 参数的替换表达式)、id: publish(action 为publish:github)、id: register(action 为catalog:register,input.repoContentsUrl引用 publish 步骤的输出,input.catalogInfoPath: /catalog-info.yaml)。 - 在同一文件中添加
spec.output——links第一项的title为Repository,url引用 publish 步骤输出的remoteUrl,entityRef引用 register 步骤输出的entityRef。 - 编写
/root/cba-template/mkdocs.yml——site_name可填写任意值,nav第一项为Home: index.md,plugins第一项为techdocs-core。然后在/root/cba-template/docs/index.md中写一行以#开头的标题和一段说明。 - 编写
/root/cba-template/skeleton/catalog-info.yaml——kind: Component;metadata.name使用模板值替换表达式(字符串中必须包含values.name);在metadata.annotations中加入backstage.io/techdocs-ref: dir:.和backstage.io/kubernetes-id: node-service;设置spec.type: service、spec.lifecycle: experimental;spec.owner使用 owner 值替换表达式。 - 把模板将生成的结果部署到集群。创建命名空间
cba-scaffold,并在其中创建 Deploymentnode-service(标签为backstage.io/kubernetes-id: node-service和app.kubernetes.io/part-of: cba-platform,镜像为node:22-alpine,replicas 为2,Pod 模板标签中也要加入相同的backstage.io/kubernetes-id)、Servicenode-service(port 为80,targetPort 为3000),以及 ConfigMapnode-service-techdocs(键techdocs-ref的值必须与第 6 步骨架中的注解值完全相同)。
参考
- 替换表达式的形式是在双花括号前加美元符号。表单输入通过
parameters.<이름>引用,前序步骤的结果通过steps.<id>.output.<필드>引用。 - 请用双引号包住替换表达式,避免 YAML 解析器把花括号误认为流式映射。
publish:github的输出包含remoteUrl和repoContentsUrl,catalog:register的输出包含entityRef。- 常见错误 1:把 Template 的 apiVersion 写成
backstage.io/v1alpha1。脚手架使用的是scaffolder.backstage.io/v1beta3。 - 常见错误 2:把
parameters写成单个对象。为了支持多个页面,它必须是数组。 - 常见错误 3:在骨架的
metadata.name中写死固定字符串。该文件由模板生成,因此这里必须使用替换表达式。
Template 清单骨架
编写 /root/cba-template/template.yaml——apiVersion: scaffolder.backstage.io/v1beta3、kind: Template、metadata.name: node-service、metadata.title 可填写任意值、metadata.tags 的第一项为 nodejs、spec.owner: group:team-platform、spec.type: service。
Template 与目录实体使用不同的 apiVersion。请使用脚手架专用组,所有者则沿用其他实体的引用格式。
parameters——用户表单
在同一文件中添加 spec.parameters——数组第一项包含 title(任意值);required 为 [name, owner];properties.name 包含 type: string、pattern: '^[a-z0-9-]+$' 和 title;properties.owner 包含 type: string 和 title。
parameters 是页面数组,每个页面都是 JSON Schema。请确认必填项列表和属性定义各自应放在哪里。
steps——操作的组合
在同一文件中添加 spec.steps——必须恰好有 3 项,依次为 id: fetch(action 为 fetch:template,input.url: ./skeleton,input.values.name 使用 name 参数的替换表达式)、id: publish(action 为 publish:github)、id: register(action 为 catalog:register,input.repoContentsUrl 引用 publish 步骤的输出,input.catalogInfoPath: /catalog-info.yaml)。
每个步骤都包含 id、name、action 和 input。想一想获取骨架、创建仓库、注册目录分别对应哪个 action 名称。
output——完成后显示的内容
在同一文件中添加 spec.output——links 第一项的 title 为 Repository,url 引用 publish 步骤输出的 remoteUrl,entityRef 引用 register 步骤输出的 entityRef。
前序步骤的结果通过步骤 id 引用。请判断仓库地址和已注册实体引用分别来自哪个步骤的输出。
mkdocs 配置与文档
编写 /root/cba-template/mkdocs.yml——site_name 可填写任意值,nav 第一项为 Home: index.md,plugins 第一项为 techdocs-core。然后在 /root/cba-template/docs/index.md 中写一行以 # 开头的标题和一段说明。
TechDocs 使用 mkdocs。配置文件需要站点名称、导航目录以及 TechDocs 插件。
骨架中的 catalog-info.yaml
编写 /root/cba-template/skeleton/catalog-info.yaml——kind: Component;metadata.name 使用模板值替换表达式(字符串中必须包含 values.name);在 metadata.annotations 中加入 backstage.io/techdocs-ref: dir:. 和 backstage.io/kubernetes-id: node-service;设置 spec.type: service、spec.lifecycle: experimental;spec.owner 使用 owner 值替换表达式。
这是模板将生成的文件,因此名称位置要写替换表达式,而不是具体值。也不要忘记指向文档位置的注解。
将生成结果应用到集群
把模板将生成的结果部署到集群。创建命名空间 cba-scaffold,并在其中创建 Deployment node-service(标签为 backstage.io/kubernetes-id: node-service 和 app.kubernetes.io/part-of: cba-platform,镜像为 node:22-alpine,replicas 为 2,Pod 模板标签中也要加入相同的 backstage.io/kubernetes-id)、Service node-service(port 为 80,targetPort 为 3000),以及 ConfigMap node-service-techdocs(键 techdocs-ref 的值必须与第 6 步骨架中的注解值完全相同)。
亲手部署模板将生成的工作负载。骨架中填写的文档引用值必须与写入集群的值一致。