Skip to main content

Upgrade APISIX Ingress Controller

APISIX Ingress Controller 2.2 introduces Gateway API 1.6, new and updated APISIX CRDs, stricter validation, and changes to listener-port matching. Before upgrading from 2.1.0, update the CRDs and review the compatibility changes that can affect existing resources.

API7 availability

API7 Ingress Controller has not yet published an equivalent release. Do not follow this procedure for the latest public API7 2.1.0 release or replace only its controller image. Continue using the controller, chart, and installation package selected by your API7 release until API7 publishes a compatible set.

Prerequisites

Before upgrading, confirm the following:

  • The cluster runs Kubernetes 1.31 or later.
  • You know whether Helm, Argo CD, or Flux manages the controller.
  • You know which deployment owner manages the Gateway API and APISIX CRDs. Keep that owner unchanged, and do not apply CRDs manually when a GitOps or platform release manages them.
  • You have selected APISIX Ingress Controller chart 1.3.0. Do not override only the image tag on an older chart because its CRDs, RBAC, and webhook paths are incompatible.

Back Up the Current Deployment

Record the currently running image:

kubectl get deployment <ingress-controller-deployment> -n <namespace> \
-o jsonpath='{.metadata.namespace}{"/"}{.metadata.name}{": "}{range .spec.template.spec.containers[*]}{.image}{" "}{end}{"\n"}'

For an Argo CD or Flux deployment, confirm that the current Git revision and controller configuration can be restored before making changes.

For a Helm release, save the computed values as a rollback reference and export the user-supplied overrides for the upgrade:

helm get values <release-name> -n <namespace> --all -o yaml \
> ingress-controller-computed-values-backup.yaml
helm get values <release-name> -n <namespace> -o yaml \
> ingress-controller-overrides.yaml

Do not pass the computed-values backup to helm upgrade because it contains defaults from the old chart. Review ingress-controller-overrides.yaml for renamed or removed settings, and pass only the migrated user overrides to the new chart.

Upgrade Gateway API CRDs

Before rolling out the controller, upgrade the Gateway API bundle to the 1.6.0 standard channel. This bundle includes the v1 TCPRoute, UDPRoute, and TLSRoute APIs used by the controller.

If a platform Application, Kustomization, or other GitOps source owns these CRDs, update its pinned bundle to Gateway API 1.6 and reconcile that source. Do not run the manual command against platform-managed CRDs because doing so can change field ownership and create drift.

For a manually managed bundle, use server-side apply because the CRDs exceed the client-side annotation size limit:

kubectl apply --server-side --force-conflicts \
-f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.6.0/standard-install.yaml

Verify that the API server serves the versions used by the controller:

kubectl get crd tcproutes.gateway.networking.k8s.io \
-o jsonpath='{range .spec.versions[?(@.served==true)]}{.name}{"\n"}{end}'
kubectl get crd udproutes.gateway.networking.k8s.io \
-o jsonpath='{range .spec.versions[?(@.served==true)]}{.name}{"\n"}{end}'

Both outputs should include v1.

Upgrade APISIX CRDs

Upgrade the APISIX CRDs through their existing owner before rolling out the controller:

  • If a separate platform Application or Kustomization owns them, update its pinned APISIX CRD source and reconcile it before reconciling the controller.
  • If the Argo CD controller Application or Flux HelmRelease owns the bundled CRDs, update the chart and CRD settings in Git and follow the tool-specific upgrade procedure. Do not apply the CRDs manually.

For a direct Helm deployment whose APISIX CRDs are not managed by another reconciler, download the compatible controller chart and apply only its APISIX CRD file. Do not apply the chart's aggregate CRD output because it also contains the Gateway API bundle, which can have a different owner. Helm installs resources from a chart's crds/ directory but does not upgrade existing CRDs during helm upgrade.

Download and apply the APISIX CRDs:

helm pull apisix/apisix-ingress-controller \
--version 1.3.0 \
--untar --untardir <chart-download-directory>
kubectl apply --server-side --force-conflicts \
-f <chart-download-directory>/apisix-ingress-controller/crds/apisixic-crds.yaml

If you install the controller through the APISIX umbrella chart, use the controller chart version declared as its dependency. After the CRD owner finishes reconciling, confirm that the selected source contains the new policy CRD:

kubectl get crd l4routepolicies.apisix.apache.org

Review Configuration Changes

Address the following compatibility changes before upgrading.

Cross-Namespace Consumer Credentials

A Consumer that references a credential Secret in another namespace now requires a ReferenceGrant in the Secret namespace. Create the grant before rolling out the controller. Without it, the controller no longer programs the credential. See Configure Cross-Namespace References.

