AdmissionReview 解析失败总返回 400 是因 K8s 默认用 protobuf 而非 JSON;须依 Content-Type 用 runtime.Decode 并注册 admissionv1.AddToScheme;拒绝响应需显式设 Allowed=false 且 Result.Code=403、Message 非空;caBundle 必须是 base64 编码的 CA 根证书;handler 超时须 ≤1s 且禁用外部阻塞调用。

为什么 AdmissionReview 解析失败总是 400?
因为 K8s 发送的请求体是二进制 protobuf(v1.16+ 默认),不是 JSON。用 json.Unmarshal 直接解 io.Reader 必然 panic 或静默失败,HTTP 响应直接 400。
- 必须先检查请求头
Content-Type:若为application/vnd.kubernetes.protobuf,得用k8s.io/apimachinery/pkg/runtime/serializer/protobuf+scheme解码 - 推荐统一走
runtime.Decode,它能自动识别格式;但前提是你的*runtime.Scheme已注册admissionv1.AdmissionReview类型(调用admissionv1.AddToScheme(scheme)) - 别自己读完整 body 再判断格式——K8s 控制面可能关闭了 protobuf 支持(通过
--admission-control-config-file配置),实际发来的是 JSON,所以 decoder 必须兼容双模式
如何让 Webhook 正确返回拒绝响应?
返回结构不对,K8s 就当“允许”,连日志都不打。核心就一条:AdmissionResponse 的 Allowed 字段必须显式设为 false,且 Result 要带 Code(如 403)和 Message(否则 UI 不显示原因)。
- 不要只写
resp.Allowed = false就完事,K8s 审计日志和kubectl apply报错都依赖resp.Result.Message -
resp.Result.Code建议固定用403(Forbidden),避免用400(Bad Request)——后者会让 K8s 认为是 webhook 自身错误,可能重试或降级 - 如果要附带建议修复方式(比如“请添加 label `owner: team-a`”),塞进
Message即可,K8s CLI 会原样输出
证书与 TLS 配置为何总卡在 x509: certificate signed by unknown authority?
不是证书不合法,而是 K8s apiserver 不信任你 webhook 的 CA。它只认你通过 mutatingWebhookConfiguration 或 validatingWebhookConfiguration 的 caBundle 字段提供的 PEM 编码 CA 证书。
-
caBundle必须是 base64 编码后的 CA 根证书(不是服务端证书!),且该 CA 必须签发了你的 webhook 服务证书 - 生成时别用
openssl req -x509直接生成自签名证书——它没 CA 属性,K8s 拒绝加载;要用openssl ca或cfssl显式标记CA:TRUE - 更新证书后,必须同时更新所有
WebhookConfiguration对象里的caBundle字段,并滚动重启 apiserver(或等其自动 reload,通常 1~5 分钟)
怎样避免拦截逻辑阻塞核心 API 请求?
Admission Controller 是同步阻断式调用,你的 handler 执行超时(默认 30s),apiserver 就直接返回 500 并丢弃请求。这不是性能问题,是可用性红线。
立即学习“go语言免费学习笔记(深入)”;
- 所有外部依赖(DB、HTTP 调用、复杂正则匹配)必须加 context 超时,且 timeout 值 ≤ 2s(建议 1s),并设
ctx, cancel := context.WithTimeout(r.Context(), time.Second) - 禁止在 handler 里做文件 IO、启动 goroutine 后不管、或调用未设限的第三方 SDK(比如某些云厂商 SDK 默认无超时)
- 如果真需要异步决策(如查策略中心),得把 webhook 改成 “先放行 + 后审计” 模式,用 operator 或 audit log 补偿,而不是硬扛在 admission path 上
真正难的从来不是写通逻辑,而是把 caBundle 更新、AdmissionReview 解码路径、超时控制这三处拧紧——漏一个,上线后就是静默失效或集群雪崩。










