kubernetes-sigs / kubernetes-sigs/controller-runtime
webhook: Admission metrics are not reported by status code
@mattsu2020 is already working on this.
Since Jun 22, 2026.
- Dominant language
- Go
- Stars
- 3k
- Forks
- 1.3k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 14
Description
This is several bugs in one bug since it appears multiple things are broken. Apologies if it gets too complicated.
Problem 1: It appears that controller-runtime webhooks always respond with HTTP status code 200 OK even if the request is completely malformed.
Example (sending a malformed request to a webhook endpoint):
curl -k -v https://localhost:9443/validate-ship-example-org-v1beta1-frigate
< HTTP/2 200
< ... other response headers ...
<
{"response":{"uid":"","allowed":false,"status":{"metadata":{},"message":"contentType=, expected application/json","code":400}}}
Problem 2: controller-runtime webhooks do not use the metav1.Status.Code and always respond with HTTP status code 200 OK.
Example code I used to register my custom handler at /test:
webhookServer.Register("/test", &webhook.Admission{Handler: &myHandler{}})
...
type myHandler struct{}
func (*myHandler) Handle(context.Context, admission.Request) admission.Response {
return admission.Response{
AdmissionResponse: admissionv1.AdmissionResponse{
Allowed: false,
Result: &metav1.Status{
Code: 403,
Message: "things suck",
Status: "Failure",
Reason: metav1.StatusReasonForbidden}}}
}
And here's the query I am making:
curl -XPOST -k -v -H "Content-Type: application/json" https://localhost:9443/test
< HTTP/2 200
...
<
{"kind":"AdmissionReview","apiVersion":"admission.k8s.io/v1","response":{"uid":"","allowed":false,"status":{"metadata":{},"status":"Failure","message":"things suck","reason":"Forbidden","code":403}}}
Problem 3: controller-runtime doesn't expose any metrics about rejected requests and their .status.codes. This is likely because
- we always report code=200 no matter the response (Problem 1 & 2)
- it appears we're capping
controller_runtime_webhook_requests_total{code=...}dimension to only200and500here: https://github.com/kubernetes-sigs/controller-runtime/blob/4cae9dfbf174fa5d49ebca007bd6f3784cf1ffb3/pkg/webhook/internal/metrics/metrics.go#L70-L76
so even if I make a faulty request, only the code=200 metric goes up:
controller_runtime_webhook_requests_total{code="200",webhook="/test"} 4
In an ideal state, I'd like to see controller_runtime_webhook_requests_total metric actually let me understand things like how many requests I'm denying (non-200 codes, such as 403, 400, 429, ...).
/kind bug
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.