目录一致性诊断与门禁
目标
对接手的目录进行静态诊断,找出四类缺陷,制作修复后的副本,并把同样的检查固化为在 PR 中运行的 lint 门禁。本环境没有 Backstage,因此所有诊断都通过读取文件完成。
为什么重要
目录并不是在注册时损坏,而是会随着时间逐渐腐化。大多数腐化问题不会被 Backstage 报错。违反架构的实体会显示错误,但指向不存在目标的引用通常只是无法计算关系,最终在界面上呈现为空白。空白页面不像故障,因此没人报告,也就没人修复。本实验中的四类问题,正是实际环境中反复出现的模式。尤其要养成在比较引用前先进行规范化的习惯。team-orders、group:team-orders 和 group:default/team-orders 指向同一对象,如果直接比较字符串,就会把正常引用误报为缺陷。最后一步的 lint 门禁如果只验证干净输入返回 0,也只完成了一半。只有在故意注入缺陷时返回非 0,这个门禁才真正保护了什么。
步骤
- 在
/root/cba-audit/incoming/中按下述内容原样创建八个文件。它们都使用apiVersion: backstage.io/v1alpha1。明确说明缺失的字段不要补上。component-orders.yaml— Componentorders-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-orders,spec.system: commerce-core,spec.providesApis第一项为orders-api,spec.dependsOn两项为resource:orders-db和component:ledger-service。component-ledger.yaml— Componentledger-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-ledger,spec.system: finance-core,spec.dependsOn第一项为component:orders-service。component-report.yaml— Componentreport-worker,spec.type: service,spec.owner: group:team-analytics,spec.system: commerce-core,spec.dependsOn第一项为resource:analytics-warehouse。缺少spec.lifecycle。api-orders.yaml— APIorders-api,spec.type: openapi,spec.lifecycle: production,spec.system: commerce-core。缺少spec.owner。resource-orders-db.yaml— Resourceorders-db,spec.type: database,spec.owner: group:team-storage,spec.system: commerce-core。system-commerce-core.yaml— Systemcommerce-core,spec.owner: group:team-orders,spec.domain: retail-ops。group-team-orders.yaml— Groupteam-orders,spec.type: team。group-team-ledger.yaml— Groupteam-ledger,spec.type: team。
- 在
/root/cba-audit/missing-required.txt中逐行写出缺失必填字段的位置。格式为<정규화된 엔티티 참조> <필드 경로>。所有 kind 共同的必填字段是apiVersion、kind、metadata.name;此外,Component 和 API 还要求spec.type、spec.lifecycle、spec.owner,Resource 要求spec.type、spec.owner,System 和 Domain 要求spec.owner,Group 要求spec.type。 - 在
/root/cba-audit/dangling-owners.txt中记录spec.owner指向本目录中不存在的组的情况。格式为<엔티티 참조> <정규화한 소유자 참조>。所有者的默认 kind 是group,默认命名空间是default。 - 在
/root/cba-audit/dangling-refs.txt中记录除所有者外的其他引用指向不存在目标的情况。目标字段是spec.system(默认 kind 为 system)、spec.domain(domain)、spec.dependsOn(component)、spec.providesApis(api)。格式为<가리킨 쪽 참조> <없는 대상의 참조>。 - 在
/root/cba-audit/dependency-cycle.txt中逐行写出沿spec.dependsOn边遍历时处于循环中的实体引用。只统计指向实际存在实体的边。 - 在
/root/cba-audit/fixed/中创建修复后的目录。对fixed/重新执行第 2~5 步的四项诊断时,结果必须全部为 0,并且incoming/中原有的八个实体必须保持 kind 和名称不变且全部保留。必要时可以新建缺失的实体。 - 编写
/root/cba-audit/lint.sh。检查第一个参数所指向的目录:若存在任何必填字段缺失或指向不存在目标的引用,则以非 0 退出;若没有问题,则以 0 退出。评分器会用incoming/、fixed/以及两个分别注入单个缺陷的目录来运行此脚本。 - 将审计结果保存到集群中。创建命名空间
cba-audit(标签为app.kubernetes.io/part-of: developer-portal),并在其中创建 ConfigMapcatalog-audit。它包含三个键:incoming-findings为第 2~5 步发现的缺陷总数,fixed-findings为0,entities为fixed/中的实体文件数。
参考
- 引用格式为
[<kind>:][<namespace>/]<name>,比较前必须规范化。 - 不同字段的默认 kind 不同:
spec.owner是 group,spec.system是 system,spec.dependsOn是 component。 - 常见错误 1:删除有缺陷的实体来让列表看起来干净。被隐藏的服务也会在凌晨三点出故障。
- 常见错误 2:先逐个修复实体。如果不先创建缺失的 Group 和 Domain,就会对同一位置重复修改。
- 常见错误 3:只用干净输入测试 lint。无论如何都返回 0 的门禁还不如没有。
重现接手的目录
在 /root/cba-audit/incoming/ 中按下述内容原样创建八个文件。它们都使用 apiVersion: backstage.io/v1alpha1。明确说明缺失的字段不要补上。
component-orders.yaml— Componentorders-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-orders,spec.system: commerce-core,spec.providesApis第一项为orders-api,spec.dependsOn两项为resource:orders-db和component:ledger-service。component-ledger.yaml— Componentledger-service,spec.type: service,spec.lifecycle: production,spec.owner: group:team-ledger,spec.system: finance-core,spec.dependsOn第一项为component:orders-service。component-report.yaml— Componentreport-worker,spec.type: service,spec.owner: group:team-analytics,spec.system: commerce-core,spec.dependsOn第一项为resource:analytics-warehouse。缺少spec.lifecycle。api-orders.yaml— APIorders-api,spec.type: openapi,spec.lifecycle: production,spec.system: commerce-core。缺少spec.owner。resource-orders-db.yaml— Resourceorders-db,spec.type: database,spec.owner: group:team-storage,spec.system: commerce-core。system-commerce-core.yaml— Systemcommerce-core,spec.owner: group:team-orders,spec.domain: retail-ops。group-team-orders.yaml— Groupteam-orders,spec.type: team。group-team-ledger.yaml— Groupteam-ledger,spec.type: team。
严格按照说明创建。明确标为缺失的字段不要补上,这些缺陷正是后续步骤要诊断的对象。
诊断必填字段缺失
在 /root/cba-audit/missing-required.txt 中逐行写出缺失必填字段的位置。格式为 <정규화된 엔티티 참조> <필드 경로>。所有 kind 共同的必填字段是 apiVersion、kind、metadata.name;此外,Component 和 API 还要求 spec.type、spec.lifecycle、spec.owner,Resource 要求 spec.type、spec.owner,System 和 Domain 要求 spec.owner,Group 要求 spec.type。
不同 kind 的必填字段不同。Component 和 API 都需要 type、lifecycle、owner 三项,Resource 需要两项,System 和 Domain 需要 owner 一项。
诊断失效的所有者引用
在 /root/cba-audit/dangling-owners.txt 中记录 spec.owner 指向本目录中不存在的组的情况。格式为 <엔티티 참조> <정규화한 소유자 참조>。所有者的默认 kind 是 group,默认命名空间是 default。
所有者值可以省略 kind,因此比较前必须进行规范化。命名空间的默认值是 default。
诊断失效的其他引用
在 /root/cba-audit/dangling-refs.txt 中记录除所有者外的其他引用指向不存在目标的情况。目标字段是 spec.system(默认 kind 为 system)、spec.domain(domain)、spec.dependsOn(component)、spec.providesApis(api)。格式为 <가리킨 쪽 참조> <없는 대상의 참조>。
除所有者外,还有四个字段会引用其他目标。每个字段的默认 kind 不同,规范化时必须使用正确的 kind。
诊断依赖循环
在 /root/cba-audit/dependency-cycle.txt 中逐行写出沿 spec.dependsOn 边遍历时处于循环中的实体引用。只统计指向实际存在实体的边。
只需沿 dependsOn 遍历。仅统计指向实际存在实体的边,并找出在这些边上存在路径能够回到自身的实体。
修复后的目录
在 /root/cba-audit/fixed/ 中创建修复后的目录。对 fixed/ 重新执行第 2~5 步的四项诊断时,结果必须全部为 0,并且 incoming/ 中原有的八个实体必须保持 kind 和名称不变且全部保留。必要时可以新建缺失的实体。
先补齐组织数据,再修复分组关系,最后修改各个实体。删除有缺陷的实体来让列表变干净并不算修复。
在 PR 中运行的 lint 门禁
编写 /root/cba-audit/lint.sh。检查第一个参数所指向的目录:若存在任何必填字段缺失或指向不存在目标的引用,则以非 0 退出;若没有问题,则以 0 退出。评分器会用 incoming/、fixed/ 以及两个分别注入单个缺陷的目录来运行此脚本。
门禁仅在干净输入时返回 0 还不够。务必故意注入缺陷,确认它会返回非 0;评分器也会这样测试。
将审计结果保存到集群
将审计结果保存到集群中。创建命名空间 cba-audit(标签为 app.kubernetes.io/part-of: developer-portal),并在其中创建 ConfigMap catalog-audit。它包含三个键:incoming-findings 为第 2~5 步发现的缺陷总数,fixed-findings 为 0,entities 为 fixed/ 中的实体文件数。
不要手工计数,而应根据前面步骤的产物计算这些数字。评分器会从原始目录重新计算并核对。