Files
zhuangang/topics/devops/k8s/examples/agent-api/test_manifests.py
T

64 lines
2.3 KiB
Python

# 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 不应提交到仓库"