Skip to main content

Understand the Admission Webhook

The admission webhook validates Ingress Controller resources before Kubernetes accepts create or update requests. It detects configuration errors before they cause runtime failures or service disruptions.

The standalone APISIX and API7 Ingress Controller charts enable the webhook by default with webhook.enabled=true. The APISIX umbrella chart leaves it disabled unless ingress-controller.webhook.enabled=true; the setup tutorial enables it explicitly.

When enabled, the webhook validates:

  • Resource schemas and required fields
  • References to resources such as Secrets and Services
  • Duplicate or conflicting configurations
  • TLS certificate configuration

The webhook returns messages only when a request contains a potential configuration issue.

If Argo CD renders the controller chart, see Manage with Argo CD for the current webhook certificate limitation and deterministic configuration options.

SSL Certificate Conflicts

A certificate conflict occurs when multiple resources in the same GatewayProxy scope use different TLS certificates for one hostname. The webhook rejects the conflict to prevent ambiguous routing and certificate selection.

SSL configuration conflicts detected:
- Host '<hostname>' is already configured with a different certificate in <resource-type>/<namespace>/<resource-name>

Certificate conflicts commonly result from duplicate TLS resources or from creating a resource during certificate rotation instead of updating the existing one. The rejection message identifies the resource that already uses a different certificate for the hostname.

GatewayProxy Conflicts

When you create or update a GatewayProxy, the webhook checks it against existing GatewayProxy resources. It rejects conflicts that could let multiple controllers interfere with the same control plane instance.

gateway proxy configuration conflict: GatewayProxy <namespace>/<new-gatewayproxy-name> and <namespace>/<existing-gatewayproxy-name> both target Service <namespace>/<service-name> port <port> while sharing <admin-key>

gateway proxy configuration conflict: GatewayProxy <namespace>/<new-gatewayproxy-name> and <namespace>/<existing-gatewayproxy-name> both target control plane endpoints [<endpoint-url>] while sharing <admin-key>

GatewayProxy conflicts occur when two resources manage the same control plane instance with the same admin key. The key may be an inline value or the same Secret reference.

To resolve this conflict, identify all GatewayProxy resources and determine which one should remain. If you genuinely need multiple GatewayProxy resources, ensure they target different control plane instances.

Missing Service References

When you create or update a resource that routes traffic to a backend Service, the webhook checks that the Service exists. A missing Service produces a warning such as:

Warning: Referenced Service '<namespace>/<service-name>' not found

Unlike errors, warnings allow the resource to be created, but traffic routing will fail until the backend services exist.

A reference may fail because the Service has not been created or its name or namespace is misspelled. Confirm that the Service exists in the expected namespace before applying the dependent resource.

Missing Secret References

When a resource references a Secret for TLS, authentication, or plugin configuration, the webhook checks that the Secret and required keys exist.

If the secret referenced by your resource does not exist, you will see a warning message such as:

Warning: Referenced Secret '<namespace>/<secret-name>' not found

If the referenced Secret does not contain a required key, such as password for basic authentication, the webhook returns a warning such as:

Warning: Secret key '<key-name>' not found in Secret '<namespace>/<secret-name>'

Unlike errors, warnings allow the resource to be created, but the affected functionality will not work correctly until the referenced secrets are properly configured.

Create the Secret before applying the resource that references it. Confirm that its name and namespace are correct and that it contains every required key.

Cross-Namespace Consumer Secrets

A Consumer that references a credential Secret in another namespace is rejected unless a ReferenceGrant in the Secret namespace permits the reference. The error contains:

not permitted by any ReferenceGrant

The response does not disclose whether the Secret exists. Create the grant before applying the Consumer. See Configure Cross-Namespace References.

Invalid CSRF Annotations

When k8s.apisix.apache.org/enable-csrf is true, the Ingress must also have a non-empty k8s.apisix.apache.org/csrf-key annotation. Otherwise, the webhook rejects both create and update requests:

annotation "k8s.apisix.apache.org/enable-csrf" is enabled but "k8s.apisix.apache.org/csrf-key" is missing or empty

Add a strong key to the Ingress annotations, then apply the resource again. See the CSRF annotation reference.

Missing Gateway References

When you create or update a Gateway or IngressClass that references a GatewayProxy, the admission webhook validates that the GatewayProxy exists. If the GatewayProxy referenced by your resource does not exist, you will see a warning message such as:

Warning: Referenced GatewayProxy '<namespace>/<gatewayproxy-name>' not found

Unlike errors, warnings allow the resource to be created, but the affected functionality will not work correctly until the referenced GatewayProxy is properly configured.

To resolve this issue, ensure that the GatewayProxy exists in the correct namespace and check for any spelling errors in the GatewayProxy reference.

Webhook Connectivity

The webhook Service listens on port 443 and forwards requests to container port 9443. If a NetworkPolicy selects the controller pod, it must allow TCP traffic to pod port 9443, not only Service port 443.

If TCPRoute or UDPRoute validation returns a 404 after an upgrade, inspect any hand-maintained ValidatingWebhookConfiguration. The current API version and paths are:

Resourcerules[].apiVersionsclientConfig.service.path
TCPRoutev1/validate-gateway-networking-k8s-io-v1-tcproute
UDPRoutev1/validate-gateway-networking-k8s-io-v1-udproute

Chart-managed webhook resources are updated with the chart. Update custom resources manually and verify the webhook endpoints:

kubectl get validatingwebhookconfiguration \
-o jsonpath='{range .items[*].webhooks[*]}{.clientConfig.service.path}{"\t"}{range .rules[*].apiVersions[*]}{.}{" "}{end}{"\n"}{end}' \
| grep -E 'v1-(tcp|udp)route'

Each TCPRoute and UDPRoute row should show its v1 webhook path followed by the v1 API version. If the version is v1alpha2, update both the rule and path to the values in the table.