Blog de Amazon Web Services (AWS)

Picturesocial – Cómo exponer API’s contenerizadas a Internet?

Por Jose Yapur – Sr. Developer Advocate, AWS

No todo se trata de crear y desplegar, una de las partes más importantes del camino es asegurar que nuestras API’s están disponibles para ser consumidas por los clientes, donde sea que estén. La forma en la que expones un API puede representar el éxito o fracaso de todo el proyecto. En este post vamos a aprender sobre Amazon API Gateway y cómo es que nos ayuda a asegurar nuestros backends y a consumirlos de forma segura.

Pero primero, vamos a recapitular nuestro avance hasta ahora con Picturesocial. Hemos creado, contenerizado y desplegado API’s y asegurado la infraestructura. Sin embargo, nuestros servicios son presentados con Internet Load Balancers, eso significa que cualquiera con la URL puede llamarlos sin ningún tipo de control. Hasta el momento no hemos implementado políticas de throttling, validación de api-key, autenticación o algún otro mecanismo para proteger nuestros endpoints.

Una elección natural sería presentar todo desde un Load Balancer capa 7, pero administrar todo el diseño del API podría ser un reto para esa solución. Es aquí donde Amazon API Gateway viene al rescate.

Adicionalmente el equipo técnico de Picturesocial se reunió para definir los siguientes requerimientos:

  • R1: Las API no pueden exponerse directamente desde Kubernetes hacia una red pública.
  • R2: Evitaremos llamar al backend por contenido que no se refresca constantemente.
  • R3: Ninguna aplicación cliente será autorizada para llamar al backend más de 10,000 veces por segundo.
  • R4: Los llamados a API’s necesitan un API Key.

Ahora, en el paso a paso, aprenderemos cómo exponer nuestras API’s mientras que cubrimos los requerimientos usando Network Load Balancers, API Gateway y VPC Link.

Pre-requisitos

Paso a Paso

  • Exploremos visualmente que es lo que haremos a continuación. Tendremos un humano llamando API’s por medio de un API Gateway, ese API Gateway tendrá una conexión privada hacia Kubernetes a través de VPC Link y VPC Link será el canal que podrá llamar al Private Load Balancer.

  • Vamos a asegurarnos que los servicios expuestos por Kubernetes solo puedan ser llamados dentro de una VPC, aquí es donde Kubernetes Private Load Balancers nos ayudará a simplificar el proceso. Este servicio fue explorado en un post anterior sobre Qué es Kubernetes y Por qué debería importarme.
  • Revisemos el manifiesto que usamos en ese post. Básicamente creamos un LoadBalancer público para la app pictures que es presentada en el puerto 80.
#########################
# Definicion del servicio
#########################
kind: Service
apiVersion: v1
metadata:
  namespace: dev
  name: pictures-lb
spec:
  selector:
    app: pictures
  ports:
  - port: 80
    targetPort: 5075
  type: LoadBalancer
  • Si queremos hacer que ese LoadBalancer será accesible únicamente bajo una VPC, necesitamos hacer algunos cambios. Kubernetes trabaja con personalizaciones para interactuar con los Cloud Providers dentro de “anotaciones” o “annotations”, aquí es donde definimos el tipo de LoadBalancer y si será público o privado.
#########################
# Definicion del servicio
#########################
kind: Service
apiVersion: v1
metadata:
  namespace: dev
  name: pictures-lb
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: nlb
    service.beta.kubernetes.io/aws-load-balancer-internal: "true"
spec:
  selector:
    app: pictures
  ports:
  - port: 80
    targetPort: 5075
  type: LoadBalancer
  • Guardamos los cambios nuestro manifiesto y aplicamos los cambios en Kubernetes.

