admissionreview 的 request.object 有时为 nil,因 kubernetes 仅在 create/update 请求且客户端提交有效 body 时填充该字段;delete、get 等请求或无 body 时不填充。

为什么 AdmissionReview 的 request.object 有时是 nil?
因为 Kubernetes 在某些请求类型(如 DELETE、GET)或资源未带完整 body 时,不会填充 request.object 字段;只有 CREATE/UPDATE 类请求且客户端提交了有效 body,它才非空。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 永远先检查
req.Request.Object.Raw是否为空字节,再尝试反序列化;不要直接解包req.Request.Object.Object - 对
DELETE或PATCH请求,真正要校验或修改的往往是request.oldObject(UPDATE)或request.namespace/request.name(DELETE) - 用
scheme.Default(&obj)预填充默认字段,避免因缺失 optional 字段导致解码后结构体字段为零值而误判
如何安全地修改 Pod 的 spec.containers[*].env?
直接覆盖 env 切片会丢弃用户原始声明,且可能破坏 initContainer 与 appContainer 的 env 顺序依赖;K8s 对 env 的 merge 规则不透明,必须手动保序合并。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 遍历原
env列表,用 map 记录已存在的name,再追加新 env 变量(避免重复) - 若需注入 secret 引用,务必检查目标
Secret是否存在于同一 namespace,否则准入会失败并返回"secret not found" - 修改后调用
json.Marshal再写入response.Patch,别用json.MarshalIndent—— K8s patch decoder 不接受缩进空格
admissionregistration.k8s.io/v1 的 sideEffects 设成 None 会怎样?
表示该 webhook 绝对不产生副作用(比如不改 etcd、不调外部 API),K8s 会允许在 dry-run 请求中执行它;但如果实际代码里调了 client.Get() 或写了日志文件,就违反契约,可能导致缓存穿透或 etcd 压力异常。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 仅当 webhook 纯做校验(如检查 label 格式)、且全程不碰 client、不 sleep、不发 HTTP 请求时,才设
None - 只要读了其他资源(哪怕只查一个
ConfigMap),就必须设为NoneOnDryRun,否则 dry-run 创建会失败 - 生产环境别为了“省事”硬设
None—— K8s 1.26+ 对 sideEffects 校验更严格,错误配置会导致 webhook 直接被跳过
本地调试 webhook 时,kubectl apply 卡住没响应?
大概率是 TLS 握手失败或证书 CN 不匹配:K8s apiserver 要求 webhook server 的证书 Subject.CommonName 必须是 service-name.namespace.svc,且必须由 apiserver 信任的 CA 签发(通常是 ca.crt from /etc/kubernetes/pki/ca.crt)。
实操建议:
立即学习“go语言免费学习笔记(深入)”;
- 用
openssl s_client -connect your-webhook-service:443 -servername your-webhook-service.namespace.svc直接测 TLS 连通性 - 生成证书时,CN 必须严格等于 service FQDN;IP SAN 不生效,DNS SAN 必须包含完整 svc 域名
- 临时调试可改用
insecureSkipTLSVerify: true(仅限 minikube/kind),但上线前必须切回双向 TLS
最常被忽略的是:webhook server 启动后没监听 0.0.0.0:443,而是只绑了 127.0.0.1,Pod 内部能通,apiserver 就连不上。










