Kong Gateway es un API Manager construido sobre NGINX y escrito en Lua, disponible en versión Community (gratuita) y versión Enterprise (de pago y más completa), extensible mediante Plugins (algunos sólo disponibles en la versión Enterprise) que pueden activarse en diferentes scopes (Global, Route, Service, Consumer). Kong puede ejecutarse fácilmente de forma dockerizada (ej: Docker, Docker Compose, Kubernetes, etc.) usando PostgreSQL o Cassandra como base de datos (e incluso DB-Less mediante configuración declarativa), y es escalable horizontalmente (Clustering).
Kong es una de las principales opciones de API Manager, Open Source y disponible en una versión Community gratuita, un producto bastante chulo. En este Post vamos a hacer una introducción a Kong y a Konga (un Dashboard que sirve como herramienta gráfica de administración), así como veremos de forma práctica como hacer algunas configuraciones básicas, como la publicación de servicios a través de Kong (muy sencillito, básicamente la función de un Proxy Inverso).
Dicho esto, comenzamos una nueva serie de Posts acerca de Kong, que espero que sirva e interese a más de uno.
Introducción a los API Manager
Los API Manager son una pieza cada vez más importante para compartir datos con clientes y proveedores mediante APIs, y para ayudar a gestionar de forma centralizada sobre nuestras APIs, ciertas funcionalidades como las siguientes:
- Forzar ciertas políticas (ej: max request size).
- Control de acceso y tráfico (ej: API Keys, autenticación básica, rate limit, whitelisting, etc.)
- Tranformaciones de Requests y Responses.
- Registro, colecta, y análisis de estadísticas de uso.
- Informes de Rendimiento.
- API Gateway: punto único de publicación de APIs a consumidores.
Pero el punto no es sólo poder gestionar este tipo de cosas de forma centralizada (que mola), sino que además, no tienes que preocuparte de implementar esa lógica en cada una de tus APIs, de eso ya se encarga el API Manager, tu sólo preocúpate de implementar la lógica de negocio.
Tenemos muchas soluciones de API Manager donde escoger, algunas dentro del offering de servicios PaaS que nos ofrecen los principales proveedores de Cloud (ej: Google Apigee, Azure API Management), otras son soluciones ofrecidas también como servicio (ej: MuleSoft, Kong, tyk.io), y también soluciones que podemos instalar nosotros en OnPrem o IaaS (ej: Kong, WSO2 API Manager, tyk.io, KrakenD, etc), y muchas más (ej: IBM API Connect, axway, Mashery, 3scale, etc).
En nuestro caso, vamos a hablar de Kong, que puede utilizarse de forma gratuita (ej: ideal para pequeños proyectos) y tiene también disponible una versión Enterprise de pago (más completa y avanzada).
Introducción a Kong Community y Konga
Las principales diferencias entre Kong Community (Open Source) y Kong Enterprise, son básicamente las siguientes:
- La versión Community no incluye una GUI, siendo necesario configurarlo mediante llamadas a la Kong API Admin, mientras que la versión Enterprise incluye un Web Dashboard donde podemos configurar Kong de forma gráfica y sencilla. Sin embargo, existen soluciones Open Source de la Comunidad como Konga, que se trata de un Dashboard con el que podemos administrar Kong Community de forma sencilla.
- La versión Enterprise incluye funcionalidad adicional (ej: Workspaces), además del Dashboard, así como determinados Plugins que sólo están disponibles para Enterprise, mientras que Kong Community sólo incluye los Plugins más básicos (por ejemplo, no podemos integrarnos con un IdP externo en la versión Community).
- La versión Enterprise incluye Vitals, que proporciona métricas y gráficos de la salud, rendimiento, y uso de Kong. En la versión Community podemos utilizar Prometheus y Grafama para la monitorización de Kong.
- La versión Community no incluye el Developer Portal.
Podríamos ver a Kong como un NGINX super-vitaminado que incluye una API de administración junto con un montón de Plugins que facilitarnos la vida, con una versión de pago con funcionalidad adicional y un servicio de soporte.
Para más información, podemos consultar la documentación del producto (Kong Docs – Kong Gateway) así como su repo de GitHub (GitHub – Kong).
La versión de pago de Kong actualmente está reconocido por Gartner como uno de los líderes en Full Life Cycle API Management: Kong Named Leader in Gartner® Magic Quadrant™ for Full Life Cycle API Management for Third Year
Kong por defecto utiliza los puertos tcp-8000 y tcp-8443 para recibir las peticiones HTTP y HTTPS de los consumidores (pueden cambiarse por otros puertos), y del mismo modo, utiliza los puertos tcp-8001 y tcp-8444 para la Kong API Admin (por defecto sólo escucha en localhost, y como buena práctica, es recomendable exponerlo de forma limitada y a poder ser bajo otro número de puerto) que podemos utilizar para configurar Kong, a golpe de curl, Postman, o como deseemos.
Para más info acerca de la API de Kong, podemos consultar la documentación del producto: Kong Docs – Admin API
Konga proporciona un Dashboard que nos permitirá ver y modificar la configuración de Kong de una forma sencilla, muy útil como herramienta de administración de Kong si utilizamos Kong Community. Konga no incluye toda la funcionalidad que ofrece la Kong API Admin, pero permite muchas cosas. Konga necesita una base de datos para almacenar su configuración, pudiendo utilizar la misma de Kong (es decir, otra base de datos dentro de la misma instancia de PostgreSQL usada por Kong), o si lo deseamos, también podemos usar una base de datos totalmente distinta (ej: PostgreSQL, SQL Server, MySQL, o MongoDB). Algunos tips, antes de que pasemos a verlo en acción un poco más adelante:
- Konga ofrece dos tipos de usuarios, Admin (full-access) y non-Admin (por defecto con permisos de sólo lectura, que podemos cambiar, pero no permite hacer un perfilado mucho más fino).
- Con una única instancia de Konga, podemos administrar varias instalaciones de Kong (podemos definir las conexiones a cada Kong, y activar en cada momento la que deseemos para trabajar).
- Konga permite hacer Snapshots (manualmente o planificados mediante una expresión cron), es decir, un Backup de Kong que podemos restaurar en caso necesario, incluso podríamos exportarlo a un JSON en disco para importarlo más adelante en la misma o incluso sobre otra instancia de Kong.
Konga utiliza por defecto el puerto tcp-1337 para publicar el Dashboard de administración de Kong.
La última versión de Konga es la 0.14.9, de Mayo del 2020 (se puede comprobar fácilmente en Docker Hub y en GitHub), y desde entonces hasta ahora no ha habido actualizaciones. Este es quizás el principal inconveniente de Konga, que actualmente no tiene mantenimiento, aunque en cualquier caso podemos seguir usando la API Admin de Kong para lo que necesitemos.
Para más info acerca de Konga, podemos consultar la Web de Konga, el Docker Hub de Konga, o bien el repo de GitHub de Konga.
Ejecutando Kong y Konga con Docker Compose
Quizás la forma más sencilla de utilizar Kong, es con Docker Compose, que es como lo vamos a describir en este Post, para conseguir tener un entorno de Laboratorio de forma rápida y sencilla donde hacer pruebas, sin miedo a romper nada (también está disponible el Kong Ingress Controller para Kubernetes).
Para ello vamos a utilizar un fichero Docker Compose bastante completo, que define lo siguiente, y que podéis encontrar en GitHub – ElWillieES – kong-docker-lab. Si quieres seguir paso a paso este Post (así como el resto de Post sobre Kong), puedes descargarte este Docker Compose, arrancarlo, y hacer los laboratorios tu mismo siguiendo los pasos que te iré describiendo más abajo en este Post, así como en el resto de Post de Kong.
- Una red Docker de tipo Bridge (docker-net), con direccionamiento de red 172.1.1.0/24, que nos va a permitir poder asignar direcciones IP fijas a los diferentes contenedores, simular bloqueos por IP, etc.
- Un contendor con PosgreSQL 11 (postgres) y dirección IP fija (172.1.1.10). Especificamos como variables de entorno el usuario y contraseña de superadmin (postgres/password), y además:
- Montamos como volumen un Script SQL de inicialización (create_kong_db.sql) sobre la ruta /docker-entrypoint-initdb.d para que se ejecuten la primera vez que arranquemos Postgres, y realicen las tareas necesarias de inicialización (ej: crear la base de datos de Kong). Para más info: PostgreSQL – Initialization Scripts
- Montamos un volumen para los datos de Postgres (/var/lib/posgresql/data), y así tener persistencia.
- Un contenedor para la preparación de la base de datos de Kong (kong-prepare). Utilizaremos la versión 2.8.3 de Kong (también probamos la 2.1.4). Especificamos como variables de entorno los datos de conexión a PostgreSQL, y depende del contenedor de PosgreSQL (postgres). Realmente es útil sólo la primera vez que se ejecuta.
- Un contenedor para Kong (kong) y dirección IP fija (172.1.1.11). Utilizaremos la misma versión que en kong-prepare (versión 2.8.3 de Kong). Especificamos como variables de entorno los datos de conexión a la base de datos Postgres y alguna configuración más, y mapeamos los puertos para que sean accesibles desde el exterior. Depende del contenedor kong-prepare, necesario para que prepare la base de datos para que pueda arrancar Kong correctamente.
- Un contenedor para la preparación de la base de datos de Konga (konga-prepare). Depende del contenedor de PosgreSQL (postgres), e incluye el comando a ejecutar con los datos necesarios (en este caso, no se apoya en variables de entorno). Realmente es útil sólo la primera vez que se ejecuta.
- Un contenedor para Konga (konga) y dirección IP fija (172.1.1.12). Utilizaremos la última versión de Konga (0.14.9), especificamos como variables de entorno los datos de conexión a la base de datos Postgres y alguna configuración más (ej: un token, y el modo de desarrollo), y mapeamos el puerto que utiliza (tcp-1337) para que sea accesible desde el exterior. Depende del contenedor kong-prepare, necesario para que prepare la base de datos para que pueda arrancar Konga correctamente.
- Varios contenedores con NGINX (service_a, service_b_1, service_b_2, service_b_3, service_c) y dirección IP fija. Su única función es simular ser tres micro-servicios con los que podamos hacer pruebas, uno de los cuales está en tres contenedores para poder hacer pruebas de balanceo. Al acceder muestra el nombre del servicio y otros datos, además de un timestamp, para ayudar a comprobar el resultado de las pruebas que hagamos. Mapeamos los puertos que utilizan para que sean accesibles desde el exterior, y montamos como volumen el fichero de configuración de NGINX.
- Un contenedor para Redis (redis) y dirección IP fija (172.1.1.20). Lo podemos utilizarlo para pruebas con el Plugin de Rate Limiting, por ejemplo.
- Un contenedor para Prometheus (prometheus) y dirección IP fija (172.1.1.21). Lo utilizaremos para pruebas de monitorización.
- Montaremos como volumen el fichero de configuración de Prometheus (prometheus.yml).
- Montamos un volumen para los datos de Prometheus (/prometheus), y así tener persistencia.
- Un contenedor para el Node Exporter de Prometheus (node-exporter) y dirección IP fija (172.1.1.22). Para pruebas de monitorización.
- Un contenedor para Grafana (grafana) y dirección IP fija (172.1.1.23). Nos permitirá tener Dashboards (los hagamos nosotros mismos o los descarguemos de grafana.com), y explorar datos de los Logs, pudien conectarnos a Prometheus y Elasticsearch.
- Montamos un volumen para los datos de Grafana (/var/lib/grafana), y así tener persistencia.
- Un contenedor para Elasticsearch (elasticsearch) y dirección IP fija (172.1.1.24). Nos permitirá importar los Logs de Kong, para explorarlos y realizar Dashboard con Grafana.
- Montamos un volumen para los datos de Elasticsearch (/usr/share/elasticsearch/data), y así tener persistencia.
- Un contenedor para Kibana (kibana) y dirección IP fija (172.1.1.26). Nos permitirá hacer Dashboards y explorar los datos que tenemos en Elasticsearch.
- Montamos un volumen para los datos de Kibana (/usr/share/kibana/data), y así tener persistencia.
- Un contenedor para ElasticHQ (elastichq) y dirección IP fija (172.1.1.27). Nos permitirá administrar Elasticsearch de forma gráfica, más rápido y sencillo que directamente atacando a la API.
- Tres contenedores para Logstach (logstash, logstash-tcp, logstash-http) y dirección IP fija (172.1.1.25, 172.1.1.28, 172.1.1.29). Montarán como volumen el fichero de configuración de las Pipelines, para cargar los Logs de peticiones y respuestas de Kong a través de los Plugins UDP Log, TCP Log, y HTTP Log respectivamente.
Aunque este Docker Compose arranca varios NGINX que podemos utilizar para simular micro-servicios en nuestras pruebas, si lo deseamos también podemos utilizar Mockbin, un servicio gratuito que permite mockear endpoints HTTP, que también nos puede resultar de utilidad para hacer nuestras pruebas de laboratorio, y publicar a través de Kong lo servicios fake de Mockbin a modo de laboratorio.
Descargaremos el repo (git clone) de GitHub, y ejecutaremos los siguientes comandos, para arrancar los contendores del Docker Compose, y comprobar su estado (en este ejemplo, estamos utilizand un portátil con Windows 11 y Docker Desktop).
docker-compose up -d
docker-compose ps
A continuación se muestra una pantalla capturada de la salida de ejecución de ambos comandos.
En caso necesario, podemos comprobar los Logs de Docker Compose así como parar (sin eliminarlos) y volver a arrancar todos los contenedores Docker con los siguientes comandos respectivamente:
docker-compose logs
docker-compose stop
docker-compose start
Si deseamos parar y/o arrancar un único contenedor (ej: service_a), podemos utilizar comandos como los siguientes:
docker-compose stop service_a
docker-compose start service_a
También podemos parar y eliminar todos los contenedores con el siguiente comando:
docker-compose down
Explicados estos comandos Docker Compose, continuamos con el arranque de nuestro pequeño laboratorio de Kong. Para ellos, podemos comprobar el acceso a las siguientes URLs (todas deben de responder):
- Kong: http://localhost:8000
- Kong API Admin: http://localhost:8001
- Konga: http://localhost:1337
- Service A: http://localhost:9001
- Service B (Instancia 1): http://localhost:9002
- Service B (Instancia 2): http://localhost:9003
- Service B (Instancia 3): http://localhost:9004
- Service C: http://localhost:9005
La primera vez que accedamos a Konga, deberemos crear la primera cuenta de un usuario Admin, tras lo cual nos pedirá que iniciemos sesión con el usuario que acabamos de crear.
La primera vez que iniciamos sesión con el usuario admin que acabamos de crear, deberemos configurar la conexión al servidor Kong que deseamos administrar desde Konga. La forma más sencilla (y menos segura, pero sufiente para entornos de Laboratorio como el nuestro), es especificando un nombre para la conexión y la URL de la Kong API Admin (es decir, sin seguridad por API Key, JWT, ó Basic Auth).
Hecho esto, ya tendremos Konga configurado para administrar nuestro primer Kong Gateway. Aunque en el siguiente pantallazo se muestra la versión 2.1.4 de Kong, finalmente lo dejé con la versión 2.8.3 de Kong, que es la más reciente de las 2.X.X (recordemos que hasta ahora Konga no ha sacado más versiones desde hace tres años).
Publicar nuestro primer Service en Kong utilizando Konga
Lo siguiente que deberemos hacer en crear un Service con al menos una Route.
Un Service en Kong es una abstracción de un servicio (es decir, una API o un endpoint) que deseamos disponibilizar a través de Kong, caracterizable principalmente por su URL, que deberemos configurar en Kong. Asociado a un Service, deberemos de configurar una o varias Routes, que son los puntos de entrada que hacen alcanzable dicho Service desde el exterior, pudiendo incluir detalles adicionales como los verbos HTTP disponibles, etc.
Vamos a verlo con un ejemplo utilizando Konga para configurarlo (más visual, aunque se puede hacer también a golpe de curl o de Postman, que tampoco es nada complicado, lo veremos también).
Para añadir un nuevo Service, accederemos a la opción Services, y click en Add new Service.
Se mostrará un formulario donde indicaremos el nombre que le deseemos dar al Servicio así como la URL en la que está disponible, y haremos click en el botón Submit Service.
Una vez creado el Servicio, aparecerá en la lista de Servicios disponibles. Haremos click sobre el, para ver sus detalles.
En la página de detalles del Servicio, haremos click en Routes, para poder crear una Route que permita acceder al Servicio que acabamos de crear.
Una vez en la página de Routes del Servicio que acabamos de crear, haremos click en Add Route, para crear una nueva Route que de acceso a nuestro Servicio.
En la página para añadir una nueva Route para nuestro Servicio, añadiremos un nombre y la ruta que deseamos utilizar, y click en Submit Route.
Una vez creada nuestra Route para poder acceder a nuestro Servicio, podemos ver sus detalles desde Konga, pudiendo editarla y eliminarla.
Hecho esto, ya sólo nos queda probarlo. Para ello, accederemos a la URL de Kong, a la ruta que acabamos de crear para acceder al Service A, y podremos ver que todo funciona cómo deseábamos. Fácil y sencillo.
Ahora vamos a añadir otro Service con su propia Route. En esta ocasión, en lugar de hacerlo con Konga, vamos a hacerlo a golpe de curl. Sería tan sencillo como ejecutar los siguientes dos comandos:
curl --location --request POST 'http://localhost:8001/services' \
--header 'Content-Type: application/json' \
--data-raw '{
"url" : "http://service_c:9005",
"name" : "service-c",
"retries" : 5,
"connect_timeout" : 60000,
"write_timeout" : 60000,
"read_timeout" : 60000
}'
curl --location --request POST 'http://localhost:8001/services/service-c/routes' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "service-c",
"protocols": [
"http",
"https"
],
"paths": [
"/service-c"
],
"methods": []
}'
A continuación podemos ver la salida de ejecución de los dos anteriores comandos curl.
Configurar Upstreams en Kong: Health Check + Load Balancing
Kong permite la configuración de Upstreams, que consiste en un nombre de host virtual al que podemos asociar uno o varios destinos (Targets) sobre los que Kong podrá comprobar su salud o disponibilidad, así como repartir la carga (peticiones) entre aquellos que estén disponibles, en base al peso que le asignemos a cada Target.
Veamos como crear un Upstream en Kong utilizando Konga. Para ello haremos click en Create upstream en la sección de Upstreams.
Especificaremos un nombre, y click en Submit upstream. Si lo deseamos, además podemos configurar Health Checks pasivos y/o activos.
Con esto, ya lo habremos creado, pero no hemos acabado aún. Click en Details para continuar.
Seguidamente, click en Targets para continuar.
En la siguiente pantalla podemos ver los destinos (Targets) existens así como añadir uno nuevo. En nuestro caso, click en Add target, para añadir uno nuevo.
En la siguiente pantalla especificaremos el destino y el peso que le queramos añadir. En nuesto caso lo repetiremos posteriormente para crear un total de tres Targets, con las siguientes direcciones:
- 172.1.1.15:9002
- 172.1.1.16:9003
- 172.1.1.17:9004
Finalmente quedarán configurados los Targets como se muestra en la siguiente pantalla:
Una vez creado el Upstream, crearemos un nuevo Service, especificando como Host el nombre del Upstream que acabamos de crear (en esta ocasión estamos utilizando el campo Host, en lugar del campo URL). Además Konga nos obligará a especificar un puerto (pondremos el 9002, aunque realmente va a utilizar el puerto configurado en cada Target). Click en Submit service para continuar.
Una vez creado el Service asociado al Upstream, crearemo un Route basado en un Path, que será el punto de entrada a nuestro Servicio.
Y listo. Con esto ya habremos creado un Service con una Route, que tiene un Upstream asociado con tres Targets sobre los que repartirá las peticiones entrantes. Para probarlo, basta con acceder a la URL del Servicio repetidas veces, y veremos como cada vez respone un Target distinto. Fácil y sencillo.
Despedida y Cierre
Hasta aquí llega este primer Post sobre Kong y Konga, donde hemos realizado una introducción a estos interesantes productos, una buena alternativa como APIM para muchos proyectos, así como hemos realizado las primeras configuraciones en Kong, y compartido un repo de GitHub con un Docker Compose para que podáis hacer pruebas de forma rápida y sencilla (GitHub – ElWillieES – kong-docker-lab).
Poco más por hoy, como siempre confío que la lectura resulte de interés.