CSRF Annotations

An Ingress with k8s.apisix.apache.org/enable-csrf: "true" must also set a non-empty k8s.apisix.apache.org/csrf-key. When the admission webhook is enabled, it rejects an Ingress with a missing or empty key. If the webhook is disabled or bypassed, Kubernetes can accept the Ingress, but the controller logs an annotation error and omits the CSRF plugin when translating the route.

Fix every affected Ingress before the rollout so that routes intended to use CSRF protection are not published without it. See the CSRF annotation reference.

Plugin Configuration

Malformed plugin config values now cause translation to fail instead of publishing the plugin with an empty configuration. Inspect controller logs and resource status for previously ignored configuration, especially for security plugins such as ip-restriction.

Listener-Port Matching

listener_port_match_mode defaults to off. This prevents the controller from injecting a server_port match when a Gateway listener uses a Service port such as 80 but APISIX receives the connection on a container port such as 9080.

If you set the mode to explicit or auto, it also applies to TCPRoute and UDPRoute. Each Gateway listener port must equal the physical APISIX stream listener port. Review the configuration reference and all HTTP, gRPC, TCP, and UDP listeners before retaining either mode.

Manually Managed Webhooks

The chart updates the TCPRoute and UDPRoute webhook rules and paths from v1alpha2 to v1. If you manage ValidatingWebhookConfiguration outside the chart, update both rules[].apiVersions and clientConfig.service.path:

ResourceAPI versionWebhook path
TCPRoutev1/validate-gateway-networking-k8s-io-v1-tcproute
UDPRoutev1/validate-gateway-networking-k8s-io-v1-udproute

The webhook Service forwards port 443 to container port 9443. If a NetworkPolicy restricts the controller pod, allow TCP traffic to pod port 9443.

Upgrade the Deployment

Update the chart version, controller image, CRDs, RBAC, and webhook configuration as one reviewed release change. If you manage a NetworkPolicy for the controller, update it in the same rollout to allow the required webhook traffic.

  • For a Helm-managed deployment, apply the CRD updates, refresh the chart repository metadata, and run helm upgrade with chart 1.3.0 and the reviewed ingress-controller-overrides.yaml file.
  • For Argo CD or Flux, update the CRD source and controller chart or manifest pin in Git. Reconcile the CRD owner first, wait for the required CRDs to become established, and then reconcile the controller. Follow the Argo CD or Flux procedure for the selected ownership model.

Wait for the rollout to complete:

kubectl rollout status deployment/<ingress-controller-deployment> -n <namespace>

Verify the Upgrade

Confirm the running image and webhook endpoints:

kubectl get deployment <ingress-controller-deployment> -n <namespace> \
-o jsonpath='{range .spec.template.spec.containers[*]}{.image}{"\n"}{end}'

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.

Confirm that the Gateway API and policy resources are accepted:

kubectl get gateway,httproute,grpcroute,tcproute,udproute,tlsroute -A
kubectl get backendtrafficpolicy,l4routepolicy -A

Verify the traffic paths used in your environment:

  • HTTP and gRPC routes return the expected responses.
  • TLSRoute termination presents the expected certificate and routes by SNI.
  • TCPRoute and UDPRoute traffic reaches the selected listener and backend.
  • Downstream mTLS accepts a valid client certificate and rejects a missing certificate.
  • Cross-namespace Consumer credentials work only when a matching ReferenceGrant exists.
  • With the admission webhook enabled, applying an Ingress with CSRF enabled and no key is rejected. If the webhook is disabled, confirm that no Ingress has CSRF enabled without a non-empty key.

Roll Back

Use the same deployment owner to roll back the controller:

  • For a direct Helm deployment, run helm history <release-name> -n <namespace> to identify the pre-upgrade revision, then run helm rollback <release-name> <revision> -n <namespace> --wait. Keep the saved values as a reference; do not pass them to helm rollback.
  • For Argo CD, revert the controller version and values in Git by following the Argo CD rollback procedure. Do not run helm rollback or edit the Deployment directly.
  • For Flux, revert the controller version and values in Git by following the Flux rollback procedure. Do not run helm rollback or edit the Deployment directly.

Do not delete or downgrade Gateway API or APISIX CRDs during rollback. Deleting a CRD also deletes its custom resources. Keep the installed CRDs under their existing owner, and verify that they remain compatible with the older controller.

The older controller does not reconcile the new L4RoutePolicy resource and may not watch the Gateway API v1 L4 resource paths. After rollback, treat TCP, UDP, and TLS routing as unavailable until you restore a compatible controller. If a resource caused the rollback, remove or correct it instead of downgrading cluster-wide CRDs.