APIs y MicroServicios en Empresas Monolíticas — Deploy y escalamiento de microservicios con Kubernetes #7

Jovani Aarzate
Apr 14 · 11 min read

La necesidad de escalar microservicios de forma global hoy en día es necesaria, siendo la forma mas adecuada para que los recursos se puedan gestionar según la demanda y esta es una de la ventajas que nos provee Kubernetes.

El uso de contenedores y de orquestadores como Kubernetes, permite automatizar el despliegue, escalado y gestión de las aplicaciones que se ejecutan dentro de dichos contenedores.

Existen dos opciones de implementación de auto escalado de microservicios, con contenedores y Kubernetes.

Horizontal Pod Autoscaling (HPA) Monitorización y escalado por script

¿Cómo funciona el autoescalador de POD horizontal HPA?

Al iniciar el despliege de microservicios en Kubernetes, inicialmente crearemos un deployment y con ello crear solo un POD para ejecutar nuestra aplicación. cuando el tráfico aumente, tendremos que escalar la aplicación para satisfacer la demanda de los usuarios.

La ampliación de una implementación garantizará que se creen nuevos PODS y se programen en nodos con los recursos disponibles,

Kubernetes también admite el escalado automático de PODS, la escala a cero también es posible, y terminará todos los PODS de la implementación especificada.

La ejecución de varias instancias de una aplicación requerirá una forma de distribuir el tráfico a todas ellas.

Los servicios tienen un balanceador de carga integrado, que distribuirá el tráfico de red a todos los PODS de una implementación expuesta.

Los servicios supervisarán continuamente los PODS en ejecución utilizando puntos finales, para garantizar que el tráfico se envíe solo a los PODS disponibles.

Lo que hace es crear un punto de entrada que recibe el tráfico por el puerto definido y balancea entre las distintas replicas del pod. (kube-proxy)

Una vez que tenga varias instancias de una aplicación en ejecución, podrá realizar actualizaciones continuas sin tiempo de inactividad. ZERO DOWTIME

pero….

El HorizontalPodAutoscaler normalmente obtiene métricas de una serie de API agregadas (metrics.k8s.io, custom.metrics.k8s.io, y external.metrics.k8s.io). La métrica metrics.k8s.io generalmente la proporciona metrics-server, que debe iniciarse por separado.

El HorizontalPodAutoscaler también puede obtener métricas directamente de Heapster.

Horizontal Pod Autoscaling (HPA)

Este escalado se hace por uso de recursos como CPU/Memoria, aunque en futuras versiones Kubernetes llegará a soportar otras métricas adicionales.

Ahora manos a la obra….

Primeramente:

1.- Para realizar esta ambientación es necesario bajar el proyecto de clientes de las siguientes url’s.

https://github.com/jovaniac/api-clientes-microservicios-scaling.git

Prerequisitos 1.- Tener un Cluster de Kubernetes, podemos instalar Minikube, en este caso se uso GKE como cluster.

Crearemos en cluster básico en Google Cloud Plattform:

caracteristicas del Cluster

El cluster de Kubernetes se aproviciona rápidisimo!!

Cluster de 4 nodos 8vCPUs con 30 GB de RAM Total

Obtenemos los datos de conexión al cluster para Kubectl, con gcloud, es necesario tener instalado y configurado.

> gcloud container clusters get-credentials standard-cluster-1  --zone us-central1-a --project  true-hook-237600

Donde:

standard-cluster-1 es tu cluster

— zone us-centra1-a indicamos la zona donde se desplegará el cluster

— project nombre del proyecto de google

Validamos que kubectl en nuestra maquina local, ya esta configurado con los datos en el archivo .config el cual apunta a nuestro cluster previamente creado, para esto obtendremos los datos con la siguiente instruccion de gcloud.

Validamos el cluster con:

> kubectl cluster-info

Nos asigna una IP en este caso 35.239.75.155

Nodos del CLuster en estatus READY.

kubectl get nodes

Verificamso que todos los PODs para el funcionamiento del Cluster se hayan creado correctamente con:

kubectl get pods --all-namespaces

Deploy y Services de MicroServicios Es necesario crear los archivos de deploy y service para nuestro microservicios de clientes, este se deberán de ejecutar con kubectl en Kubernetes.

> kubectl apply -f kubernetes/

Deploy y Service de Clientes

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: servicio-cliente
  labels:
    app: servicio-cliente
