Blog de Amazon Web Services (AWS)

Cómo exponer varias aplicaciones en Amazon EKS a través de un único balanceador de carga

Por Rubens Devito, Arquitecto de Soluciones Senior de AWS y
JP Santana, Arquitecto de Soluciones Principal para Startups de AWS

 

Introducción

Las arquitecturas de microservicios ya se han convertido en estándar para aplicaciones nativas en la nube. Una mayor granularidad en las políticas de escalado, aislamiento de funciones y capacidad de contar con equipos independientes que trabajen en funcionalidades específicas de la aplicación son solo algunas de las razones por las que se ha utilizado comúnmente este patrón de arquitectura. Combinado a esto, con el hecho de que las nuevas aplicaciones nacen a menudo en la nube, se tiene una combinación perfecta entre una arquitectura modular y escalable con tecnologías que facilitan la implementación, operación y administración de cada microservicio que ofrece la nube.

 

Un patrón, pero varias alternativas de implementación

En AWS, hay al menos dos rutas a seguir para implementar una arquitectura de microservicios: 1) Transformar distintos componentes de una aplicación o servicio en un contenedor o conjunto de contenedores y delegar su administración a un orquestador de contenedores, como Amazon Elastic Kubernetes Service (EKS) y Amazon Elastic Container Service (ECS); 2) transformar distintos componentes de su aplicación o servicio en funciones sin servidor y delegar su administración hacia AWS Lambda.

El siguiente paso consiste en exponer cada uno de estos microservicios, ya sea en contenedores o funciones sin servidor, a través de un endpoint para que un cliente o una API puedan enviar solicitudes y recibir respuestas. Por lo general, querrá que cada microservicio tenga su propio endpoint. Por ejemplo, cada sufijo («/») al final de una dirección apunta a un microservicio diferente:

www.example.com/servicio1 > Microservicio 1
www.example.com/servicio2 > Microservicio 2
www.example.com/servicio3 > Microservicio 3

Este tipo de balanceo o enrutamiento se conoce como Path-Based Routing, en que el enrutamiento está embebido en la dirección/URL.

Una de las principales ventajas de este enfoque es su bajo costo y simplicidad para exponer docenas de aplicaciones. Por eso, Application Load Balancer (ALB) y Amazon API Gateway cuentan con dicha funcionalidad. Es decir, con un único ALB o un único API Gateway, se puede exponer los microservicios que se ejecutan en contenedores de Amazon EKS o Amazon ECS, o en funciones sin servidor de AWS Lambda.

En este artículo, mostraremos cómo exponer sus aplicaciones a través de un Application Load Balancer que se ejecuta en contenedores gestionados por Amazon EKS.

 

Arquitectura y componentes

 

 

Clúster EKS es el clúster de Kubernetes donde se ejecutarán sus aplicaciones. Amazon EKS es un servicio de AWS que abstrae la complejidad de administrar un control plane de Kubernetes, compuesto principalmente por nodos del control plane y por etcd, un motor de base de datos altamente disponible donde se almacena todas las configuraciones del clúster, lo que permite a nuestros clientes centrarse en el data plane, es decir dónde sus aplicaciones serán ejecutadas.

Grupo de Auto Escalado es una funcionalidad en AWS que permite la adición o eliminación automática de instancias de Amazon EC2 basándose en una métrica de supervisión. Para nuestra demostración, solo se utilizará para mantener un número mínimo de instancias EC2 que se ejecutan a alta disponibilidad. Sin embargo, los Grupos de Auto Escalado también son compatibles con AWS Fargate –– de esta forma, AWS también puede gestionar el data plane de tu clúster.

Application Load Balancer (ALB) distribuye automáticamente el tráfico entre varios destinos, sean instancias de Amazon EC2, contenedores o direcciones IP, en una o más zonas de disponibilidad. ALB funciona en la capa 7 (aplicación) del modelo OSI (HTTP/HTTPS) y ofrece, entre muchas funcionalidades, Condiciones de ruta, lo que permite definir reglas que direccionan solicitudes basadas en URL (Path-Based Routing). ALB es una de las tres opciones de balanceo de Elastic Load Balancing.

