Skip to main content

Set Up Ingress Controller and Gateway

This tutorial focuses on setting up APISIX Ingress Controller and APISIX gateway on a Kubernetes cluster for local learning and testing.

for API7 Enterprise users

API7 Dashboard generates the deployment scripts required to set up API7 Ingress Controller and Gateway. In the Dashboard:

  • Create a new gateway group of type Ingress Controller. The Dashboard will then generate deployment steps for the following, based on the namespace and name you specified:
    • Install the Ingress Controller.
    • Deploy the GatewayProxy configuration. Select the Gateway API tab if you plan to use Gateway API, or the Ingress tab if you plan to use Ingress or APISIX CRDs.
  • Deploy a Gateway instance on Kubernetes.

Once completed, skip to the next tutorial where you will learn how to create a route that proxies requests to an upstream service on the same cluster.

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.
  • For an API7 installation, use a Kubernetes version supported by the Ingress Controller release selected by API7 Dashboard.
  • 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.

Deployment Mode

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 the current APISIX umbrella chart selects a compatible Ingress Controller chart:

helm show chart apisix/apisix \
| 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 \
--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

You should see name of the GatewayProxy:

NAME AGE
apisix-config 12s

Show the configuration of the GatewayProxy resource in YAML format:

kubectl get gatewayproxy apisix-config -o yaml

You should see the configuration of the GatewayProxy resource similar to 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

If everything is ok, you should see that all pods are in the 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

If everything is ok, you should see a response similar to 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 9080:80 &

Then send a request to the gateway:

curl -sI "http://127.0.0.1:9080" | grep Server

If everything is ok, you should see the APISIX version:

Server: APISIX/3.18.0
info

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.

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:

gatewayclass-gateway.yaml
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 controllers can use the port in the Gateway listener for server_port route matching based on listener_port_match_mode (auto, explicit, or off). Neither controller dynamically opens data-plane ports. When listener-port matching injects a server_port predicate, the Gateway listener port must match the physical gateway listener port. With the mode set to off, as in this quickstart, a Kubernetes Service port such as 80 can map to a different container port such as 9080.

Apply the configuration to your cluster:

kubectl apply -f gatewayclass-gateway.yaml

To learn more about these parameters and how to adjust them as needed, see Define Controller and Gateway.

Next Step

In the next tutorial, you will learn how to create a route that proxies requests to an upstream service on the same cluster.