spec:
  replicas: 1
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2
      maxUnavailable: 0
  selector:
    matchLabels:
      app: servicio-cliente
  template:
    metadata:
      labels:
        app: servicio-cliente
    spec:
      containers:
        - name: servicio-cliente
          image: jovaniac/servicio-cliente:0.0.1-snapshot
          ports:
            - containerPort: 8081
              protocol: TCP
          imagePullPolicy: Always
          resources:
          #solicitud de memoria
            requests:
              memory: "256Mi"
              cpu: "250m"
          #limite de memoria
            limits:
              memory: "1024Mi"
              cpu: "500m"   
---
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
  name: servicio-cliente
spec:
  maxReplicas: 5
  minReplicas: 1
  targetCPUUtilizationPercentage: 70
  scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment
    name: servicio-cliente

Importante la siguiente configuración, para especificar la asignación de CPU y RAM para la aplicación interna del contenedor, en este caso microservicios con Spring Boot. estableciendo la memoria inicial y el máximo.

#solicitud de memoria
            requests:
              memory: "256Mi"
              cpu: "250m"
          #limite de memoria
            limits:
              memory: "1024Mi"
              cpu: "500m"

Donde en requests se especifica la memoria solicitada al contenedor, limits indicamos cual seria el limite para poder escalar.

Ahora, especificamos cuanto queremos ESCALAR, cuantas REPLICAS se crearán al momento de hacer SCALING.

spec:
  maxReplicas: 5
  minReplicas: 1
  targetCPUUtilizationPercentage: 70
  scaleTargetRef:
    apiVersion: extensions/v1beta1
    kind: Deployment
    name: servicio-cliente

Se indica cuales serán el número de replicas cuando se ESCALE maxReplicas, y a cuantas va decrementar Scaling DOWN minReplicas. así mismo cuanto será el porcentaje de CPU usado para iniciar el SCALING UP targetCPUUtilizationPercentage, en este caso lo hacemos por CPU 70%.

La imagen que se expresa en el Deploy de Cliente en este caso se publico en el registry de DockerHub.

Para poder crear la imagen, se creo el siguiente Dockerfile.

FROM openjdk:8u151-jre-slim
MAINTAINER jovaniac@gmail.com”
COPY servicio-cliente.jar /opt/servicio-cliente.jar
EXPOSE 8081
ENTRYPOINT [“java”, “-Djava.awt.headless=true”, “-Xms256m”, “-Xmx256m”, “-jar”, “/opt/servicio-cliente.jar”]

Service Discovery de Clientes, importante no definir como LoadBalancer los services, ya que queremos que la comunicación sea por el ingresgateway de Istio.

apiVersion: v1
kind: Service
metadata:
  name: servicio-cliente
  labels:
    app: servicio-cliente
spec:
  spec:
  type: LoadBalancer
  ports:
  - port: 8081
    name: http
  selector:
    app: servicio-cliente

Nos ponemos en la raiz del proyecto de clientes y ejecutamos la siguiente instrucción, la cual nos servirá para poder instalar el microservicio en Kubernetes

> kubectl apply -f kubernetes/

Se realizó correctamente el deploy, veremos que nos generé una IP publica para poder realizar las pruebas de SCALING. en la columna de EXTERNAL-IP nos aprovicionará una IP Elastica, inicialmente inicia como PENDING.

Veremos que tambien nos creará un HPA, con las caracteristicas que establecimos y podemos visualizar el consumo actual del microservicio de clientes.

> kubectl get pods,svc,hpa — all-namespaces

Vemos que en la columna TARGET, indica cual es el portentaje para que ESCALE el POD en este caso 70%, y que el estado actual es DESCONOCIDO, pero aqui veremos el porcentaje de la memoria USADA.

Dejamos pasar algunso segundos y ahora veremso reflejado el siguiente TARGET 0% / 70%.

El log del microservicio para ver si ya se inicio.

> kubectl logs -f servicio-cliente-669bd54644-zbwmf

Verificamos que ya nos haya aprovicionado la IP publica, la ip que nos da es 34.66.232.240.

default service/servicio-cliente LoadBalancer 10.11.251.249 34.66.232.240 8081:31362/TCP 12m

Momento de ESCALAR…

Herramienta de benchmarking HTTP

Para esto necesitaremos instalar WRK a HTTP benchmarking tool, wrk es una herramienta de evaluación comparativa de HTTP moderna capaz de generar una carga significativa cuando se ejecuta en una única CPU de múltiples núcleos.

Para poder instalar la herramienta ir a https://github.com/wg/wrk/wiki/Installing-wrk-on-Linux

ahora realizamos un request al micoservicio de clientes:

> http://34.66.232.240:8081/api/v1/clientes

payload de entrada:

