This article is a part of the series "Hands-On With Apache APISIX Ingress."

Other articles in the series:

In Kubernetes, Ingress is a native object that allows you to access your services externally by defining a set of rules. Using a reverse proxy, an Ingress controller implements these defined rules and routes external traffic to your services.

Kubernetes Ingress
Kubernetes Ingress

Apache APISIX is an open source API gateway (a souped-up reverse proxy) that provides features like authentication, traffic routing, load balancing, canary releases, monitoring, and more. APISIX also supports custom Plugins and integrates with popular open source projects like Apache SkyWalking and Prometheus. To learn more about APISIX, you can see the official documentation.

The Apache APISIX Ingress controller sits between the defined Ingress rules and the APISIX API gateway. It configures the proxy to route traffic based on the defined rules.

APISIX Ingress
APISIX Ingress

This hands-on tutorial will teach you how to set up the APISIX Ingress controller on your Kubernetes cluster and route traffic to your services.

Before you move on, make sure you:

  1. Have access to a Kubernetes cluster. This tutorial uses minikube for creating a cluster.
  2. Install and configure kubectl to communicate with your cluster.
  3. Install Helm to deploy the APISIX Ingress controller.

Deploying a Sample Application

We will use a sample HTTP server application (bare-minimum-api) to demonstrate the working of the Ingress controller.

While running the application, you can set a “version” and a port to listen to. For this example, we will create two “versions” of this application which will return different responses as shown below:

bare-minimum-api
bare-minimum-api

We configure the v1 API as v1 and the v2 API as v2 manually while deploying them

You can deploy the application on your Kubernetes cluster by running:

kubectl run bare-minimum-api-v1 --image navendup/bare-minimum-api --port 8080 -- 8080 v1.0
kubectl expose pod bare-minimum-api-v1 --port 8080

To test the application outside the cluster, you can use port-forward:

kubectl port-forward bare-minimum-api-v1 8080:8080

Now, if you open up a new terminal window and run:

curl http://127.0.0.1:8080

You will get back a response from the application:

Hello from API v1.0!

Similarly, you can deploy another “version” of the application by running:

kubectl run bare-minimum-api-v2 --image navendup/bare-minimum-api --port 8080 -- 8080 v2.0
kubectl expose pod bare-minimum-api-v2 --port 8080

Now, we can deploy APISIX Ingress and expose these applications to external traffic.

Deploying APISIX Ingress

APISIX and APISIX Ingress controller can be installed using Helm:

helm repo add apisix https://charts.apiseven.com
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
kubectl create ns ingress-apisix
helm install apisix apisix/apisix \
  --set gateway.type=NodePort \
  --set ingress-controller.enabled=true \
  --namespace ingress-apisix \
  --set ingress-controller.config.apisix.serviceNamespace=ingress-apisix
kubectl get pods --namespace ingress-apisix

Note: We are using NodePort as the Gateway service type. You can also set it to LoadBalancer if your cluster has one.

Helm will create five resources in your cluster:

  1. apisix-gateway: The data plane that handles external traffic.
  2. apisix-admin: Control plane that processes configuration changes.
  3. apisix-ingress-controller: The ingress controller.
  4. apisix-etcd and 5. apisix-etcd headless: To store configuration and handle internal communication.

Once all the pods and services are running, you can test APISIX by accessing the Admin API:

kubectl exec -n ingress-apisix deploy/apisix -- curl -s http://127.0.0.1:9180/apisix/admin/routes -H 'X-API-Key: edd1c9f034335f136f87ad84b625c8f1'

If you get a response similar to the one shown below, APISIX is up and running:

{
  "action": "get",
  "node": {
    "key": "/apisix/routes",
    "dir": true,
    "nodes": []
  },
  "count": 0
}

Configuring APISIX Ingress

Once you have verified that the APISIX gateway and Ingress controller is running, you can create Routes to expose the deployed application to external traffic.

This will route traffic between the two application versions based on the client request:

Routing requests to v1
Routing requests to v1

Requests to the path /v1 should be routed to the bare-minimum-api-v1 service

Routing requests to v2
Routing requests to v2

Requests to the path /v2 should be routed to the bare-minimum-api-v2 service

To configure Routes, APISIX comes with declarative and easy-to-use custom resource:

apiVersion: apisix.apache.org/v2beta3
kind: ApisixRoute
metadata:
  name: api-routes
spec:
  http:
    - name: route-1
      match:
        hosts:
          - local.navendu.me
        paths:
          - /v1
      backends:
        - serviceName: bare-minimum-api-v1
          servicePort: 8080
    - name: route-2
      match:
        hosts:
          - local.navendu.me
        paths:
          - /v2
      backends:
        - serviceName: bare-minimum-api-v2
          servicePort: 8080

The APISIX Ingress controller converts this resource to an APISIX gateway configuration.

APISIX also supports configuration using native Kubernetes Ingress resource:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-routes
spec:
  ingressClassName: apisix
  rules:
    - host: local.navendu.me
      http:
        paths:
          - backend:
              service:
                name: bare-minimum-api-v1
                port:
                  number: 8080
            path: /v1
            pathType: Exact
          - backend:
              service:
                name: bare-minimum-api-v2
                port:
                  number: 8080
            path: /v2
            pathType: Exact

You can use either to configure APISIX but I prefer the easier APISIX custom resource. We can apply this manifest file to our cluster to create Routes in APISIX:

kubectl apply -f apisix-ingress-manifest.yaml

If the Ingress controller is configured correctly, you should see a response indicating that APISIX API gateway has been configured:

apisixroute.apisix.apache.org/api-routes created

Now, let’s test these Routes.

Testing the Created Routes

If you were following along using minikube and NodePort, you should be able to access APISIX through the Node IP of the service apisix-gateway. If the Node IP is not reachable directly (if you are on Darwin, Windows, or WSL), you can create a tunnel to access the service on your machine:

minikube service apisix-gateway --url -n ingress-apisix

This will show the URL with which you can access the apisix-gateway service.

You can send a GET request to this URL and it would be Routed to the appropriate service:

curl http://127.0.0.1:51538/v2 -H 'host:local.navendu.me'
Hello from API v2.0!

Now you have APISIX routing traffic to your applications! You can try the two configured Routes and see APISIX routing the requests to the appropriate application.

What’s Next?

In this tutorial, you learned to set up APISIX Ingress on your cluster. We tested it out by configuring basic Routes to a sample application.

With APISIX gateway and the Ingress controller, you can also configure Upstreams, Plugins, mTLS, and monitoring. To learn more about APISIX and how you can use these features, visit apisix.apache.org.

See the complete list of articles in the series “Hands-On With Apache APISIX Ingress”.