Skip to main content

Upgrade Ingress Controller

Upgrading APISIX or API7 Ingress Controller from 2.1.0 to 2.2.0 requires updating the CRDs before the controller rollout. The new release introduces Gateway API 1.6, new and updated APISIX CRDs, stricter validation, and changes to listener-port matching. Review the compatibility changes before upgrading.

Review the Release Notes for shared and product-specific changes before starting the upgrade.

Helm-managed installations use the normal Helm workflow for the controller rollout. For API7 Ingress Controller, regenerate the deployment command in Dashboard and run its helm upgrade --install command. For APISIX Ingress Controller, run helm upgrade for the existing release with the selected APISIX installation chart and reviewed values. The CRD steps below remain separate because Helm does not upgrade existing CRDs from a chart's crds/ directory.

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 the compatible controller chart listed in the Helm chart reference. Do not override only the image tag on an older chart because its CRDs, RBAC, and webhook paths are incompatible.
  • For API7 Ingress Controller, keep the chart, image, and CRDs from the same controller release. Do not combine a Dashboard-generated script that pins a different controller release with the CRDs, webhook paths, or examples in this documentation.

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 Controller 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. For Helm users, applying the CRDs is the separate prerequisite before the normal controller upgrade.

For APISIX Ingress Controller, 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

For API7 Ingress Controller, download and apply the APISIX CRDs:

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

If you install APISIX Ingress 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

The controller binary defaults listener_port_match_mode to off when the field is omitted. That prevents injecting a server_port match when a Gateway listener uses a Service port such as 80 but the gateway receives the connection on a container port such as 9080.

Helm does not always install that binary default:

Install surfaceEffective mode after installing this version
API7 Ingress Controller chartoff
APISIX Ingress Controller chart, including the APISIX umbrella chartauto

Upgrading with the APISIX chart keeps or sets auto. To get off on that path, set config.listenerPortMatchMode=off on the dedicated chart or ingress-controller.config.listenerPortMatchMode=off on the umbrella chart.

If you set the mode to explicit or auto, it also applies to TCPRoute and UDPRoute. Review the routes and listeners that meet the injection conditions in the configuration reference. Whenever the controller injects a server_port predicate, the declared Gateway listener port must match the corresponding physical HTTP, TLS, or stream listener. Review 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

API7 Ingress Controller chart 0.1.26 changes the default webhook.failurePolicy from Fail to Ignore. This prevents an unavailable cluster-scoped webhook from blocking changes to resources owned by another controller. To retain fail-closed admission, set the value to Fail explicitly and ensure the webhook is highly available.

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

After the CRDs are established, use the normal deployment workflow. If you manage a NetworkPolicy for the controller, update it in the same rollout to allow the required webhook traffic.

  • For API7 Ingress Controller managed directly with Helm, regenerate the deployment script for the existing gateway group in Dashboard. Add any reviewed custom overrides, then run the generated helm upgrade --install command.
  • For APISIX Ingress Controller managed directly with Helm, refresh the chart repository metadata and run helm upgrade for the existing release with the selected APISIX installation chart 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.