Skip to content

Commit

Permalink
docs: add tutorial on using custom Plugins (#1745)
Browse files Browse the repository at this point in the history
Signed-off-by: Navendu Pottekkat <navendu@apache.org>
  • Loading branch information
pottekkat authored Mar 26, 2023
1 parent c5b2ae8 commit 0ad8eaa
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/en/latest/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"tutorials/manage-ingress-certificates-with-cert-manager",
"tutorials/enable-authentication-and-restriction",
"tutorials/how-to-access-Apache-APISIX-Prometheus-Metrics-on-k8s",
"tutorials/using-custom-plugins",
"tutorials/how-to-use-go-plugin-runner-in-apisix-ingress",
"tutorials/external-service",
"tutorials/external-service-discovery"
Expand Down
223 changes: 223 additions & 0 deletions docs/en/latest/tutorials/using-custom-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
---
title: Using custom Plugins in APISIX Ingress
keywords:
- APISIX ingress
- Apache APISIX
- Custom Plugins
- Lua Plugins
description: A tutorial on how you can configure custom Plugins in APISIX Ingress.
---

<head>
<link rel="canonical" href="https://navendu.me/posts/custom-plugins-in-apisix-ingress/" />
</head>

This tutorial explains how you can configure custom Plugins to work with APISIX Ingress.

## Prerequisites

Before you move on, make sure you:

1. Have access to a Kubernetes cluster. This tutorial uses [minikube](https://github.com/kubernetes/minikube).
2. [Install Helm](https://helm.sh/docs/intro/install/) to deploy the APISIX Ingress controller.

## Deploy httpbin

We will deploy a sample service, [kennethreitz/httpbin](https://hub.docker.com/r/kennethreitz/httpbin/), for this tutorial.

You can deploy it to your Kubernetes cluster by running:

```shell
kubectl run httpbin --image kennethreitz/httpbin --port 80
kubectl expose pod httpbin --port 80
```

## Writing a Custom Plugin

In this tutorial we will focus only on configuring custom Plugins to work with APISIX Ingress.

:::tip

To learn more about how to write custom Plugins, see the [documentation](https://apisix.apache.org/docs/apisix/plugin-develop/). You can also write [external Plugins](https://apisix.apache.org/docs/apisix/external-plugin/) in programming languages like Java, Python, and Go.

:::

In this tutorial, we will use a [sample Plugin](https://raw.githubusercontent.com/navendu-pottekkat/apisix-in-kubernetes/master/custom-plugin/plugins/custom-response.lua) that rewrites the response body from the Upstream with a custom value:

```lua {title="custom-response.lua"}
-- some required functionalities are provided by apisix.core
local core = require("apisix.core")

-- define the schema for the Plugin
local schema = {
type = "object",
properties = {
body = {
description = "custom response to replace the Upstream response with.",
type = "string"
},
},
required = {"body"},
}

local plugin_name = "custom-response"

-- custom Plugins usually have priority between 1 and 99
-- higher number = higher priority
local _M = {
version = 0.1,
priority = 23,
name = plugin_name,
schema = schema,
}

-- verify the specification
function _M.check_schema(conf)
return core.schema.check(schema, conf)
end

-- run the Plugin in the access phase of the OpenResty lifecycle
function _M.access(conf, ctx)
return 200, conf.body
end

return _M
```

Now we can set up APISIX to utilize this Plugin and enable it for specific Routes.

While one approach is to create a customized build of APISIX that includes the Plugin's code, this is not a simple task.

An alternative method involves generating a [ConfigMap](https://kubernetes.io/docs/concepts/configuration/configmap/) from the Lua code and then mounting it onto the APISIX instance within the Kubernetes environment.

To create the ConfigMap, you can execute the following command:

```shell
kubectl create ns ingress-apisix
kubectl create configmap custom-response-config --from-file=./apisix/plugins/custom-response.lua -n ingress-apisix
```

Now we can deploy APISIX and mount this ConfigMap.

## Deploying APISIX

We will use Helm to deploy APISIX and APISIX Ingress controller.

First, we will update the `values.yaml` file to mount the custom Plugin we created before.

You can configure the Plugin under `customPlugins` as shown below:

```yaml {title="values.yaml"}
customPlugins:
enabled: true
plugins:
- name: "custom-response"
attrs: {}
configMap:
name: "custom-response-config"
mounts:
- key: "custom-response.lua"
path: "/usr/local/apisix/apisix/plugins/custom-response.lua"
```
You should also enable the Plugin by adding it to the `plugins` list:

```yaml {title="values.yaml"}
plugins:
- api-breaker
- authz-keycloak
- basic-auth
- batch-requests
- consumer-restriction
- cors
...
...
- custom-response
```

Finally you can enable the Ingress controller and configure the gateway to be exposed to external traffic. For this, set `gateway.type=NodePort`, `ingress-controller.enabled=true`, and `ingress-controller.config.apisix.serviceNamespace=ingress-apisix` in your `values.yaml` file.

Now we can run `helm install` with this [updated values.yaml](https://raw.githubusercontent.com/navendu-pottekkat/apisix-in-kubernetes/master/custom-plugin/values.yaml) file:

```shell
helm install apisix apisix/apisix -n ingress-apisix --values ./apisix/values.yaml
```

APISIX and APISIX Ingress controller should be ready in some time with the custom Plugin mounted successfully.

## Testing without Enabling the Plugin

First, let's create a Route without our custom Plugin enabled.

We will create a Route using the [ApisixRoute](https://apisix.apache.org/docs/ingress-controller/concepts/apisix_route) CRD:

```yaml {title="route.yaml"}
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: api-route
spec:
http:
- name: route
match:
hosts:
- local.navendu.me
paths:
- /api
backends:
- serviceName: bare-minimum-api
servicePort: 8080
```

We can now test the created Route:

```shell
curl http://127.0.0.1:52876/api -H 'host:local.navendu.me'
```

This will give back the response from our Upstream service as expected:

```shell
Hello from API v1.0!
```

## Testing the Custom Plugin

Now let's update the Route and enable our custom Plugin on the Route:

```yaml {title="route.yaml"}
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
name: api-route
spec:
http:
- name: route
match:
hosts:
- local.navendu.me
paths:
- /api
backends:
- serviceName: bare-minimum-api
servicePort: 8080
plugins:
- name: custom-response
enable: true
config:
body: "Hello from your custom Plugin!"
```

Now, our custom Plugin should rewrite the Upstream response with "Hello from your custom Plugin!"

Let's apply this CRD and test the Route and see what happens:

```shell
curl http://127.0.0.1:52876/api -H 'host:local.navendu.me'
```

And as expected, we get the rewritten response from our custom Plugin:

```text {title="output"}
Hello from your custom Plugin!
```

0 comments on commit 0ad8eaa

Please sign in to comment.