Set Up Ingress Controller and Gateway
Set up an Ingress Controller and gateway on Kubernetes, then prepare to create your first route. API7 Dashboard generates the API7 deployment, while the APISIX path below provides a runnable Helm installation for local learning and testing.
Set Up API7 Ingress Controller
API7 Dashboard generates the deployment commands and connection configuration for API7 Ingress Controller and Gateway. Follow the generated steps for your gateway group, then verify the deployment in Kubernetes and the Dashboard.
Prerequisites
- Access to API7 Dashboard with permission to create an Ingress Controller gateway group, retrieve its deployment configuration, and add gateway instances. For local evaluation, start with the API7 Gateway Quick Start.
- A Kubernetes cluster running version 1.31 or later that is supported by the controller release selected by Dashboard.
- Helm version 3.8 or later and kubectl, configured to use the target cluster.
- Kubernetes permissions to install CRDs, cluster-scoped RBAC resources, and the controller and gateway workloads.
Prepare the Deployment
In Gateway Settings → Deployment, configure Admin API Address with an API7 control-plane address reachable from the controller pods. Configure DP Manager Address with an address reachable from the gateway pods. A local quickstart address such as localhost refers to the pod itself when used inside Kubernetes; use addresses that the pods can reach.
Choose a namespace for the deployment and keep it consistent in the generated controller, GatewayProxy, and gateway commands. The controller installation command includes --create-namespace, so it creates the namespace if it does not exist. Run that command before applying the generated manifests.
Examples in later guides use aic as the namespace. Substitute the namespace you selected if it differs.
Deploy the Controller and Gateway
API7 Dashboard and API7 Ingress Controller are released independently, so a generated command may select a different controller release than this documentation covers. Before running it, compare both --version and deployment.image.tag with API7 Deployment Versions.
- In Gateway Groups, add a gateway group of type Ingress Controller.
- In Deployment Steps, enter the controller namespace and release name, generate its installation script, and run it against the target cluster.
- Generate and apply the GatewayProxy configuration in the same namespace. Select Gateway API to deploy the generated GatewayClass and Gateway, or Ingress to deploy the IngressClass for Ingress or APISIX CRDs. Keep the generated connection settings and resource names.
- In Gateway Instances for this gateway group, add a gateway instance, select Kubernetes deployment, and run the generated deployment command.
If you retain the generated commands and connection configuration for reproducibility or troubleshooting, store them securely because they contain credentials.
Verify Installation
Check the controller and gateway Deployments in the namespace you selected:
kubectl get deployments,pods,services -n <namespace>
kubectl rollout status deployment/<ingress-controller-deployment> -n <namespace>
kubectl rollout status deployment/<gateway-deployment> -n <namespace>
Both Deployments should complete their rollout, and their pods should be ready. Use the Deployment names returned by the first command rather than assuming the Helm release name is the Deployment name.
For Gateway API, check the generated connection and gateway resources:
kubectl get gatewayproxy,gateway -n <namespace>
kubectl get gatewayclass <gatewayclass-name>
For Ingress or APISIX CRDs, check the GatewayProxy and generated IngressClass instead:
kubectl get gatewayproxy -n <namespace>
kubectl get ingressclass <ingressclass-name>
In the gateway group's Gateway Instances, confirm that the gateway instance appears with a Healthy status. Ready pods show that the workloads are running; they do not prove that routing configuration has synchronized. Continue to Proxy Requests and send a request through the gateway to verify the complete traffic path. Use your generated namespace and Gateway or IngressClass name in that tutorial.
If the resources are present but traffic does not reach the backend, see Troubleshoot Manifest Translation and Synchronization.
Set Up APISIX Ingress Controller
The following sections install APISIX Ingress Controller and APISIX gateway with Helm on a Kubernetes cluster for local evaluation.
Prerequisites
- Install Docker as a dependency of kind.
- Install kind. For the APISIX installation, create a local Kubernetes 1.31+ cluster or use an existing cluster that meets this requirement.
- Install Helm (version 3.8+).
- Install kubectl.
Create a Namespace
Create a new namespace aic (or any name of your choice):
kubectl create namespace aic
Optionally, you can set the namespace as the preferred namespace:
kubectl config set-context --current --namespace=aic
Install APISIX and APISIX Ingress Controller
In this section, you will install APISIX and APISIX Ingress Controller in standalone mode on your Kubernetes cluster.
The standalone mode is recommended over the traditional etcd-based deployment, as it avoids the stability issues that can occur when running APISIX and etcd together inside Kubernetes.
Add the APISIX chart repository and update its metadata:
helm repo add apisix https://apache.github.io/apisix-helm-chart
helm repo update
Confirm that APISIX umbrella chart 2.18.0 selects a compatible Ingress Controller chart:
helm show chart apisix/apisix --version 2.18.0 \
| grep -A 4 'name: apisix-ingress-controller'
The dependency entry should show version: 1.3.0 or a later compatible version. Do not override only the controller image on an older umbrella chart, because doing so does not update the CRDs, RBAC, or webhook configuration.
Install APISIX and APISIX Ingress Controller:
helm install apisix \
--version 2.18.0 \
--namespace aic \
--create-namespace \
--set apisix.deployment.role=traditional \
--set apisix.deployment.role_traditional.config_provider=yaml \
--set etcd.enabled=false \
--set ingress-controller.enabled=true \
--set ingress-controller.config.provider.type=apisix-standalone \
--set ingress-controller.apisix.adminService.namespace=aic \
--set ingress-controller.gatewayProxy.createDefault=true \
--set ingress-controller.webhook.enabled=true \
--set ingress-controller.config.listenerPortMatchMode=off \
apisix/apisix
❶&❷ Start APISIX in API-driven standalone mode.
❸ Disable the etcd deployment.
❹ Install APISIX Ingress Controller (along with APISIX).
❺ Configure the controller to operate in standalone mode, where configuration is pushed directly to the gateway instead of using etcd.
➏ Configure the namespace of the APISIX Admin Service that the controller will connect to for pushing configurations.
➐ Automatically creates a GatewayProxy resource that defines the connection information with APISIX.
The command also enables the admission webhook so invalid Ingress Controller resources are rejected before reconciliation.
Setting listenerPortMatchMode to off avoids route mismatches when Kubernetes Service ports such as 80 and 443 map to APISIX container ports 9080 and 9443. See Configuration File for other matching modes.
See the GatewayProxy resource
Find the name of the GatewayProxy:
kubectl get gatewayproxy -n aic
You should see the GatewayProxy name:
NAME AGE
apisix-config 12s
View the GatewayProxy configuration in YAML format:
kubectl get gatewayproxy apisix-config -n aic -o yaml
The output should resemble the following:
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
annotations:
meta.helm.sh/release-name: apisix
meta.helm.sh/release-namespace: aic
creationTimestamp: "2025-11-25T10:07:40Z"
generation: 1
labels:
app.kubernetes.io/managed-by: Helm
name: apisix-config
namespace: aic
resourceVersion: "3073"
uid: 6b0a30db-530c-4f14-b127-024d0507b18e
spec:
provider:
controlPlane:
auth:
adminKey:
value: edd1c9f034335f136f87ad84b625c8f1
type: AdminKey
service:
name: apisix-admin
port: 9180
type: ControlPlane
Verify Installation
To verify that APISIX Ingress Controller is installed and running, check the status of the pods:
kubectl get pods -n aic
The APISIX gateway and Ingress Controller pods should report a Running status:
NAME READY STATUS RESTARTS AGE
apisix-bffb459b8-rcqz7 1/1 Running 0 2m53s
apisix-ingress-controller-ff66c9585-wlxfh 2/2 Running 0 2m53s
You can also check the status of the services:
kubectl get services -n aic
The output should resemble the following:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apisix-admin ClusterIP 10.96.61.223 <none> 9180/TCP 2m54s
apisix-gateway NodePort 10.96.108.211 <none> 80:30834/TCP 2m54s
apisix-ingress-controller ClusterIP 10.96.249.157 <none> 8080/TCP 2m54s
apisix-ingress-controller-webhook-svc ClusterIP 10.96.161.96 <none> 443/TCP 2m54s
To check the installed APISIX version, first map the gateway service port to the local machine's port:
kubectl port-forward svc/apisix-gateway -n aic 9080:80 &
Then send a request to the gateway:
curl -sI "http://127.0.0.1:9080" | grep Server
The response should include the APISIX version:
Server: APISIX/3.19.0
If you would like to use a load balancer to expose the service on the kind cluster as an alternative to port forwarding, see load balancer kind documentation.
Define Controller and Gateway
See the Gateway API tab if you plan to use Gateway API, or the Ingress tab if you plan to use Ingress or APISIX CRDs.
- Gateway API
- Ingress
The APISIX chart installs the Gateway API 1.6.0 CRDs. Verify that the API server serves the v1 L4 Route APIs used in these guides:
kubectl get crd \
tcproutes.gateway.networking.k8s.io \
udproutes.gateway.networking.k8s.io \
tlsroutes.gateway.networking.k8s.io \
-o jsonpath='{range .items[*]}{.metadata.name}{": "}{range .spec.versions[?(@.served==true)]}{.name}{" "}{end}{"\n"}{end}'
Each row should include v1. If your platform manages Gateway API CRDs separately, install the Gateway API 1.6.0 standard bundle through that owner before installing the controller. Configure the controller release to skip its bundled CRDs.
If you will be using Gateway API, define the GatewayClass and Gateway resources:
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: apisix
spec:
controllerName: apisix.apache.org/apisix-ingress-controller
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
namespace: aic
name: apisix
spec:
gatewayClassName: apisix
listeners:
- name: http
protocol: HTTP
port: 80
infrastructure:
parametersRef:
group: apisix.apache.org
kind: GatewayProxy
name: apisix-config
The port declares the Gateway API listener; it does not open a corresponding data-plane port. This quickstart disables listener-port matching so the route can match when Service port 80 maps to APISIX container port 9080.
Apply the configuration to your cluster:
kubectl apply -f gatewayclass-gateway.yaml
If you will be using Ingress or APISIX CRDs, the following IngressClass resource is already applied during installation. You may proceed without any additional configuration.
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: apisix
spec:
controller: apisix.apache.org/apisix-ingress-controller
parameters:
apiGroup: apisix.apache.org
kind: GatewayProxy
name: apisix-config
namespace: aic
scope: Namespace
To learn more about these parameters and how to adjust them as needed, see Define Controller and Gateway.
Test Routing
Continue to Proxy Requests to create a route to an upstream service on the same cluster. Controller releases may become available at different times, so follow any product-specific availability notes in later guides.
Clean Up the APISIX Local Evaluation
This cleanup applies only to the APISIX local evaluation installed in this guide. Do not use it to remove an API7 deployment generated by the Dashboard.
Delete the routes and other user-created resources from the evaluation first. If you used Gateway API, delete the evaluation Gateways and GatewayClass apisix while the controller is still running, then wait for the GatewayClass deletion to finish. Finally, uninstall the apisix Helm release from namespace aic. Helm removes the chart-managed webhook Secrets; delete other Secrets only when they are explicitly identified as evaluation resources that are not shared.