feat: 按 doc_id 重组 ansible/files 与验证框架

- ansible/files 改为与文档 XX-YY 对齐的目录结构,更新相关 playbook 路径
- 新增 scripts/verify.sh 与 ansible/playbooks/verify/*.yml,移除单体 verify-matrix.yml
- 补充 docs/00-02 矩阵状态、00-05 验证框架与流程、00-04 环境与 ylc65 工作机说明
- 增加 k3s 存储准备、Longhorn、local-path 等 playbook 与辅助脚本

Made-with: Cursor
This commit is contained in:
2026-03-26 07:01:14 +08:00
parent a67788de56
commit 8c43761962
192 changed files with 4006 additions and 320 deletions

View File

@@ -0,0 +1,196 @@
# 00-05-测试与验证框架(设计说明)
> 本页是“测试与验证框架”的设计说明,并与仓库里已落地的 `scripts/verify.sh` + `ansible/playbooks/verify/` 对齐。
## 1. 为什么需要它
仓库里 `docs/00-02-验证矩阵.md` 目前扮演“待验证列表/状态记录”的角色,用来回答:
- 这篇文档(`XX-YY`)是否已经在你的实验环境中从头到尾跑通?
- 如果没跑通,缺口在哪里?
而“自动化执行”和“状态记录”是两件不同的事。测试框架需要把自动化执行能力,拆成可维护的小块,并通过统一的 id/索引把文档与用例关联起来。
## 2. 自动化验证流程(一般步骤)
下面是一条**从操作者视角**的通用流水线;本仓库里对应关系已写在各步括号中。
1. **接入目标环境**
- 用 SSH 登录**控制节点**(或在本机配置好到控制节点的 Ansible `inventory`,由 Ansible 代你 SSH
- 在仓库根(或文档约定目录)准备好代码:`git pull` / `scp` 同步等,与 [`docs/00-04-部署环境说明.md`](00-04-部署环境说明.md) 一致。
- 按需加载验证环境变量:复制并填写 [`scripts/.env.verify.example`](../scripts/.env.verify.example) 为 `scripts/.env.verify`,执行前 `source``verify.sh` 会自动尝试加载)。
2. **环境与前置清理(按验证目标选择深度)**
- **基本检查**`kubectl get nodes`、磁盘/内核版本、防火墙与文档是否一致;必要时对照 `00-04`
- **轻量清理(本仓库 `verify.sh` 的常态)**:默认不卸载整个 K3s每个 `verify/XX-YY.yml`**teardown** 阶段只删除**本篇** apply 过的资源(或 gate 未执行 apply 时跳过删除),避免污染下一用例。
- **重度清理(重装/复现安装文档时)**:若你要从「空机」验证 `01-01` 等**整集群安装**流程,才需要按文档执行 `k3s-uninstall.sh`、删数据目录、清 iptables 等——这与日常「矩阵逐项验收」是**不同场景**,不要默认混进每一次 `run-all`
3. **部署**
- **推荐(本仓库)**:用 Ansible playbook 部署——要么是正式安装/初始化类(如 `k3s-init-and-install.yml`),要么是验证用例里的 `kubectl apply` / `helm install` / `import_playbook`
- **文档中的 bash 一键命令**:仍可按 `docs/` 逐步执行;适合排障或 playbook 尚未覆盖的边角。自动化验收应尽量**收敛进** `ansible/playbooks/verify/*.yml`,避免「文档一套、手敲一套」长期分叉。
4. **按设计目标做断言**
- **集群侧**`kubectl get` / `describe` / `logs``kubectl rollout status`、必要时看事件与 `Endpoints`
- **入口侧**:在控制节点或文档指定的入口上对 `Service`/`Ingress`/`IngressRoute``curl`(本仓库 nginx 矩阵等用响应头 `X-Backend` 或状态码区分路径)。
- **Helm / 存储 / 网络**:按该篇文档的「预期」增查命令(如 `helm list``PVC Bound`、跨节点 curl
- 依赖外部云账号、NFS、ACME 邮箱等时:未满足条件可用 **gate 跳过** apply并在矩阵备注中写明「未配变量未验」。
5. **收尾与记录**
- 默认 **`VERIFY_TEARDOWN=1`**:验证通过后删除临时资源,减少对共享实验集群的干扰;调试时可设 `0` 保留现场。
- 将结论写回 [`docs/00-02-验证矩阵.md`](00-02-验证矩阵.md)(状态与备注),必要时更新对应 `docs/XX-YY-*.md` 中的命令或版本说明。
6. **本仓库一键串联**
- 在控制节点仓库根执行:`./scripts/verify.sh run-all`(或 `run <XX-YY>`),即按矩阵顺序重复「部署 → 断言 → teardown」的自动化版本缺 playbook 会 **fail-fast**
### 2.1 局限与约定补全(建议在文档与 `verify/XX-YY.yml` 中写死)
下列能力 **不会**`verify.sh` 自动推断;必须在对应 `docs/XX-YY-*.md` 里写清「谁执行、对哪里发请求、怎样算过」,并在 playbook 里逐项实现。**未写进 playbook 的步骤即视为未自动化覆盖**。
| 主题 | 建议约定 |
|------|----------|
| **多节点:在哪台机器 `curl`** | **默认**:在 inventory 的 **`k3s_server`(控制节点)** 上,对 **集群入口** 发 HTTP`nginx_entry_base` / `http://<控制节点或 LB IP>`),与「从集群外经 NodePort/主机网络进 Traefik」一致。**例外**(必须显式写):要验 worker 仅内网、跨节点路径、或「必须从某台 agent 访问」时,在 playbook 里对指定 host 执行 `curl`(或 `delegate_to` / 专用 play并在文档「验证命令」中写明 **执行主机与目标 URL**,避免隐含「任意节点等价」。 |
| **TLS / SNI** | 自签或跳过校验仅用于排障:`curl -k`。**验收**应优先:真实证书路径下用 `curl -v` 看证书链;或用 `curl --resolve <域名>:443:<入口IP> https://<域名>/...`**无 DNS** 时模拟 SNI。需要时用 `openssl s_client -connect host:443 -servername <域名> </dev/null` 看握手。ACME 类用例依赖 **公网 80/443、有效邮箱、DNS/Secret**gate 跳过 apply 时,矩阵应标 **⚠️**,不得记成 ✅。 |
| **仅浏览器可用的 UI** | Traefik Dashboard OAuth、依赖 JS/CSP/WebSocket 的交互、文件上传等,`curl` 往往不够。约定三选一:**(1)** 自动化降级为只断言 `IngressRoute`/Deployment/Service 存在 + HTTP 非 5xx**(2)** 在 `00-02` 备注 **「UI 需手工浏览器验收」****(3)** 另起 CI/脚本用 headless如 Playwright`verify.sh` **并列**,不强行塞进 Ansible。 |
| **Helm 长耗时:超时与重试** | 安装/升级统一带 **`--wait` 与合理 `--timeout`**(大 chart 可 10m20m 量级按实际调。Ansible 侧对「Pod 未就绪」可用 **`until` + `retries` + `delay`** 轮询,避免单次 `kubectl` 瞬断误判。文档写清 **最短等待** 与失败时要看 **`helm status` / `kubectl describe` / 事件**。调试设 `VERIFY_TEARDOWN=0` 保留现场。 |
| **CI 无真集群** | 与实验室 **`verify.sh run-all` 不等价**。可选:**kubeconform** 等对清单做离线 schema有短时 apiserver 时用 **`kubectl apply --dry-run=server`**;或用 **kind/k3d** 起临时集群跑子集用例。应在 CI 配置或 `README` 中写明 **「本流水线只保证 YAML/静态;矩阵级验收仍以控制节点 run-all 为准」**,避免混为一谈。 |
**原则**:每篇文档至少有一句话说明 **验证命令的执行位置**(控制节点 / 指定 worker / 办公机经 VPN**成功判据**状态码、响应头、kubectl 资源相位playbook 与文档冲突时以 **先修 playbook、再改文档** 对齐。
## 3. 执行框架(与仓库一致)
此前设想的「静态层yamllint / kubeconform / ansible-lint→ 运行时 → 追溯」**未纳入**当前落地实现;若日后在 CI 里加格式或 schema 检查,应与 `verify.sh` **并列**,不必塞进同一脚本。
本仓库**实际**验收路径只有下面几条,且都以 **Ansible 为执行引擎**(在控制节点上对集群下发 `kubectl` / `helm` / `curl` 等):
1. **`docs/00-02-验证矩阵.md`**:列出 `XX-YY` 与顺序;`verify.sh run-all` 按文中首次出现的 `XX-YY` 依次执行。
2. **`scripts/verify.sh`**:调用 `ansible-playbook -i <inventory> ansible/playbooks/verify/<doc_id>.yml`;缺对应 playbook 则 **fail-fast**
3. **`ansible/playbooks/verify/<doc_id>.yml`**:单篇用例,通常拆成「部署 → 验证 → 清理」多个 **play**(默认 **`VERIFY_TEARDOWN=1`** 做 teardown
4. **特例**:无集群动作的文档可走 **`verify/_noop-tasks.yml`**(仓库路径/文件存在性);依赖 NFS、ACME、Cloudflare 等外部条件的可用 **gate 跳过** applyteardown 需避免「无清单仍删」类失败(各 playbook 已按此收敛)。
**真源**:可部署清单以 **`ansible/files/`** 为准;`docs/XX-YY-*.md` 与矩阵通过同一 **`doc_id`** 与 playbook 对齐。矩阵里的状态/备注仍建议 **手工** 维护(见 §7
## 4. 文档 id 与用例索引
约定:
- `docs/XX-YY-*.md` 的文档 id 为 `XX-YY`(例如 `02-05`)。
- 自动化用例文件名为 `verify/XX-YY.yml`,与 `doc_id` 一致即可playbook 内不必再写 YAML 字段 `doc_id`,除非你想自检)。
- 框架通过 `doc_id` 把“文档”映射到 `verify/<doc_id>.yml`,从而实现按篇自动执行(`verify.sh`)。
这样你在 `00-02` 里更新状态时,不需要关心脚本内部结构;只要 id 一致就能追溯。
## 5. 用例数据模型(建议)
建议把用例写成“按文档 id 编排的任务集合”。在本仓库里,**用例落在** `ansible/playbooks/verify/<XX-YY>.yml`,不再使用单体 `verify-matrix.yml`(已移除,避免与拆分后的 playbook 双份维护)。
- 文档 id `XX-YY` → 文件 `verify/XX-YY.yml`
- 每个文件内一般拆为三段(多个 play 或顺序 tasks
示例02-05`./scripts/verify.sh run 02-05` 执行 `ansible/playbooks/verify/02-05.yml`(内部 `import_playbook` `nginx-matrix-deploy.yml`,再 HTTP 校验四路径,最后 teardown`02-01``02-04` 另有单路径 playbook便于单独调试。
每个 `verify/XX-YY.yml` 的典型结构为三段:
- **deploy**`kubectl apply` / `helm install`
- **verify**`kubectl rollout status` / `curl` / `assert`
- **teardown**`kubectl delete` / `helm uninstall`(默认执行,可用 `VERIFY_TEARDOWN=0` 关闭)
```yaml
doc_id: "02-05"
case_id: "nginx-matrix-all"
description: "02-05 四条路径均返回 200并区分后端内容"
apply:
paths:
- "ansible/files/02-05-nginx-matrix/"
strategy: "apply-r"
wait:
namespace: "default"
deployments:
- "nginx-m1"
- "nginx-m2"
- "nginx-m3"
- "nginx-m4"
timeout: "180s"
http_check:
entry_base: "http://<入口IP>"
paths:
- path: "/demo-m1/"
expect_status: 200
expect_body_contains: "Backend: M1"
- path: "/demo-m2/"
expect_status: 200
expect_body_contains: "Backend: M2"
```
## 6. 执行器Executor——两类在 Ansible 中落地)
测试框架的执行器应当清晰分成两类,对应两种“被测对象”(机器 vs 集群):
### 6.1 Ansible 远程命令类(普通 Linux / 设备执行命令)
- 目标:在普通 Linux/路由/设备上通过 `ssh` 执行命令,并做断言(例如 `exit_code``stdout_contains/regex``file_exists`)。
- 不强制要求在这类执行器里做 HTTP/curl 校验HTTP/服务可用性校验归到 K3s 类用例。
落地方式Ansible 的 `command/shell` + `assert`inventory 决定 SSH 目标与用户/密钥)。
### 6.2 Ansible K3s 集群类(部署 + 结果校验 + 可选清理)
- 目标:对 K3s 集群做 `apply` / `wait` / `check` / `http_check`(可选),并支持可选 `teardown/delete`
- 执行位置分两种:
- 本机直接 `kubectl`
-`kubectl` 需要通过 SSH 在控制节点执行(复用你现有的 `.env.verify` 变量语义)
落地方式Ansible 在控制节点(如 ylc61执行 `kubectl` / `helm` / `curl`,多个 play 顺序执行。默认策略:验证完成后 **执行 teardown**(清理部署),可通过 `VERIFY_TEARDOWN=0` 关闭。
## 7. 状态记录与写回策略
你已经在 `docs/00-02-验证矩阵.md` 里定义了状态含义(未验证/部分验证/已验证)。
建议未来的写回策略分两步:
- 首先:仍然由你手工更新 `00-02`(减少自动化失败导致的误写)
- 之后:如果要自动写回,则需要明确“失败判定标准、覆盖范围、并发策略”,避免多个执行器同时写同一条状态。
## 8. 与旧自动化的关系
- `docs/00-02-验证矩阵.md` 不承担执行细节,只作待验证列表与状态记录
- 自动化执行以 `scripts/verify.sh``ansible/playbooks/verify/*.yml` 为准;本页描述其约定与扩展方式
## 9. 可选扩展(未落地)
当前「一篇文档 → 一个 `verify/XX-YY.yml`」在规模小时最简单:**入口仍是 `scripts/verify.sh`**,不必为了「架构感」提前建一堆目录。当出现下面任一情况时,再考虑本节里的拆法即可。
### 9.1 何时值得拆
- **重复**:多个 playbook 里出现相同的 `kubectl rollout status``curl` 重试、gate + teardown 模板,改一处要改十处。
- **体积**:单个 `XX-YY.yml` 过长,难以一眼看清「本篇到底验了什么」。
- **复用非 Ansible 逻辑**:例如要在本机做纯文本处理、复杂拼接,再交给 Ansible这类少量逻辑可以放在 shell大量仍建议用 Ansibleinventory、变量、幂等已有约定
### 9.2 Ansible 侧:角色与 `include_tasks`(优先)
与正式部署 playbook 一样,验证逻辑**优先**留在 Ansible 生态里拆:
- **`include_tasks`** 或 **`import_tasks`**:把「等 Deployment」「带重试的 HTTP 检查」「安全 delete」抽成 `ansible/playbooks/verify/_*.yml` 小文件,由各 `XX-YY.yml` 引用。
- **Role**(例如 `ansible/roles/k3s_verify_http/`):当同一套「变量约定 + 多 task」在多篇文档复用时用 role 比复制粘贴更清晰;`verify.sh` **不需要改**,仍只调用 `verify/XX-YY.yml`,由该文件 `roles:``import_role` 即可。
原则:**`verify.sh` 只认 `verify/<doc_id>.yml` 这一层文件名**;底下怎么组织 include/role 是内部重构。
### 9.3 `scripts/lib/`(次要)
适合只放 **bash 层**的薄工具:解析矩阵、拼 `ansible-playbook` 参数、统一日志格式等。若把「怎么 curl」「怎么 kubectl wait」写进大量 shell容易和 inventory、sudo、`KUBECONFIG` 两套路径打架,**一般不如 Ansible task**
### 9.4 单独的 `tests/` 目录(与现框架并列)
若将来引入 **非 Ansible** 的测试运行器(例如用编程语言写契约测试、或只跑静态检查),可以建 `tests/` 存放用例与配置,由 **CI 或另一条脚本** 调用;它与 `verify.sh`**并列流水线**,而不是替换关系:
- **矩阵验收 / 真机集群路径**:仍以 `verify.sh` + `verify/*.yml` 为准。
- **PR 上的快速反馈**:可对 `ansible/files/**/*.yaml` 跑 yamllint、kubeconform、`kubectl apply --dry-run=server`(需集群凭据时再决定挂不挂 CI
这样不会出现「同一篇文档到底以哪套测试为准」的模糊地带:文档级约定验收看矩阵 + verify playbook代码库卫生看 CI。
### 9.5 静态检查(再次强调)
yamllint、ansible-lint、schema 校验等 **不放进 `verify.sh`** 亦可:在 GitHub Actions / 本地 pre-commit 里单独跑即可。与 §3 一致——与运行时验证 **并列**,互不嵌套。