When APISIX custom resources are the right way to route traffic
Use APISIX custom resources when your Kubernetes routes need APISIX plugins for authentication, traffic control or observability, and when you want the Ingress Controller to manage that configuration. In the APISIX Ingress Controller 2.x line, the controller is the source of truth for these resources. The controller translates Kubernetes Ingress v1 resources, Gateway API resources and APISIX custom resources into APISIX configuration, so the choice of resource type determines how much APISIX behavior you can express in Kubernetes objects. Plain Ingress v1 and Gateway API cover standard routing, while the APISIX resources are the place where plugin configuration lives. Confirm with the controller documentation which plugin settings each resource type exposes before you split routes across them.
Three resources cover most decisions. Use ApisixRoute for routes that need plugins, upstream settings or path rules that go beyond a standard Ingress. Use ApisixConsumer for consumer credentials, so that API keys and similar secrets are attached to a consumer object rather than written into each route. Use ApisixGlobalRule for policy that applies to all traffic, which replaces ApisixClusterConfig because the 2.0 release removed that CRD. The GatewayProxy CRD connects the controller to the data plane, so you also need to decide which APISIX gateway instances each set of resources targets. Review the APISIX Ingress Controller upgrade guide before migrating any ApisixClusterConfig objects, since those manifests will not load unchanged.
The source-of-truth model has a practical consequence for operations. Changes made directly through the Admin API are overwritten on the next full sync, so an emergency route edit made in the Admin API can disappear without warning. Keep plugin configuration in version-controlled manifests and make every change through them. Also confirm the controller and APISIX versions together: the 2.0 and 2.1 releases support APISIX 3.0 and later and recommend 3.13, and the downloads page lists 2.2.0 as the current controller release. Check the APISIX Ingress Controller overview for the pairing that matches your cluster before you commit to a design.
Choosing between Ingress, Gateway API and APISIX CRDs
Each Kubernetes routing object trades portability against control. Ingress and Gateway API objects travel between controllers, while APISIX custom resources expose plugins, consumers and global behavior that those standard objects do not model directly. The decisions below set which objects your teams write and who owns them.
Portability of standard objects
If routes must move between gateways or the team wants vendor-neutral manifests, standard Ingress v1 or HTTPRoute objects are the safer base. The APISIX Ingress Controller translates them into APISIX configuration, so the manifests stay readable to other controllers. Check which fields your routes need before committing, because anything APISIX-specific will not carry over unchanged.
Plugin-rich routes need ApisixRoute
ApisixRoute is the choice when a route needs APISIX plugins such as authentication, rate limits or request transforms attached per path. Standard objects cannot express most of these settings without annotations that differ by controller. Inventory each route's plugin list early, since that list determines which custom resources the team must write and review.
Credentials belong in ApisixConsumer
ApisixConsumer holds the credentials that plugins such as key-auth or jwt-auth check. Keeping consumers as separate objects lets security teams review who can call which APIs without reading every route. Decide where consumer secrets come from, because the controller will sync whatever the manifests reference and Kubernetes Secrets are stored unencrypted in etcd unless encryption at rest is configured.
Global behavior uses ApisixGlobalRule
ApisixGlobalRule applies plugins to every request the gateway handles, which makes it the place for organization-wide controls such as logging or security headers. A global rule affects all routes, so a mistake here has a wider blast radius than a single route change. Confirm the global rule set in version control and in review, and check which existing ApisixClusterConfig usage must move to it.
Gateway ownership and change control
Who edits the resources decides whether the gateway stays consistent. In Ingress Controller 2.0 and later the controller is the source of truth, so manual Admin API changes are overwritten on the next full sync. Platform teams should own the gateway resources and application teams should request changes through the same review path as other manifests.
Coexistence with existing Ingress
Teams moving from another controller often run Ingress objects beside new custom resources during a transition. Confirm which controller claims each Ingress class and host before applying both, so two controllers do not program the same hostname. Plan a per-route cutover with a rollback path rather than moving every route in one change.
What ApisixRoute, ApisixConsumer and ApisixGlobalRule each do
ApisixRoute is the custom resource to use when a Kubernetes route needs more than host and path matching. The Ingress Controller reads it and produces the matching APISIX route, with its match conditions, upstreams and plugins, in the gateway's configuration. Use it when one endpoint needs rate limiting, header transformation, an authentication plugin or several backends with weighted traffic. Simpler routing can stay on Ingress v1 or Gateway API resources, since the controller translates all three into APISIX configuration. See the overview of the Ingress Controller for the resource types it supports.
- Match conditions: Host, path, method and header rules select the traffic that a route handles.
- Upstreams: The route points at Kubernetes services, and weighted backends can split traffic between versions.
- Plugins on the route: Authentication, traffic control and transformation settings apply only to the paths this route covers.
- Per-route scope: Changes to one route do not alter other routes, which keeps review of a single API change contained.
- Schema by version: The fields a route accepts depend on the controller and APISIX versions, so the same manifest may behave differently after an upgrade.
Before you standardize on this resource, confirm the API version and field names your controller release accepts, and test a representative route in a non-production cluster.
ApisixConsumer represents an identity that calls the APIs, such as a partner system, an internal service or an individual application, and it carries the credentials that identity presents. Consumer-scoped plugins apply only to requests that authenticate as that consumer, so one partner can have a different quota or key policy from another. Credentials are usually held in Kubernetes Secrets, which are stored unencrypted in etcd by default, so encryption at rest and restricted read access to those Secrets are part of the design, not an afterthought.
- Credential types: Key, JWT and HMAC-style credentials are configured on the consumer, and the plugin you choose sets which fields are required.
- Consumer-scoped plugins: Rate limits or access rules can be tied to a consumer rather than to a route.
- Secret handling: Keep credential values in Secrets with encryption at rest enabled and least-privilege RBAC on list and watch.
- Field changes by version: The hmac-auth plugin was rewritten in APISIX 3.11.0, and the required access key field became
key_idfor APISIX 3.11 and later, so older consumer manifests need review. - Manual edits: Consumers created through the Admin API directly are overwritten on the next full sync, so credential issuance must go through the manifests.
Ask your security team which system is the source of record for each consumer's credentials, and confirm the field names against the plugin version you deploy.
ApisixGlobalRule holds plugin configuration that applies across the gateway rather than to a single route or consumer. It is the resource that replaces ApisixClusterConfig in Ingress Controller 2.0, where the older resource was removed. Global rules suit controls every API should share, such as a common logging or security header policy. Because they touch all traffic, a mistake here has a wider effect than an error in one route, so changes need the same review you would give a gateway-wide setting.
- Replacement path: Move any
ApisixClusterConfigobjects toApisixGlobalRuleas part of the controller upgrade, and check the upgrade guide for the steps. - Scope: Plugins defined here run for every route, so list the globally applied plugins in your design document.
- Interaction with route plugins: Confirm in the plugin documentation for your APISIX version how global and route-level settings combine when both define the same plugin.
- Controller ownership: Global rules edited directly in the Admin API are overwritten on the next full sync, so the manifest is the record.
- Change control: Treat a global rule change as a gateway release, with a rollback manifest and a test run against representative routes.
Before upgrading, search your manifests and cluster for ApisixClusterConfig objects and confirm which global behaviors they currently provide.
The GatewayProxy CRD is how the Ingress Controller connects to the APISIX data plane, the gateway pods that handle client traffic. The controller is the source of truth for the configuration it manages, so the data plane must be reached through the endpoint and mode defined here. In Ingress Controller 2.0 and later, GatewayProxy replaces the mock-etcd approach that was removed, and the controller sends configuration to APISIX rather than letting gateways read it from a separate store. The standalone, API-driven mode needs APISIX 3.13 or later, and the controller releases 2.0.0 and 2.1.0 recommend 3.13.
- Endpoint definition:
GatewayProxyidentifies which APISIX instances receive the configuration produced from the other resources. - Mode choice: Standard etcd-backed operation and API-driven standalone operation have different failure and recovery behavior, so choose before you build.
- Version floor: Standalone API-driven mode requires APISIX 3.13 or later, so confirm the data plane image before enabling it.
- Access control: Restrict who can edit
GatewayProxyand the Admin API credentials it uses, because they determine where configuration lands. - Full sync: Each full sync rewrites the data plane from the manifests, so anything added by hand is removed.
Before deployment, confirm which mode your team will run and which APISIX version the data plane image carries.
Which resource fits which configuration need
This table compares ApisixRoute, ApisixConsumer, ApisixGlobalRule, standard Ingress v1 and HTTPRoute across the attributes that drive the decision: typical use, plugin support, credential handling, scope and portability. Read each row against your controller version, because plugin coverage and field names change between Ingress Controller releases and should be confirmed before you commit a design.
| Attribute | ApisixRoute | ApisixConsumer | ApisixGlobalRule | Ingress v1 and HTTPRoute |
|---|---|---|---|---|
| Typical use | Routes that need APISIX plugins such as auth, rate limits or request rewrites | Identities and credentials that authentication plugins check against | Plugins that apply to every request, such as shared logging or security headers | Portable host and path routing, with plugins limited to what the standard allows |
| Plugin support | Full APISIX plugin set, confirmed per controller version | Attaches credentials to plugins such as key-auth or jwt-auth | Global plugins only, applied across all routes | Limited to standard filters or annotations, varying by implementation |
| Credential handling | References consumers and secrets but does not store credentials itself | Holds consumer credentials, ideally sourced from Kubernetes Secrets | Does not handle credentials directly | No consumer model; credentials handled by an external auth service |
| Scope | Namespaced, bound to one service or host set | Namespaced, linked to routes through plugin configuration | Cluster-wide effect on the gateway data plane | Namespaced, with cross-namespace references controlled by policy |
| Portability | Specific to APISIX; not portable to other gateways | Specific to APISIX credential model | Specific to APISIX; confirm replacement fields in your version | Highest portability across ingress implementations |
| Replaces or succeeds | Routes that previously used annotations for APISIX features | Consumer objects from earlier APISIX Ingress Controller releases, to be confirmed | ApisixClusterConfig, removed in Ingress Controller 2.0 | Not applicable |
| Change control risk | Controller overwrites manual Admin API edits on the next full sync | Same overwrite behavior; manage credentials through the cluster | Global changes affect all traffic, so review them as platform changes | Managed as standard Kubernetes objects through your existing pipeline |
Deploying APISIX CRDs with the Ingress Controller
This sequence takes a Kubernetes cluster from version checks to a working APISIX custom resource setup, with each step confirmed before the next begins. The end state is a GatewayProxy pointing at your data plane, a tested ApisixRoute and ApisixConsumer synced into APISIX, and any legacy ApisixClusterConfig replaced by ApisixGlobalRule.
Confirm controller and APISIX version compatibility
Your platform engineer checks the APISIX Ingress Controller overview guidance before installing anything. The controller 2.x releases support APISIX 3.0 and later, and the project recommends APISIX 3.13, which is also the minimum for API-driven standalone mode. Record the controller version, the APISIX version and the Kubernetes version your cluster runs. Done when the three versions appear in a written compatibility note that your architect has approved. Confirm the exact support matrix with the project before you pin any version, because later releases may change it.
Review the 2.0 source of truth model
Before the first sync, the team agrees on how changes are made. In Ingress Controller 2.0 the controller is the source of truth, so manual Admin API edits are overwritten on the next full sync. Assign ownership so that routes and consumers change only through Kubernetes manifests in Git. Also confirm that ApisixClusterConfig and mock-etcd mode are no longer used, since both were removed in 2.0. Done when the change process is documented and nobody on the team holds a plan to edit the Admin API directly.
Install the CRDs and the Ingress Controller
The platform team installs the APISIX Ingress Controller and its custom resource definitions into a non-production namespace first, using the install method your team has standardized. Confirm that the APISIX custom resources, including ApisixRoute, ApisixConsumer and ApisixGlobalRule, are registered with the API server. Check that the controller pod is running and that its logs show no errors about unknown kinds or version mismatches. Done when the custom resource types list in the cluster and the controller reports healthy.
Create the GatewayProxy for the data plane
Create a GatewayProxy resource that tells the controller where the APISIX data plane is and how to reach its Admin API. Store the admin credential in a Kubernetes Secret rather than in the manifest, and restrict read access to that Secret with least-privilege RBAC, since Kubernetes Secrets are stored unencrypted in etcd unless you configure encryption at rest. Confirm the endpoint matches the Admin API port in your deployment (9180 in traditional mode). Done when the GatewayProxy reports a ready status and the controller log shows a successful connection to the data plane.
Apply a test ApisixRoute and ApisixConsumer
Apply a small ApisixRoute that targets a non-production upstream service and references the GatewayProxy, along with an ApisixConsumer that carries one test credential and points to an authentication plugin you have chosen, such as key-auth or jwt-auth. Keep the plugin set minimal for this test so failures are easy to isolate. Check that the resource status shows accepted, not an error. Done when both resources report a synced status and no validation messages appear in the controller events.
Verify the synced configuration in APISIX
Confirm that the controller has written the route and consumer into APISIX. Query the data plane through the Admin API using a read request, and compare the route ID, upstream and plugin settings with your manifest. Then send a request through the gateway port with the test credential, expecting a successful response, and again without a credential, expecting rejection. Done when both requests return the expected results and the Admin API output matches the manifest. Record the test as your baseline for regression checks.
Migrate ApisixClusterConfig to ApisixGlobalRule
If your cluster has an existing ApisixClusterConfig, convert its settings into an ApisixGlobalRule because the older CRD was removed in Ingress Controller 2.0. Translate each global plugin setting one at a time, apply the new resource to the test environment, and repeat the verification from the previous step to confirm that global behavior is unchanged. Then delete the old resource. Done when the ApisixGlobalRule is synced, the old ApisixClusterConfig is gone and test requests still behave as before. Review the plugin list carefully, since any setting missed in translation will silently stop applying.
Confirm full-sync behavior before production
Before promoting the setup, test that the controller overwrites an intentional manual Admin API change on the next full sync. Make a harmless change to the test route through the Admin API, wait for the controller to reconcile, and confirm the change reverts to the manifest value. Document the observed reconciliation behavior and the sync interval in your environment. Done when the team has seen the overwrite happen and has agreed that all production changes go through Git.
What happens to manual Admin API changes after the controller takes over
In APISIX Ingress Controller 2.0 and later, the controller is the source of truth, so any change made directly through the APISIX Admin API is overwritten on the next full sync. A route tweaked by hand, a consumer key added with curl, or a global plugin toggled in the dashboard will quietly disappear the next time the controller reconciles. Before cutover, every manual change in the existing gateway must be recreated as an ApisixRoute, ApisixConsumer or ApisixGlobalRule manifest and stored in version control, or it will not survive the switch.
The 2.0 release also removed mock-etcd mode and the ApisixClusterConfig CRD. If your current environment or runbooks reference ApisixClusterConfig, those manifests must be migrated to ApisixGlobalRule for global rules, and the data plane connection is now declared through a GatewayProxy resource. Confirm the exact field mapping and any plugin-level differences against the APISIX Ingress Controller upgrade guide for the controller version you plan to run, since a manifest that applies cleanly may still change behavior.
Audit the existing environment before cutover. Export the live configuration from the Admin API and compare it against what is in Git, listing every route, consumer, global rule and plugin that exists only in the running gateway. Check scripts, CI jobs, monitoring hooks and partner onboarding procedures for calls to the Admin API that write configuration, since those will silently fail or be reverted after the controller takes over. Also confirm the hmac-auth field name used by any consumer, because the controller guide notes that access_key became key_id for APISIX 3.11 and later. Run the audit in a staging cluster first and record which teams own each item so that drift has a clear owner after go-live.
Questions teams ask before using APISIX CRDs
How much effort does a CRD-based APISIX build take?
Effort depends mostly on how many routes, plugins and consumers the gateway must carry, and how many clusters and environments the same configuration must reach. A small set of Ingress-style routes with one authentication method is far less work than a catalog of plugin-rich routes spread across several clusters. The main drivers are the number of ApisixRoute and ApisixConsumer objects, the plugin chains you need on each, the identity provider integration, the number of environments, and how much the existing gateway configuration must be translated and tested. No duration is supplied for this work, so ask any partner for a written scope that lists each route group, plugin, credential type and environment before agreeing a timeline.
Can our team build and run this without outside help?
A team with Kubernetes operations experience and someone who understands APISIX plugin behavior can build it in house, provided it has time to test each resource type. The skills that are often thin are Kubernetes RBAC and namespace design, secret handling for consumer credentials, and knowing which changes the controller will overwrite. Check whether your engineers have run a Kubernetes controller that reconciles state, whether they can read the APISIX Ingress Controller upgrade guide and act on it, and whether they have a rollback path for routes. If any of these are missing, a fixed-scope engagement can cover design and knowledge transfer while your team keeps ownership.
What does the work need from our side?
The work needs named owners in four areas: the platform team that runs the Kubernetes clusters and namespaces, the API owners who define routes, upstreams and access rules, the identity team that issues client credentials and provides OpenID Connect or JWT settings, and the security team that approves TLS, secret storage and the list of plugins allowed in production. You will also need access to a non-production cluster, a Git repository for manifests, and a decision on who may change resources in the cluster. Ask for these inputs to be written into the scope so that the vendor and your teams know what is due and when.
How do ApisixConsumer resources handle the hmac-auth key_id change?
For APISIX 3.11 and later, the hmac-auth plugin uses key_id where earlier versions used access_key, according to the APISIX Ingress Controller 2.0 upgrade guide. If your consumer definitions still use the old field, they need to be rewritten before or during the upgrade, or the credential will not match the plugin's expected configuration. Also check the signed_headers default, which APISIX 3.17.0 changed to date, because clients that sign other headers will fail verification. Put the consumer manifests under version control, test one signed request end to end in a staging cluster, and confirm the exact field names against the APISIX release you run before rolling out.
Can our existing Ingress setup keep running alongside these resources?
Yes, the APISIX Ingress Controller 2.x translates Kubernetes Ingress v1, Gateway API resources and APISIX custom resources into APISIX configuration, so Ingress objects and custom resources can coexist during a migration. The practical risks are duplicate hostnames and paths, two controllers claiming the same ingress class, and plugin behavior that differs between the old and new definitions. Move one route group at a time, compare responses and logs in parallel, and keep the old Ingress object ready for rollback. Confirm the ingress class settings and the controller version against the overview and upgrade guide before you start.
Why does a manual Admin API change disappear after an upgrade?
In APISIX Ingress Controller 2.0 the controller is the source of truth, and manual Admin API changes are overwritten on the next full sync. ApisixClusterConfig was removed, and ApisixGlobalRule now handles global rules, with a GatewayProxy resource connecting the data plane. Any emergency change made directly through the Admin API will therefore be lost, sometimes without warning. Require that every change goes through a manifest in Git, restrict Admin API access to the platform team, and add a drift check to your pipeline so unexpected differences are detected quickly.
What ongoing work follows the initial build?
After go-live, recurring work includes tracking APISIX and Ingress Controller releases, reading upgrade guides for breaking field changes, renewing certificates and client credentials, reviewing plugin changes, and running the restore steps for etcd or Kubernetes state. Some of this can be handled by your team, and some can be covered by a retainer for upgrades and support, which is available from DeployOpen on request. Ask any provider to state in writing which of these tasks are included, how often they occur, and how quickly they will be handled.
Securing CRD-managed routes and credentials
When APISIX routes and consumers are declared as Kubernetes objects, the cluster becomes the place where gateway credentials and routing policy live. The controls below decide who can change those objects, where the secrets sit, and how changes are reviewed and traced back to a person.
Encrypt Secrets or move them out of etcd
Consumer credentials for key-auth, jwt-auth or hmac-auth are usually held in Kubernetes Secrets, and those Secrets are stored unencrypted in etcd by default. Confirm that encryption at rest is enabled for the API server's Secret resources, or that credentials are pulled from an external store through the Secrets Store CSI Driver. Ask who holds etcd snapshots, because a snapshot exposes the same data.
Restrict RBAC on consumer and route objects
Anyone who can create or patch an ApisixConsumer can add a credential, and anyone who can patch an ApisixRoute can redirect traffic or add a plugin. Grant create, update and delete on these kinds only to the pipeline identity and a small platform group. Keep list and watch on Secrets narrow, because read access to the consumer's Secret is read access to the credential.
Harden the controller pods
The APISIX Ingress Controller reads cluster-wide resources and writes to gateway configuration, so its pod is a high-value target. Apply the restricted profile of the Pod Security Standards to its namespace, run it as non-root, drop unneeded capabilities and limit its service account to the resources it watches. Confirm this against the chart version you deploy.
Control access to the Admin API
The Ingress Controller 2.0 treats the cluster as the source of truth, so a manual change through the APISIX Admin API is overwritten on the next full sync. That protects the declared state but does not block the attempt. Confirm the Admin API listener is reachable only from the controller and operators, and that its admin key is stored as a Secret with restricted access rather than in a values file.
Review manifest changes through GitOps
Because the CRDs define routes, plugins and credentials, a manifest merge is a production change. Route every ApisixRoute, ApisixConsumer and ApisixGlobalRule change through a pull request with a second reviewer, and have the pipeline run schema validation before sync. Ask whether the GitOps controller can be the only identity that applies these kinds to the cluster.
Audit who edited what
Kubernetes audit logs record requests against API objects, which lets you trace who created or changed a consumer or global rule and when. Confirm that audit policy captures these resource kinds at a level that includes the request body, and that logs are shipped to storage the gateway team cannot edit. Test the trail by reproducing a change in a non-production cluster and locating it.
How DeployOpen scopes APISIX CRD work
DeployOpen agrees a written scope before any APISIX work starts, and the quote follows from that document. For CRD-based work, the scope lists each Kubernetes cluster that runs the APISIX Ingress Controller, the namespaces and the ApisixRoute objects that will be built or migrated, the ApisixConsumer objects and the credential sources behind them, the ApisixGlobalRule objects that apply across routes, and the cutover plan that moves traffic from the current gateway. It also records which plugins each route needs, which identity provider backs the consumers, and who owns the Git repository that holds the manifests. Each of these items changes the effort, so each one should appear as a line the reader can question.
The scope should also name the decisions the reader must make before the build begins. Confirm which Ingress Controller release line you will run and the APISIX version it targets, because the controller's upgrade guide ties behavior to the controller version. Confirm whether any team still edits the Admin API directly, since those changes will be overwritten on the next full sync. Confirm which Gateway API or Ingress resources remain during the transition. Ask for a written statement of what is excluded, such as custom plugin code, external identity provider configuration, or load testing, so that a later change request does not reopen the price.
Ongoing work is handled separately. Support, controller and APISIX upgrades, and continuous testing of the gateway are available as retainers, which are agreed in their own written terms after the initial build. Ask any partner, DeployOpen included, to state in the quote what is one-time, what recurs, who is responsible for the Kubernetes cluster and etcd, and how a controller upgrade will be tested against your existing CRD manifests before it reaches production.
How DeployOpen works on this
DeployOpen plans and implements self-hosted APISIX inside your own infrastructure, including the decision about whether APISIX custom resources fit your routes at all. We scope the CRD model against your existing Ingress or Gateway API resources, build it through version-controlled manifests, and hand over a configuration your team can operate and review.
How we scope
- We confirm which routes need plugin-rich ApisixRoute objects and which can stay on standard Ingress or Gateway API resources.
- We map credential ownership to ApisixConsumer objects and agree who may create or change them.
- Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
How we build
- We write ApisixRoute, ApisixConsumer and ApisixGlobalRule manifests in your Git repository, reviewed like other infrastructure code.
- We confirm the Ingress Controller version against your APISIX version and the plugin schemas in use before deployment.
- We test routes, authentication and global rules in a non-production cluster, including checks that manual Admin API changes are overwritten as expected.
How we hand over
- You receive the manifests, a runbook covering the controller as source of truth, and a record of the design decisions behind each resource type.
- We document the rule for changes: make them in Git, never in the Admin API, and how to recover from accidental drift.
- Your team walks through the handover and a test cycle with us before production cutover.
How we support
- Ongoing support, controller upgrades and continuous testing are available as retainers, scoped in writing.
- We review plugin schema changes and controller release notes when your APISIX or Ingress Controller version moves.
- We agree with you which upgrade and regression checks run on each change and who approves production rollout.