Ingress es un recurso de Kubernetes que administra el acceso externo al clúster, normalmente HTTP. Un Ingress suele proporcionar balanceo de carga, SSL y alojamiento virtual. Para tener la funcionalidad de un Ingress en el clúster, debe instalar un controlador de entrada.

AWS Load Balancer Controller es un controlador que le ayuda a administrar los clústeres de Elastic Load Balancers for Kubernetes.  Para nuestro escenario, utilizaremos el tipo Ingress para aprovisionar automáticamente un ALB y configurar las reglas de enrutamiento requeridas en este ALB para definirlas mediante manifiestos de Kubernetes.

El objetivo final es que diferentes aplicaciones respondan por diferentes rutas, pero utilizando un solo ALB.

 

 

 

Requisitos previos

Para implementar esta solución, debe tener los siguientes requisitos previos:

  • Un clúster de Amazon EKS aprovisionado con node groups, si decide ejecutar sus cargas de trabajo en instancias Amazon EC2 o en un Fargate profile, si decide ejecutarlas en AWS Fargate;
  • AWS Load Balancer Controller configurado en su clúster para que se cree un Application Load Balancer en el momento en que declaramos un recurso del tipo Ingress en Kubernetes;
  • Imágenes de contenedores de sus aplicaciones alojadas en un repositorio de Amazon Elastic Container Registry (ECR) u otro repositorio compatible de su elección. En este articulo utilizaremos imágenes de contenedores registrados en Amazon ECR y demostraremos la creación y envío de imágenes paso a paso al repositorio.

 

Creación del entorno

Creación de la aplicación e imagen Docker

Vamos a crear primero nuestras aplicaciones de ejemplo y sus respectivos archivos Dockerfile. En nuestro caso, debido a que se trata de un entorno de demostración, utilizaremos una aplicación HTML muy sencilla que muestra un fondo amarillo y la otra un fondo verde, simplemente para simular dos microservicios.

1. Crear un directorio llamado verde y otro llamado amarillo;

mkdir verde/ amarillo/

2. Copie el código de cada aplicación y guárdelo como index.html en sus directorios respectivos:

Aplicación verde:

echo '<html style="background-color: green;"></html>' > verde/index.html

Aplicación amarilla:

echo '<html style="background-color: yellow;"></html>' > amarillo/index.html

3. Vamos a crear archivos Dockerfile en los mismos directorios que creamos los archivos index.html.

Comprenda el archivo: usaremos una base de imágenes de Nginx con Alpine, crearemos un directorio para la aplicación y copiaremos el archivo index.html en este directorio. También mostraremos nuestra aplicación en el puerto 80 (HTTP).

Aplicación verde:

cat < verde/dockerfile <EOF >
DESDE nginx: alpino
EJECUTAR mkdir -p /usr/share/nginx/html/verde
COPIAR. /index.html /usr/share/nginx/html/green/index.html 
EXPONER 80
EOF

Aplicación amarilla:

cat < amarillo/dockerfile <EOF >
DESDE nginx: alpino
EJECUTAR mkdir -p /usr/share/nginx/html/amarillo
COPIAR. /index.html /usr/share/nginx/html/yellow/index.html 
EXPONER 80
EOF

4. Ahora vamos a crear un repositorio de Amazon ECR para cada aplicación y subir sus imágenes Docker.

Siga esta documentación para crear los repositorios verde y amarillo para cada una de las aplicaciones.

aws ecr create-repository --repository-name green

aws ecr create-repository --repository-name yellow

5. Una vez creado los repositorios, acceda a ellos y haga clic en el botón View push commands.

 

 

Sigue el paso a paso que se mostrará para tu sistema operativo para crear la imagen Docker y cargarla en el repositorio. En este ejemplo, utilizamos us-east-1 como región. Si no estás usando la región N. Virginia recuérdate cambiar el código.