{
 “apellidoMaterno”: “cabrera”,
 “apellidoPaterno”: “arzate”,
 “direccion”: “test”,
 “edad”: 29,
 “email”: “jovaniac@gmail.com”,
 “genero”: “h”,
 “nombre”: “jovani”
}

request con postman:

respuesta, vemos que genera un folio de creación del cliente.

{
    "folioCliente": "-1804035403",
    "nombre": "jovani",
    "apellidoPaterno": "arzate",
    "apellidoMaterno": "cabrera",
    "email": "jovaniac@gmail.com",
    "direccion": "test",
    "genero": "h",
    "edad": 29
}

Log del Container, en Kubernetes, vemos como aparece 1 peticion que hemos realizado al microservicio de clientes construido con Spring Boot

> kubectl logs -f servicio-cliente-669bd54644-zbwmf

okok, ahora comencemos a generar TRAFICO y verificar que se esten creando las REPLICAS de los PODs y se balance vía SERVICE las solicitudes.

Abriremos varias ventanas para poder ver que se están atendiendo las solicitudes en los multiples PODs.

Haya vamos!, con la siguiente instrucción realizaremos la carga de Trafico.

Donde:

-c, --connections: total number of HTTP connections to keep open with
                   each thread handling N = connections/threads

-d, --duration:    duration of the test, e.g. 2s, 2m, 2h

-t, --threads:     total number of threads to use

-s, --script:      LuaJIT script, see SCRIPTING

-H, --header:      HTTP header to add to request, e.g. "User-Agent: wrk"

    --latency:     print detailed latency statistics

    --timeout:     record a timeout if a response is not received within
                   this amount of time.

Quedando de las siguiente forma, comenzaremos poco a poco.

wrk -t1 -c1 -d30s http://34.66.232.240:8081/api/v1/clientes

Comienza a llegar el tráfico.

El HPA vía Heapster comienza a actualiza el uso de CPU.

8% de uso

Momento de ESCALAR!!!!, entramos a cada uno de los logs de los PODs, vemos que comienza a llegar peticiones al mismo microservicio en cada container.

peticiones que llegan a cada POD

El targer indica que ya sobrepaso del 70%.

Se comienzan a crear REPLICAS y ahora tenemos 2 PODs, atendiendo el tráfico.

Abrimos varias terminales para poder lanzar el tráfico, ahora con:

> wrk -t100 -c100 -d300s http://34.66.232.240:8081/api/v1/clientes

Se crean 3 REPLICAS y tenemos 3 PODs, atendiendo cada solicitud de forma balanceada.

El porcentaje de consumo esta al doble y se aproviciona más replicas, ahora tenemos 5 PODS atendiendo el tráfico.

5 Replicas, 5 PODS, con ello atendemos 100 hilos x 100 conexiones durante 300 segundos.

Tenemos abiertos 3 ventanas para ver los logs de 3 PODs, y el consumo de CPU comienza a disminuir.

Saturando el ancho de banda :), al estar enviando mucho tráfico estoy saturando mi ancho de banda de subida :)

Terminamos las peticiones hacia el microservicio y poco a poco se comienzan a morir cada POD que se creo, por lo cual me sale la leyenda de NO SUCH Container por que se produce SCALE DOWN, una vez que ya no se están recibiendo tantas solicitudes, Kubernetes automaticamente comienza a liberar recursos terminando los PODs, sin dejar de atender el tráfico entrante.

EL SCALING DOW llega a tener solo 1 replica, ya que nuestra configuración indica que como minimo existe 1.

Como podemos ver el consumo de CPU bajo, y así se redujo automáticamente el número de réplicas a 1.

Algunas evidencias del Scaling realizado en tiempo REAL.

escalando microservicios video 1
escalando microservicios video 2

En el siguiente artículo, hablaremos sobre Monitoreo de Microservicios con Istio y Grafana.

Te invito a que leas el overview de microservicios en el siguiente Link.

y mi artículo del Patron Service Discovery en Kubernetes.

así como:

y por último DataManagement y Trazabilidad Distribuida:

Mi canal de youtube: https://www.youtube.com/channel/UC-eLSM45n_ZSYr1T749E6KA/videos?view_as=subscriber

Jovani Arzate |Scaling | HPA Kuberntes | Kubernetes| apificación | microservicios | apis | spring boot | microservices | DDD| diseño de base de datos en microservicios | datamanagement| diseño de microservicios | transformación digital | api first | api first development | contrac first | microservicices with data

Jovani Aarzate

Written by

Hay lugares mucho más fáciles para trabajar, pero nadie ha cambiado el mundo en 40 horas semanales.