kubectl apply -f manifest.yml

  • Ahora vamos a ver el resultado, obteniendo el Full Qualified Doman Name (FQDN) del LoadBalancer privado que acabamos de crear. Podemos guardar el FQDN en un archivo de texto debido a que vamos a usar la ruta varias veces en los siguientes pasos 👷.

  • La forma más fácil de exponer un API por medio de API Gateway es importando un archivo Swagger con su definición. Esto es bastante simple de lograr, ejecutando el API que hicimos en el post anterior y probándola localmente nos vamos a la URL http://localhost:5075/swagger/index.html

  • Debes descargar el archivo swagger.json que se encuentra debajo del nombre del API.
  • Abriremos la Consola de AWS y buscamos API Gateway o simplemente le damos clic al siguiente link: https://us-east-1.console.aws.amazon.com/apigateway/main/apis?region=us-east-1
  • Le damos clic en VPC Link y creamos una nueva. Como estamos creando un API REST, vamos a seleccionar esa opción como en la imagen a continuación:

  • En la opción de target NLB seleccionaremos el mismo nombre del LoadBalancer privado que creamos al inicio.
  • El proceso de creación del VPC Link y de establecimiento de la conexión tomará un rato, así que una buena idea es sentarse, hacerse un buen cafecito y buscar algo dulce que lo acompañe (La voz de mi conciencia dice una manzana, pero la de mi corazón dice panecitos) ☕ 🥐
  • Cuando esté listo, regresemos a la opción de API’s y hagamos clic en crear una nueva API. Vamos a seleccionar IMPORT en la opción de REST API.

  • Acá es donde importamos el archivo Swagger que descargamos en pasos anteriores.

  • Tendremos la opción de elegir el tipo de Endpoint: a/Regional: cuando el endpoint vivirá exclusivamente en su región, en nuestro caso us-east-1. b/Edge Optimized: cuando API Gateway usa Amazon CloudFront para crear réplicas globales y rutas optimizadas para API’s distribuidas. c/ Privadas: cuando queremos que nuestras API’s sean accesibles solo dentro de una VPC.
  • En nuestro caso seleccionaremos Regional y le daremos clic en Importar.
  • Ahora toda la estructura del API será creada en API Gateway y podemos comenzar a trabajar en la integración con VPC Link.

  • Como puedes ver, tenemos un diagrama con el flujo de ejecución de cada método de nuestra API. Vamos a dar clic en “Integration Request” para cambiar el tipo de integración defecto de HTTP_PROXY a VPC_Link
  • Debería verse de la siguiente forma: a/ En “Integration Type” seleccionamos VPC Link 🤓, b/ Vamos a darle check a “Proxy Integration”, c/ El método seguirá siendo GET, d/ Seleccionamos el VPC Link que creamos. e/ El “Endpoint URL” será el FQDN con http y la ruta al método del API. Y finalmente le damos clic en “Save” 💾

  • Para probar que todo esté funcionando bien puedes ir nuevamente a “Method Execution” y hacer clic en la opción de test. Si todo funcionó bien habremos cubierto el primer requerimiento. R1: Las API no pueden exponerse directamente desde Kubernetes hacia una red pública.
  • ¡Ahora es momento de publicar el API! Click en “Actions” y luego en “Deploy API”

  • Debemos establecer el “Stage”, básicamente son los ambientes de esa API, digamos por ejemplo Desarrollo, Certificación y Producción. En mi caso le llamaré “Test” y luego le haré clic en “Deploy”

  • Una vez desplegado, seleccionaremos “Stages” del menú vertical izquierdo y configuraremos lo necesario para cumplir R2: Evitaremos llamar al backend por contenido que no se refresca constantemente; y R3: Ninguna aplicación cliente será autorizada para llamar al backend más de 10,000 veces por segundo. Para R2 marcaremos la casilla de “Enable API Cache” que ayudará a servir los requests al API que llamen a data estática o no tan cambiante. En nuestro caso renovaremos el caché cada 5 segundos por medio del campo “Cache Time-to-live (TTL)”.
  • Para R3 haremos clic en “Enable Throttling” de tal forma que establezcamos un ratio de 10,000 RPS (Request por segundo) como máximo.

  • Además, en la zona superior de los “Stage Settings” verás el Invoke URL para el API, lo usaremos más adelante para las pruebas.
  • Ahora es momento de configurar un API Key para completar el requerimiento R4: Las API’s deben ser llamadas usando un API Key.
  • Para ello vamos a darle clic a API Keys desde el menú vertical izquierdo y luego “Create an API Key”. Vamos a llamar esta llave test y seleccionamos que se genere de forma automática.

  • Finalmente, dentro del Method Execution de cada API vamos a habilitar que API Key sea requerido. Cambiando “API Key required” de false a true.

  • Si llamamos al API directamente sin un API Key recibiremos un error 403, indicando que el llamado está prohibido.

  • Pero, por el contrario, si usamos la cabecera x-api-key e incluimos el API Key autogenerado, entonces obtendremos la respuesta correcta. 👌

Si llegaste hasta acá significa que aseguraste tu backend por medio de API Gateway, de forma muy rápida y con pocos pasos. Gracias por leer hasta acá y espero que no te pierdas el siguiente episodio donde aprenderemos a lidiar con la ambigüedad cuando necesitas cómputo inmediato bajo situaciones donde la demanda será incierta

¡Nos Leemos!

 

 


Sobre el autor

José Yapur es Senior Developer Advocate en AWS con experiencia en Arquitectura de Software y pasión por el desarrollo especialmente en .NET y PHP. Trabajó como Arquitecto de Soluciones por varios años, ayudando a empresas y personas en LATAM.