Admission
The webhook answers from cache. Scanning never runs in the admission path, which is why a slow registry cannot slow down a deployment.
How a decision is made
- The API server asks about a pod.
- The tag is resolved to a digest. That resolution is cached for a minute, so a burst of identical deployments makes one registry call rather than a hundred.
- The digest's scan result and signature verdict are read from cache.
- The policy is evaluated against them and the answer is allow or deny, with a reason.
- The decision is recorded — including the allows, because evidence that only lists denials cannot show a control was operating.
Nothing in that list waits on a scan. If the digest has never been seen, step three has no answer, and what happens next is the setting below.
The two settings that decide your posture
| Value | Default | What it means |
|---|---|---|
webhook.failurePolicy | Ignore |
What the API server does when the operator does not answer. Ignore means an outage leaves you unguarded, never blocked. Fail denies until the operator answers. |
webhook.coldImagePolicy | allowAndScan |
What happens to a digest never seen before. The alternative denies it and scans it, which is Fail's natural companion. |
These two are the whole posture decision, and the honest framing is that neither answer is universally right.
Ignore keeps your cluster deployable during an outage of ours and leaves a gap in the evidence: for that window nothing was reviewed, and the evidence package says so rather than quietly showing a clean quarter.
Fail gives you a control that provably never had a gap, and it means an operator outage stops deployments. That is a real cost and you should choose it on purpose, not inherit it.
Either way, whatever crossed during a gap is still running after it closes. The
runtime reconciliation sweep is what finds it: on a schedule,
every running container's observed imageID is checked against the admission
ledger, and a digest with no admission event behind it is reported — or, under
runtimeReconciliation: enforce, stopped so it re-enters through the
webhook.
Both settings are available in every edition, Community included: policy behaviour is never gated by licence, only capacity is. Choose them knowing they are the posture that blocks a deployment at two in the morning, and make sure someone is answerable for that.
Exemptions
webhook.bypassNamespaces lists namespaces admission does not review. The operator's own namespace is always exempt, because a webhook that can block its own replacement pod is a webhook that can lock you out of fixing it.
Per-workload exceptions are not a chart value. They are made in the console, with an owner and an expiry, because an exception nobody approved and nothing expires is indistinguishable from a policy hole — and an auditor will read it as one.
Timeouts
webhook.timeoutSeconds defaults to 15. Since admission decides from cache, that is a ceiling rather than a budget: the normal answer is milliseconds, and the timeout exists for the pathological case rather than the usual one.
Serving certificate
By default the operator issues and rotates its own webhook certificate, and every replica picks up a new one without a restart — the pair lives in a Secret, not on each pod. Set webhook.tls.certManager.enabled if you would rather cert-manager owned it.