export AWS_REGION=$(aws ec2 describe-availability-zones --output text --query 'AvailabilityZones[0].[RegionName]')
export AWS_REGISTRY_ID=$(aws ecr describe-registry --query registryId --output text)
export AWS_ECR_REPO=${AWS_REGISTRY_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $AWS_ECR_REPO
cd amarillo/
docker build . -t yellow
docker tag yellow:latest $AWS_ECR_REPO/yellow:latest
docker push $AWS_ECR_REPO/yellow:latest
cd ..

cd verde/
docker build . -t green
docker tag green:latest $AWS_ECR_REPO/green:latest
docker push $AWS_ECR_REPO/green:latest
cd ..

 

Recuerde realizar este procedimiento para ambas aplicaciones.

Configuración del archivo de configuración del entorno en Kubernetes

Ahora vamos a crear un archivo de configuración de Kubernetes declarando los objetos de nuestro entorno.

1. Crea un archivo llamado color-app.yaml en tu editor de texto preferido y copia el contenido abajo en él. Si no utilizas Amazon ECR, cambia los datos de imagen a la URL de tu repositorio de imágenes Docker:

cat <<EOF > color-app.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: color-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: green-app
  namespace: color-app
  labels:
    app: green-app
spec:
  selector:
    matchLabels:
      app: green-app
  replicas: 2
  template:
    metadata:
      labels:
        app: green-app
    spec:
      containers:
      - name: green-container
        image: $AWS_ECR_REPO/green:latest
        ports:
            - containerPort: 80
        resources:
          limits:
            memory: "100Mi"
            cpu: "200m"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: yellow-app
  namespace: color-app
  labels:
    app: yellow-app
spec:
  selector:
    matchLabels:
      app: yellow-app
  replicas: 2
  template:
    metadata:
      labels:
        app: yellow-app
    spec:
      containers:
      - name: yellow-container
        image: $AWS_ECR_REPO/yellow:latest
        ports:
            - containerPort: 80
        resources:
          limits:
            memory: "100Mi"
            cpu: "200m"
EOF

Comprenda el archivo: Primero crearemos un espacio de nombres llamado color-app y dos Deployment, uno para cada aplicación. En estos Deployment definiremos 2 réplicas, agregaremos algunas etiquetas que hacen referencia a cada aplicación, indicaremos la imagen y configuramos límites de utilización de memoria y CPU.

2. Ahora agregamos dos servicios del tipo NodePort a nuestro archivo, uno para cada aplicación. Los servicios NodePort sirven para exponer las aplicaciones del clúster para que Ingress pueda acceder a ellas, lo que en nuestro caso se realiza a través del Application Load Balancer (ALB) creado automáticamente por el AWS Load Balancer Controller, mencionado en los requisitos previos. Tenga en cuenta que en Services vinculamos cada aplicación a través de etiquetas y selectores:

cat <<EOF >> color-app.yaml
---
apiVersion: v1
kind: Service
metadata:
  namespace: color-app
  name: green-service
  labels:
    app: green-app
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: /green/index.html
spec:
  type: NodePort
  selector:
    app: green-app
  ports:
    - port: 80
      targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
  namespace: color-app
  name: yellow-service
  labels:
    app: yellow-app
  annotations:
    alb.ingress.kubernetes.io/healthcheck-path: /yellow/index.html
spec:
  type: NodePort
  selector:
    app: yellow-app
  ports:
    - port: 80
      targetPort: 80
EOF

3. Por último, definimos nuestro controlador Ingress. Como se mencionó anteriormente, ALB realizará la función Ingress. Con esto, tiene la ventaja de no tener que administrar sus ingress a través de pods en el clúster, no consumirá recursos del clúster para ello, y también puede contar con todas las potentes funciones de ALB, como el escalado automático, las funciones de seguridad avanzadas y las funcionalidades de enrutamiento, como las basadas en la ruta de la URL que estamos demostrando en ese artículo.

cat <<EOF >> color-app.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: color-app-ingress
  namespace: color-app
  labels:
    app: color-app
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
    alb.ingress.kubernetes.io/healthcheck-port: traffic-port
    alb.ingress.kubernetes.io/healthcheck-interval-seconds: '15'
    alb.ingress.kubernetes.io/healthcheck-timeout-seconds: '5'
    alb.ingress.kubernetes.io/success-codes: '200'
    alb.ingress.kubernetes.io/healthy-threshold-count: '2'
    alb.ingress.kubernetes.io/unhealthy-threshold-count: '2'
spec:
  rules:
    - http:
        paths:
          - path: /yellow
            pathType: Prefix
            backend:
              service:
                name: yellow-service
                port:
                  number: 80                       
          - path: /green
            pathType: Prefix
            backend:
              service:
                name: green-service
                port:
                  number: 80
EOF

Comprenda el archivo: Tenga en cuenta que en nuestro archivo estamos definiendo «anotaciones de entrada» para que se aprovisione a través de un ALB público, el tráfico sea direccionado directamente a los pods y se configuran las funcionalidades de comprobación de estado (health checks) de ALB. Dentro del parámetro «spec», definimos las rutas URL específicas de cada una de las aplicaciones y direccionamos el tráfico a sus respectivos Services.

Creación del entorno de clúster de Amazon EKS

Una vez creado el archivo yaml, simplemente implementamos nuestra aplicación en el clúster de Amazon EKS, a través de kubectl.

1. Acceda al directorio en el que se ha guardado el archivo color-app.yaml y ejecute el siguiente comando desde una estación de trabajo que tenga acceso al clúster a través de kubectl.

kubectl apply -f color-app.yaml

Si tiene dudas sobre cómo configurar la herramienta de línea de comando, siga esta documentación para configurar RBAC y esta para la configuración del contexto local.

El entorno se aprovisiona en unos minutos.

2. Una vez que se aprovisione el ALB, puede comprobar la configuración que ha realizado automáticamente en el ALB yendo a la AWS Management Console en Amazon EC2 > Load Balancers > seleccione el ALB > haga clic en la pestaña Listeners > haga clic en View/edit rules.

 

 

3. Después de aprovisionar el ALB, ejecute el siguiente comando y copie la entrada DNS asignada al ALB. Pegue esta URL en el navegador usando /green o /yellow al final, como se muestra en las imágenes siguientes:

kubectl get ingress color-app-ingress -n color-app -o=jsonpath="{'http://'}{.status.loadBalancer.ingress[].hostname}{'\n'}"

/green

 

/yellow

 

Próximos pasos

En base a este ejemplo, ahora puedes usar el archivo yaml para tu propia carga de trabajo. Puede cambiar el nombre de las etiquetas y componentes de Kubernetes (Namespace, Deployment, Service e Ingress) de su entorno y utilizar la imagen Docker de su propia aplicación reemplazándola en la definición del Deployment. Además, este tutorial también se puede ejecutar en un clúster de Kubernetes desplegado directamente en Amazon EC2 en lugar de Amazon EKS.

 

Conclusión

En este articulo hemos visto que existen diferentes formas de desplegar una arquitectura de microservicios en la nube de AWS. A continuación, explicamos algunos conceptos clave del enfoque utilizando contenedores. Por último, demostramos paso a paso cómo implementarlo de forma sencilla y efectiva utilizando Amazon EKS y solo un único Application Load Balancer.

 

Este artículo fue traducido del Blog de AWS en Portugues.

 


Sobre los autores

Rubens Devito es Arquitecto de Soluciones Senior en AWS.

 

 

 

 

 

JP Santana es Arquitecto de Soluciones Principal para Startups en AWS.

 

 

 

 

 

Sobre los revisores

Davi Garcia es Arquitecto de Soluciones Senior con especialidade en Migraciones en AWS.

 

 

 

 

 

Diego Voltz Fagundes es Arquitecto de Soluciones para Negocios en AWS.

 

 

 

 

Conozca más contenidos sobre Computación en la página de sesiones bajo demanda.

Acesse >