Manage with Flux
Flux is a GitOps toolkit composed of specialized Kubernetes controllers. Its source controllers retrieve versioned configuration and deployment artifacts, while other controllers reconcile those sources into the cluster. In this workflow, Flux Helm Controller manages APISIX or API7 Ingress Controller as a declarative Helm release defined in Git.
Flux Helm Controller performs Helm install and upgrade actions and stores the rendered release manifest. It can also remediate failed operations and correct configuration drift. Because it does not render the chart again for every comparison, the current webhook certificate-generation behavior is not expected to cause continuous drift. Keep the webhook enabled and verify a no-change reconciliation before using the workflow in production.
This guide creates the HelmRepository and HelmRelease, configures CRD lifecycle policies and remediation, and reconciles gateway and application resources. It also covers verification, upgrades, rollback, and troubleshooting.
Prerequisites
Before you begin, ensure that you have:
- The repository, resource ownership, CRD, and credential preparation described in Prepare for GitOps.
- A Flux installation and an authenticated
fluxCLI. - Flux access to the platform repository and permission to manage the destination namespace and required cluster-scoped resources.
The examples use aic as the destination namespace. If you use another namespace, replace aic throughout the manifests and commands.
The example values focus on GitOps ownership and reconciliation; they retain the chart defaults for replicas, resource requests, and pod scheduling. Before production, configure capacity for your workload, run multiple controller replicas, and spread them across failure domains. See AIC High Availability and test failover in the target cluster. Both pinned controller charts render a PodDisruptionBudget when podDisruptionBudget.enabled=true and either autoscaling uses at least two minimum replicas or autoscaling is disabled with deployment.replicas greater than one.
Create the Helm Source and Release
Create a HelmRepository and HelmRelease for the selected controller. The examples use the controller-owned CRD model.
Apply the CRD ownership decision from Prepare for GitOps when configuring the HelmRelease:
- If the HelmRelease owns both bundles, set
install.crdstoCreateandupgrade.crdstoCreateReplace. For APISIX chart 1.4.0, also keepcrds.gatewayAPI.enabled=true. Review CRD changes separately before upgrading the release. - If the platform owns Gateway API but the dedicated APISIX HelmRelease owns its APISIX CRDs, set
crds.gatewayAPI.enabled=falseand retain theCreateandCreateReplacepolicies. - If the platform owns both bundles, reconcile them from a separate, pinned Flux Kustomization. For APISIX chart 1.4.0, set
crds.gatewayAPI.enabled=false; for both products, set the HelmRelease CRD policies toSkip. Wait until the CRDs report anEstablishedcondition before reconciling the HelmRelease. If Flux also applies the HelmRelease through a Kustomization, configure that Kustomization to depend on the CRD Kustomization.
The manifests use the Flux v2 HelmRelease API and drift detection. Confirm that your Flux installation supports these fields before applying them.
On a shared or multi-tenant cluster, set spec.serviceAccountName on the HelmRelease to a platform-owned service account with only the required permissions. The service account must be able to manage the namespaced and cluster-scoped resources assigned to the release, including CRDs when the HelmRelease owns them. Flux otherwise performs Helm actions with the permissions granted to Helm Controller.
- APISIX
- API7
The APISIX Admin API Service and apisix-admin-key Secret must already exist in the destination namespace (aic in the example).
apiVersion: v1
kind: Namespace
metadata:
name: aic
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: apisix
namespace: aic
spec:
interval: 1h
url: https://apache.github.io/apisix-helm-chart
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: apisix-ingress-controller
namespace: aic
spec:
interval: 30m
releaseName: apisix-ingress-controller
chart:
spec:
chart: apisix-ingress-controller
version: "1.4.0"
sourceRef:
kind: HelmRepository
name: apisix
namespace: aic
interval: 12h
install:
crds: Create
remediation:
retries: 3
upgrade:
crds: CreateReplace
remediation:
retries: 3
driftDetection:
mode: enabled
values:
crds:
gatewayAPI:
enabled: true
config:
listenerPortMatchMode: "off"
provider:
type: apisix-standalone
gatewayProxy:
createDefault: true
provider:
type: ControlPlane
controlPlane:
service:
name: apisix-admin
port: 9180
auth:
type: AdminKey
adminKey:
valueFrom:
secretKeyRef:
name: apisix-admin-key
key: admin-key
The highlighted value overrides the APISIX chart's packaged auto mode so Service-facing Gateway listener ports are not translated into physical server_port matches.
Replace the controller name and leader-election ID with the values generated by API7 Dashboard when they differ.
apiVersion: v1
kind: Namespace
metadata:
name: aic
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: api7
namespace: aic
spec:
interval: 1h
url: https://charts.api7.ai
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: api7-ingress-controller
namespace: aic
spec:
interval: 30m
releaseName: api7-ingress-controller
chart:
spec:
chart: api7-ingress-controller
version: "0.1.28"
sourceRef:
kind: HelmRepository
name: api7
namespace: aic
interval: 12h
install:
crds: Create
remediation:
retries: 3
upgrade:
crds: CreateReplace
remediation:
retries: 3
driftDetection:
mode: enabled
values:
config:
controllerName: api7.ai/api7-ingress-controller
leaderElection:
id: api7-ingress-controller-leader
provider:
type: api7ee
For a Gateway API workflow, reconcile the non-sensitive GatewayProxy, GatewayClass, and Gateway generated by API7 Dashboard separately. Supply their credential Secret through your secret-management solution.
The examples retry a failed operation three times. Flux uninstalls a failed installation before retrying it and rolls back a failed upgrade before retrying it. Adjust the retry count to match your recovery policy, and keep it bounded so persistent configuration or permission errors require operator review.
Reconcile the Helm Release
Commit the manifest to the path reconciled by Flux, request reconciliation, and inspect the release:
flux reconcile source helm <repository-name> -n aic
flux reconcile helmrelease <release-name> -n aic --with-source
flux get helmreleases -n aic
The HelmRelease should report Ready=True. Run the reconciliation again without changing Git and confirm that the revision and webhook Secret remain unchanged.
Reconcile Gateway and Application Resources
The HelmRelease manages the controller release. Manage the shared Gateway resources and application routes with separate Flux Kustomization resources so that their ownership and lifecycles remain independent. Despite the resource name, each referenced directory can contain ordinary Kubernetes YAML without a kustomization.yaml file.
Store the product-specific GatewayProxy, GatewayClass, shared Gateway, application namespaces, and authorization labels in the platform-owned infrastructure/gateway-resources/ directory prepared earlier. For APISIX, omit the GatewayProxy from this directory when the controller chart creates the default object. For API7, use the non-sensitive resources generated by API7 Dashboard and retain their generated names and references.
Create a GitRepository for the platform repository and a Kustomization for the shared resources:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: platform-config
namespace: flux-system
spec:
interval: 1m
url: https://github.com/example/platform-config.git
ref:
branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: platform-gateway-resources
namespace: flux-system
spec:
interval: 10m
path: ./clusters/production/infrastructure/gateway-resources
prune: true
wait: true
timeout: 3m
sourceRef:
kind: GitRepository
name: platform-config
Store each application's Deployment, Service, HTTPRoute, and policies with that application. You can use the manifests from Configuration Examples without creating overlays. Add another Kustomization for the application directory and make it depend on the shared resources:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: httpbin-production
namespace: flux-system
spec:
interval: 10m
path: ./clusters/production/applications/httpbin
prune: true
wait: true
timeout: 3m
targetNamespace: <application-namespace>
sourceRef:
kind: GitRepository
name: platform-config
dependsOn:
- name: platform-gateway-resources
Flux generates the build configuration when either directory contains plain manifests. Commit these resources to the Flux bootstrap path. The application namespace must be created by the platform Kustomization or another owner before the application Kustomization runs. On a shared or multi-tenant cluster, set spec.serviceAccountName on each Kustomization to an appropriately scoped service account.
The dependency waits for the platform Kustomization to report Ready=True, but GatewayProxy has no status in either controller. Verify the actual gateway connection through the Gateway and HTTPRoute conditions and an end-to-end request.
Verify
Verify the controller deployment, CRDs, gateway connection, and end-to-end routing before promoting the release to another environment.
Confirm that the Deployment is available and the CRDs are established:
kubectl rollout status deployment \
-l app.kubernetes.io/instance=<release-name> \
-n aic \
--timeout=300s
kubectl get pods,services -n aic
kubectl get crd gatewayproxies.apisix.apache.org
kubectl wait --for=condition=Established \
crd/gatewayproxies.apisix.apache.org \
--timeout=60s
The controller pod should report both the controller and ADC containers as ready. Inspect the rendered controller configuration and expected GatewayProxy:
kubectl get configmap -n aic
kubectl get configmap <configmap-name> -n aic \
-o jsonpath='{.data.config\.yaml}{"\n"}'
kubectl get gatewayproxy -n aic
kubectl describe gatewayproxy <gatewayproxy-name> -n aic
GatewayProxy does not expose an acceptance status in either controller. When the admission webhook is enabled, invalid objects can be rejected during creation. Verify runtime connectivity through the controller logs and the Accepted, Programmed, and ResolvedRefs conditions on related Gateway and HTTPRoute resources.
Complete Proxy Requests to a Service with the gateway and classes managed by Git. A successful request verifies the entire path from a Kubernetes route through the controller to the gateway.
Finally, reconcile once more and confirm that no resources change:
flux reconcile helmrelease <release-name> -n aic --with-source
flux get helmreleases -n aic
Upgrade and Roll Back
Manage upgrades and rollbacks through Git so that Flux remains the only reconciler for the Helm release.
Before upgrading APISIX Ingress Controller chart 1.3.x to 1.4.0, follow Migrate APISIX Chart 1.3.x Gateway API Ownership.
To upgrade the controller:
- Review the Ingress Controller release notes. Separately review the selected chart's release notes, including CRD changes.
- Change the pinned chart version and required values in Git.
- Inspect the rendered diff before reconciliation.
- Reconcile one environment and repeat the deployment, route, and no-change verification.
- Promote the same Git change to the next environment.
Before rolling back, confirm that the installed CRDs are compatible with the older controller. In the rollback change, set upgrade.crds to Skip so the older chart does not replace static CRDs. For APISIX chart 1.4.0, also set crds.gatewayAPI.enabled=false so the rollback change does not render the Gateway API bundle. If a platform Kustomization owns both bundles, keep install.crds and upgrade.crds set to Skip. Then revert the chart version and controller values in Git.
The CRD policies control resources from the chart's crds/ directory; they do not suppress Gateway API resources rendered as templates by APISIX chart 1.4.0. Inspect the rendered rollback diff and confirm that it does not modify either bundle. Automatic failed-upgrade remediation can replay a stored release manifest, which a later Git change cannot rewrite. Avoid automatic rollback across a CRD ownership change and recover with a reviewed Git revision. Do not run helm rollback or helm upgrade against a Flux-managed release.
Troubleshoot
Use the following checks to diagnose common release and reconciliation failures:
| Symptom | Check | Resolution |
|---|---|---|
| HelmRelease reports a CRD ownership or upgrade failure | Inspect install.crds, upgrade.crds, crds.gatewayAPI.enabled for APISIX chart 1.4.0, and other controllers managing the same CRDs. | Select one owner for each bundle and disable that bundle in every other release. |
| GatewayProxy creation is rejected or controller logs report connection errors | Confirm that its Secret, endpoint or Service, network access, and CRD exist before reconciliation. | Correct the Secret reference, connectivity, or dependency order, then reconcile again. |
| Controller resources return after manual deletion or editing | Check whether Flux drift detection is enabled. | Make the intended change in Git instead of editing the live object. |
| Release remediation repeatedly retries | Inspect the Helm Controller events and release history. | Correct the chart values or dependency, then reconcile the source and release again. |