Hey everyone,
I'm in the process of developing a Kubernetes Operator, and I'm using a mutating webhook to handle defaulting of any missing fields along with a validating webhook that's set to `failurePolicy: Fail` to ensure that custom resources (CRs) are structurally sound before they get admitted. My main question is: if the validating webhook confirms the correctness of the CR spec, is it still necessary to implement additional validation in the operator itself, such as in the controller or the Reconcile() function? For instance, what happens if I try to access `Spec.Foo[0]` which needs to be initialized by the mutating webhook and checked by the validating webhook?
I'm wondering what the best practice is here. Should I defensively validate all critical fields in the controller despite having the validating webhook? Or is that considered excessive? I get the concept of separation of responsibilities where the webhook focuses on validation and the controller on reconciliation. Yet, it feels a bit risky to rely solely on the webhook's reliability for production applications.
Thanks for any insights!
4 Answers
That's a great question! Having a validating webhook does add a layer of validation, but things can get tricky with upgrades. For instance, if you’re changing API versions or adding fields, the operator might not revalidate as you intended. If you've defaulting logic in your webhook, just think about scenarios where your operator at version N reads resources written by version N+1. In certain cases, yeah, you might want to add some defensive checks just to safeguard against unexpected situations. It’s all about what level of reliability you want to ensure during those upgrades!
Exactly! It’s a fine balance between keeping things straightforward and making sure everything works through various states.
I like to think of validating and mutating webhooks like client-side validation on a web form. They can guide users, but you never want to assume they are always functioning perfectly, especially during upgrades. Here are my two cents: 1. Utilize CEL expressions and CRD annotations for validation and defaulting where feasible. 2. Implement defaults in your controller as well. 3. Be clear on what constitutes a breaking API change; for example, making a previously optional field required is a big one.
In general, if the validating webhook succeeds, the object should not reach your controller, right? So, full revalidation inside the operator seems like overkill. That said, it's a smart practice to include some safeguards in your code, like checking for nil or empty slices, just to be on the safe side and avoid any unexpected panics.
Absolutely, the operator can’t guarantee that the validating webhook is properly configured or even available at all times. Sometimes a validation webhook can pass even when it’s not working. The principle of not trusting incoming data from any boundary is key—always validate against your system’s contract when you receive submissions!
Great point! I totally agree with versioning to handle those differences. It definitely mitigates issues when your API evolves.