A Beginner’s Guide to Writing a Kong API Gateway Plugin Using Go
In this tutorial, we will explore how to create a custom Kong API Gateway plugin using Go, build it, and run it with Kong using Docker Compose. Kong is a popular open-source API Gateway that helps manage and secure APIs, and it provides a flexible platform for extending its functionality through custom plugins. We’ll take you through each step, from setting up the environment to building and running the plugin. Let’s dive in!
Prerequisites
Before we begin, ensure you have the following:
- Docker and Docker Compose installed on your machine
- Go (version 1.18 or later) installed
- Basic knowledge of Go and Docker
If you meet the prerequisites, you’re ready to start.
Step 1: Set Up Your Go Project
Start by creating a new directory for your plugin and initializing a Go module.
mkdir hello-plugin
cd hello-plugin
go mod init hello-plugin
Step 2: Write the Plugin Code
Next, create a file named handler.go
inside your hello-plugin
directory with the following content:
package handlers
import (
"github.com/Kong/go-pdk"
"log"
)
type Config struct {
Message string
}
type Handler struct{}
func New() interface{} {
return &Handler{}
}
func (h *Handler) Access(kong *pdk.PDK) {
err := kong.Log.Info("Access handler invoked......")
if err != nil {
kong.Log.Err("Failed to log: %v", err)
return
}
// Add your custom logic here
err = kong.Response.SetHeader("X-Custom-Header", "CustomValue")
if err != nil {
kong.Log.Err("Failed to set header: %v", err)
return
}
kong.Log.Info("Access handler completed......")
}
This is a simple plugin that logs a message and sets a custom header for the response.
Step 3: Create the go.mod
File
Ensure your go.mod
file includes the necessary dependencies. Here’s a simple example:
module hello-plugin
go 1.18
require github.com/Kong/go-pdk v0.8.0
Step 4: Create the Dockerfile
We need a Dockerfile to containerize the plugin and set it up with Kong. Create a Dockerfile
in the root of your project:
FROM golang:1.20.0-alpine3.16 AS builder
WORKDIR /tmp/go-plugins
COPY ./plugins /tmp/go-plugins
RUN cd /tmp/go-plugins/hello-plugin && go build -o hello-plugin .
FROM kong:2.8.1-alpine
USER root
RUN apk update && apk add gettext
WORKDIR /kong
RUN mkdir go-plugins/
COPY --from=builder /tmp/go-plugins/hello-plugin/hello-plugin /kong/go-plugins/
COPY kong.conf kong.conf ./
RUN touch kong.yaml
RUN chown -R kong:kong kong.yaml
COPY kong-tmpl.yaml .
CMD envsubst < kong-tmpl.yaml > kong.yaml && /docker-entrypoint.sh kong docker-start -c kong.conf
This Dockerfile sets up the Go plugin and integrates it into the Kong container.
Step 5: Create the Docker Compose File
To make running the environment easier, we will use Docker Compose. Create a docker-compose.yaml
file:
networks:
kong-net:
driver: bridge
services:
kong-database:
image: postgres:13
networks:
- kong-net
ports:
- "5432:5432"
environment:
POSTGRES_USER: kong
POSTGRES_DB: kong
POSTGRES_PASSWORD: kongpass
volumes:
- ~/postgres-data:/var/lib/postgresql/data
kong:
build:
context: .
container_name: kong
restart: unless-stopped
networks:
- kong-net
ports:
- "8000:8000"
- "8001:8001"
- "8443:8443"
- "8444:8444"
environment:
KONG_DATABASE: "postgres"
KONG_PG_HOST: kong-database
KONG_PG_USER: kong
KONG_PG_PASSWORD: kongpass
KONG_PG_DATABASE: kong
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: 0.0.0.0:8001
KONG_LOG_LEVEL: debug
depends_on:
- kong-database
volumes:
- ./plugins/hello-plugin/configs/config.json:/kong/configs/config.json
konga:
image: pantsel/konga:latest
networks:
- kong-net
ports:
- "1337:1337"
environment:
NODE_ENV: production
depends_on:
- kong
This Compose file sets up Kong, a Postgres database for Kong’s storage, and Konga for the Kong dashboard.
Step 6: Create the Start Script
To automate the process of starting the services, create a start.sh
script:
#!/bin/bash
# Start the database container
docker compose up -d kong-database
# Wait for the database to be ready
echo "Waiting for the database to be ready..."
sleep 10
# Run the migrations bootstrap command
docker compose run --rm kong kong migrations bootstrap
# Start the Kong container
docker compose up -d kong
# Start the Konga container
docker compose up -d konga
echo "Kong has been started successfully."
This script starts the Kong and Konga services after setting up the database.
Step 7: Build and Run the Plugin
Now, it’s time to build and run your plugin with Docker Compose. Run the following commands:
chmod +x start.sh
./start.sh
Once the services are up and running, your Kong API plugin written in Go should be live. You can access Kong at http://localhost:8000
and Konga Dashboard at http://localhost:1337
.
Adding a Plugin to a Service in Kong (UI Method)
In addition to applying a plugin using the Kong Admin API, you can also add a plugin to a service via the Kong UI (Konga). Konga is a user-friendly web interface that allows you to manage Kong, services, and plugins without writing commands. Here’s how you can add your custom plugin to a service using the UI:
Step 1: Access Konga UI
First, ensure that the Konga container is running. If you followed the setup instructions in the previous tutorial, Konga should be accessible at http://localhost:1337
. Open your web browser and navigate to this address.
Step 2: Log into Konga
Once you’re at the Konga dashboard, log in using the appropriate credentials. If this is your first time setting it up, you may need to create an admin account to access the dashboard.
Step 3: Navigate to Services
In the Konga dashboard, locate the Services section on the left-hand sidebar. Here, you’ll see a list of all services that Kong is currently managing.
Step 4: Select the Service
Click on the service to which you want to apply the plugin (for example, the hello-service
you created earlier). This will open the service details page.
Step 5: Add the Plugin
Once you’re on the service details page, scroll down to the Plugins section. There should be an option to Add Plugin. Click on this button to open a form where you can select the plugin you want to apply.
- In the Plugin dropdown, select your custom plugin (in this case,
hello-plugin
). - After selecting the plugin, you may be able to configure additional plugin settings if necessary, depending on your plugin’s design.
Step 6: Save the Plugin
Click the Save or Add button to apply the plugin to the service. The plugin will now be active for that service.
Step 7: Verify the Plugin Is Applied
After adding the plugin, you can verify it by navigating back to the service details page. The plugin should now appear in the list of applied plugins for that service. You can also test the service as mentioned in the previous section by sending a request to the service’s route and checking for the custom header added by your plugin.
Why Choose Go Over Lua for Kong API Plugins?
While Kong traditionally uses Lua for plugin development, Go offers several advantages:
- Performance: Go is a statically typed, compiled language, which means it generally performs better than Lua, especially for resource-intensive operations.
- Concurrency: Go has native support for concurrency with Goroutines, making it easier to handle multiple API requests simultaneously.
- Robust Ecosystem: Go has a rich ecosystem with libraries that can simplify integration and scaling.
- Familiarity: If you’re already familiar with Go, it makes sense to use it for your Kong plugins, as opposed to learning Lua from scratch.
- Maintainability: Go’s static typing, clearer syntax, and better error handling make it easier to maintain large codebases compared to Lua.
Conclusion
By following this tutorial, you’ve learned how to create and run a Kong API plugin using Go and Docker. With Go, you get better performance, concurrency handling, and ease of integration, making it a strong choice over Lua. The Docker Compose setup makes the process easy, enabling you to focus on writing your plugin instead of worrying about environment setup.
Kong’s API Gateway is a powerful tool for managing APIs, and with the ability to extend its functionality through plugins, you can easily adapt it to your needs. Happy coding!
GitHub Repo Link: https://github.com/chamodshehanka/kong-go-plugin