# requires: yaml """对清单做团队规范检查(kubeconform 只校验结构,这里检查“写对了但不合规范”的问题)。 运行:pytest -q test_manifests.py 结构校验(可选):kubeconform -strict -summary *.yaml """ from pathlib import Path import yaml HERE = Path(__file__).parent def load_all() -> list[dict]: docs = [] for f in sorted(HERE.glob("*.yaml")): docs += [d for d in yaml.safe_load_all(f.read_text(encoding="utf-8")) if d] return docs DOCS = load_all() def by_kind(kind: str) -> list[dict]: return [d for d in DOCS if d["kind"] == kind] def test_selector_matches_pod_labels(): for dep in by_kind("Deployment"): sel = dep["spec"]["selector"]["matchLabels"] labels = dep["spec"]["template"]["metadata"]["labels"] assert sel.items() <= labels.items() for svc in by_kind("Service"): assert svc["spec"]["selector"].items() <= labels.items(), "Service 选择器和 Pod 标签不一致" def test_containers_follow_rules(): for dep in by_kind("Deployment"): for c in dep["spec"]["template"]["spec"]["containers"]: image = c["image"] assert ":" in image.rsplit("/", 1)[-1] and not image.endswith(":latest"), "镜像必须固定版本" assert "requests" in c["resources"] and "memory" in c["resources"].get("limits", {}) for probe in ("readinessProbe", "livenessProbe"): assert probe in c, f"缺少 {probe}" assert c["securityContext"]["allowPrivilegeEscalation"] is False for e in c.get("env", []): assert "value" not in e or "KEY" not in e["name"].upper(), "密钥不能明文写在清单中" def test_rolling_update_keeps_capacity(): for dep in by_kind("Deployment"): ru = dep["spec"]["strategy"]["rollingUpdate"] assert ru["maxUnavailable"] == 0 def test_pdb_lower_than_min_replicas(): hpa_min = min(h["spec"]["minReplicas"] for h in by_kind("HorizontalPodAutoscaler")) for pdb in by_kind("PodDisruptionBudget"): assert pdb["spec"]["minAvailable"] < hpa_min, "PDB 要求的可用数不小于副本数会导致节点无法驱逐" def test_no_secret_objects_in_repo(): assert not by_kind("Secret"), "Secret 不应提交到仓库"