Kong es el api gateway con más estrellas del CNCF en este momento. Kong tiene mucha funcionalidad, pero me voy a centrar solo en su estupenda integración con Kubernetes. ¿Te imaginas poder definir en tu helm chart que tal aplicación solo pueda recibir un número de peticiones por minuto desde una IP? Aviso a navegantes: en este post no trato cosas básicas. Si no tienes unos conocimientos mínimos de lo que es un api gateway o kubernetes (ingress, services, controllers, crds, ...) podrás seguir este post, pero probablemente no sepas muy bien que estás haciendo. |
Instalando kubernetes
Me hubiera gustado usar microk8s pero no me vale por el plugin de red que utiliza así que vamos a usar k3s.
Lo instalamos sin traefik, que es el ingress controller que viene con k3s (hay vida más allá de nginx ;-) ):
sudo su - curl -sfL https://get.k3s.io/ | sh -s - --disable=traefik mkdir .kube cat /etc/rancher/k3s/k3s.yaml > .kube/config
NOTA: para desinstalarlo en cualquier momento puedes ejecutar
k3s-uninstall.sh
.
Recuerda que no debes tener cosas escuchando en los puertos 80 y el 443 de tu pc.
Instalando Kong
Ahora vamos a instalar el ingress de kong:
helm repo add kong https://charts.konghq.com helm repo update helm upgrade --install kong \ --set ingressController.installCRDs=false \ kong/kong
Cuenta hasta 100, te conectas a localhost y verás esta pantalla:
.
Instalando una aplicación
Vamos a instalar Wordpress, para variar:
helm repo add bitnami https://charts.bitnami.com/bitnami helm upgrade --install wordpress \ --set wordpressUsername=admin \ --set wordpressPassword=admin \ --set service.type=ClusterIP \ --set ingress.enabled=true \ --set ingress.hostname=localhost \ bitnami/wordpress
Contamos hasta 100 y ...:
¿Ves la magia? No la ves, sino no sería magia, pero sin saber nada de Kong ya estás usando Kong y mágicamente se ha ejecutado este procedimiento.
Plugins
Los plugins se pueden utilizar para casi cualquier cosa que imagines, desde poner una contraseña a una url a modificar las cabeceras de las peticiones. Además, si quieres, te puedes programar tus propios plugins en lua.
Vamos a usar el plugin rate limiting para que solo se admitan 20 peticiones cada minuto.
Aplica este manifiesto:
echo """ apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: rate-limiting-example config: minute: 20 policy: local plugin: rate-limiting """ | kubectl apply -f -
Reconfigura wordpress para usarlo agregando --set ingress.annotations."plugins\.konghq\.com"=rate-limiting-example
tal que así:
helm upgrade --install wordpress \ --set wordpressUsername=admin \ --set wordpressPassword=admin \ --set service.type=ClusterIP \ --set ingress.enabled=true \ --set ingress.hostname=localhost \ --set ingress.annotations."plugins\.konghq\.com"=rate-limiting-example \ bitnami/wordpress
Ahora dale al F5 muchas veces y verás el resultado:
¡Magia!
Derivadas
Esta integración con Kubernetes tiene una serie de derivadas muy interesantes en las que seguro ya estás pensando.
Gitops
Si usas una aproximación gitops para el despliegue de tus aplicaciones en Kubernetes (con Terraform, Flux, o lo que sea), puedes tratar la configuración de Kong junto al resto de configuraciones de la aplicación.
Transferencia de responsabilidades
Los equipos son los que mejor conocen (o deberían conocer) las necesidades y capacidades de sus servicios así que si tienen acceso a su namespace de Kubernetes pueden gestionar los plugins de Kong que necesiten.
No seamos inocentes ... probablemente ya lo hagan pero construyendo y manteniendo sus microservicios en diversos lenguajes dependiendo del equipo, lo que va en contra de cualquier criterio de normalización en una compañía.
Pipelines más sencillas
Si prefieres no usar gitops (¿porqué?) cambiamos llamadas al api por un "kubectl apply" en los pasos de las pipelines.
Integración en helm charts
Imagina que tienes un helm chart con el que despliegas los microservicios de tu equipo.
Ahora imagina que agregas en el values.yaml
algo así:
ingress: ## Configure kong plugins ## #plugins: # - name: rate-limiting # config: # minute: 10 # limit_by: consumer # policy: local plugins: []
Y que agregas una plantilla tal que así:
{{- range .Values.ingress.plugins }} --- apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: {{ .name }} config: {{ toYaml .config | nindent 2 }} plugin: {{ .name }} {{- end }}
Y ya puestos, las anotaciones en el ingress de esta forma:
apiVersion: extensions/v1beta1 kind: Ingress metadata: ... annotations: ... konghq.com/plugins: "{{- range .Values.ingress.plugins }}{{ .name }},{{- end }}"
¡Ya tienes Kong integrado en tus Helm Charts!
Base de datos
Si haces un kubectl get po verás con asombro que ¡no hay base de datos! así que ¿donde se guarda la configuración de Kong? La configuración se guarda en el etcd de Kubernetes así que no necesitas gestionar volúmenes persistentes ni bases de datos.
Por desgracia no todos los plugins son compatibles con este tipo de despliegue así que en muchas ocasiones no te quedará más remedio que usar una base de datos adicional.
En caso de usar un despliegue con base de datos podrás seguir usando CRDs tal como he descrito arriba peeeeeeero, si alguien toca a mano algo en la base de datos que entre en conflicto con los CRDs, gana lo que haya en la base de datos.
Arquitectura
Me he centrado en esta arquitectura porque es la que me conviene para mostrar lo que quiero, pero podemos mantener el ingress/rutas de tu Kubernetes/OpenShift y usar Kong de esta forma pasándole un subdominio para que lo gestione, o bien podemos no usar la integración con Kubernetes y tener un kong por namespace.
O a lo mejor te interesa tener un Kong central para temas de autenticación con base de datos y luego un kong dbless por cluster de Kubernetes para que los equipos gestionen sus cosas de forma autónoma.
En este post no me meto en ese tipo de decisiones de arquitectura pero a lo mejor esta información de despliegue junto a la política de tu empresa pueda ayudarte a tomar la mejor decisión.
Konga
Si eres más de interfaces gráficas y no te quieres gastar dinero en la versión Enterprise, puedes usar konga.