Tutorial de NGINX: reduce la latencia de Kubernetes con el escalado automático

NGINX | 15 de marzo de 2022

Este tutorial es uno de los cuatro que ponen en práctica conceptos de «Microservicios de marzo de 2022: redes de Kubernetes»:

¿Quieres una guía detallada sobre cómo utilizar NGINX en aún más casos de uso de redes de Kubernetes? Descarga gratis nuestro libro electrónico, «Gestión del tráfico de Kubernetes con NGINX: guía práctica».

¡Tu organización ha creado una aplicación en Kubernetes y ahora está ganando popularidad! Habéis pasado de tener apenas unos pocos visitantes a recibir cientos (y, a veces, miles) al día. Pero hay un problema… el aumento del tráfico está provocando un cuello de botella, lo que genera latencia y tiempos de espera agotados para vuestros clientes. Si no podéis mejorar la experiencia, la gente dejará de usar la aplicación.

Tú – el valiente ingeniero de Kubernetes – tienes una solución. Despliegas un controlador Ingress para enrutar el tráfico y configuras una política de escalado automático para que el número de pods del controlador Ingress aumente y disminuya al instante en función de las fluctuaciones del tráfico. Ahora, los pods de tu controlador Ingress gestionan sin problemas los picos de tráfico – «¡Adiós, latencia!» – y reducen su número para ahorrar recursos cuando disminuye el tráfico – «¡Hola, ahorro de costes!». Bien hecho.

Descripción general del laboratorio y el tutorial

Este blog complementa el laboratorio de la Unidad 1 de Microservices March 2022: «Diseño de clústeres de Kubernetes para sitios web con mucho tráfico», en el que se muestra cómo utilizar NGINX Ingress Controller para exponer una aplicación y, a continuación, escalar automáticamente los pods del controlador Ingress en respuesta a un tráfico elevado.

Para seguir el tutorial, necesitas un equipo con:

  • 2 CPU o más
  • 2 GB de memoria libre
  • 20 GB de espacio libre en disco
  • Conexión a Internet
  • Gestor de contenedores o máquinas virtuales, como Docker, Hyperkit, Hyper‑V, KVM, Parallels, Podman, VirtualBox o VMware Fusion/Workstation
  • minikube instalado
  • Helm instalado
  • Una configuración que te permita abrir una ventana del navegador. Si no es posible, tendrás que averiguar cómo acceder a los servicios pertinentes mediante un navegador.

Para sacar el máximo partido al laboratorio y al tutorial, le recomendamos que, antes de empezar:

Este tutorial utiliza estas tecnologías:

Las instrucciones de cada reto incluyen el texto completo de los archivos YAML utilizados para configurar las aplicaciones. También puedes copiar el texto de nuestro repositorio de GitHub. Junto al texto de cada archivo YAML se proporciona un enlace a GitHub.

Este tutorial incluye cuatro desafíos:

  1. Configurar una aplicación sencilla en un clúster de Kubernetes
  2. Usar NGINX Ingress Controller para dirigir el tráfico a la aplicación
  3. Generar y supervisar el tráfico
  4. Escalar automáticamente NGINX Ingress Controller

Desafío 1: Configurar una aplicación sencilla en un clúster de Kubernetes

En este reto, crearás un clúster de minikube e instalarás Podinfo como aplicación de ejemplo.

Crear un clúster de Minikube

Crea un clúster de minikube. Tras unos segundos, un mensaje confirma que la implementación se ha realizado correctamente.

$ minikube start 🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default 

Instalar la aplicación Podinfo

Podinfo es una «aplicación web desarrollada con Go que muestra las prácticas recomendadas para ejecutar microservicios en Kubernetes». La utilizamos como aplicación de ejemplo porque ocupa muy poco espacio.

  1. Con el editor de texto que prefieras, crea un archivo YAML llamado 1-deployment.yaml con el siguiente contenido (o cópialo desde GitHub). Este archivo define un Deployment con una única réplica y un Service.
apiVersion: apps/v1 kind: Deployment 
metadata: 
  name: podinfo 
spec: 
  selector: 
    matchLabels: 
      app: podinfo 
  template: 
    metadata: 
      labels: 
        app: podinfo 
    spec: 
      containers: 
      - name: podinfo 
        image: stefanprodan/podinfo 
        ports: 
        - containerPort: 9898 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: podinfo 
spec: 
  ports: 
    - port: 80 
      targetPort: 9898 
      nodePort: 30001 
  selector: 
    app: podinfo 
  type: LoadBalancer 
  1. Despliega la aplicación:
$ kubectl apply -f 1-deployment.yaml deployment.apps/podinfo created 
service/podinfo created
  1. Confirma que el pod de Podinfo se haya desplegado, tal como indica el valor Running en la columna STATUS.
$ kubectl get podsNAME                       READY   STATUS   RESTARTS   AGE 
podinfo-5d76864686-rd2s5   1/1     Running  0          3m38s
  1. Abre Podinfo en un navegador. La página greetings from podinfo indica que Podinfo está en ejecución.
$ minikube service podinfo

Desafío 2: Usa NGINX Ingress Controller para dirigir el tráfico a la aplicación

En este reto, desplegarás NGINX Ingress Controller y lo configurarás para dirigir el tráfico a la aplicación Podinfo.

Desplegar NGINX Ingress Controller

La forma más rápida de instalar NGINX Ingress Controller es mediante Helm.

  1. Añade el repositorio de NGINX a Helm:
$ helm repo add nginx-stable https://helm.nginx.com/stable 
  1. Descargue e instale el controlador de entrada basado en NGINX Open Source NGINX Ingress Controller, cuyo mantenimiento corre a cargo de F5 NGINX. La última línea de la salida confirma que la instalación se ha realizado correctamente.
$ helm install main nginx-stable/nginx-ingress \ --set controller.watchIngressWithoutClass=true \ --set controller.service.type=NodePort \ --set controller.service.httpPort.nodePort=30005 
NAME: main 
LAST DEPLOYED: Tue Mar 15 09:49:17 2022 
NAMESPACE: default 
STATUS: deployed 
REVISION: 1 
TEST SUITE: None 
NOTES: The NGINX Ingress Controller has been installed.
  1. Confirme que el pod de NGINX Ingress Controller se haya desplegado, tal como indica el valor Running en la columna STATUS (para facilitar la lectura, la salida se muestra en dos líneas).
$ kubectl get podsNAME                                   READY   STATUS    ...
main-nginx-ingress-779b74bb8b-mtdkr    1/1     Running   ...
podinfo-5d76864686-fjncl               1/1     Running   ...

       ... RESTARTS   AGE
       ... 0          18s 
       ... 0        2m36s

Dirige el tráfico a tu aplicación

  1. Con el editor de texto que prefieras, crea un archivo YAML llamado 2-ingress.yaml con el siguiente contenido (o cópialo de GitHub). Este archivo define el manifiesto de Ingress necesario para dirigir el tráfico a Podinfo.
apiVersion: networking.k8s.io/v1 kind: Ingress 
metadata: 
  name: podinfo 
spec: 
  ingressClassName: nginx 
  rules: 
    - host: "example.com" 
      http: 
        paths: 
          - backend: 
              service: 
                name: podinfo 
                port: 
                  number: 80 
            path: / 
            pathType: Prefix 
  1. Despliega el recurso Ingress:
$ kubectl apply -f 2-ingress.yaml ingress.networking.k8s.io/podinfo created 

Desafío 3: Generar y supervisar tráfico

En este reto, observará el rendimiento de NGINX Ingress Controller con distintas cargas de tráfico. Como pasos preparatorios, deberá consultar las métricas disponibles en NGINX Ingress Controller, implementar Prometheus e instalar Locust. A continuación, utilizará Locust para simular un aumento repentino del tráfico y hacer un seguimiento de su efecto en el rendimiento en Prometheus.

Como ya has visto, un controlador Ingress es un pod de Kubernetes convencional que combina un proxy inverso (en nuestro caso, NGINX) con código para integrarlo con Kubernetes. Si tu aplicación recibe mucho tráfico, probablemente tengas que aumentar el número de réplicas del pod de NGINX Ingress Controller para evitar la latencia que se produce cuando NGINX Ingress Controller se sobrecarga.

Enumerar las métricas disponibles

Para saber cuándo escalar y en qué medida, necesita información precisa sobre el rendimiento de NGINX Ingress Controller. En este tutorial, la métrica de NGINX utilizada para determinar cuándo escalar es el número de conexiones activas (nginx_connections_active). Aquí comprobará que NGINX Ingress Controller realiza un seguimiento de esa métrica.

NGINX Ingress Controller expone varias métricas: 8 métricas con el modelo basado en NGINX Open Source que utilizamos en este tutorial y más de 80 métricas con el modelo basado en NGINX Plus.

  1. Obtenga la dirección IP del pod de NGINX Ingress Controller para poder consultar su lista de métricas. La dirección aparece en el campo IP y, en este caso, es 172.17.0.4. (Para facilitar la lectura, se omiten las columnas RESTARTS y AGE, y la salida se distribuye en dos líneas).
$ kubectl get pods -o wide NAME                                  READY   STATUS    ...
main-nginx-ingress-779b74bb8b-6hdwx   1/1     Running   ...
podinfo-5d76864686-nl8ws              1/1     Running   ...

    ... IP           NODE       NOMINATED NODE  READINESS GATES 
    ... 172.17.0.4   minikube   <none>          <none> 
    ... 172.17.0.3   minikube   <none>          <none>
  1. Cree un pod temporal de BusyBox con un shell en un host dentro del clúster de Kubernetes:
$ kubectl run -ti --rm=true busybox --image=busyboxIf you don't see a command prompt, try pressing enter. 
/ # 
  1. Enumere las métricas generadas por su controlador de entrada NGINX y compruebe que incluyen nginx_connections_active. Sustituya <IP_address> por el valor obtenido en el paso 1.
/# wget -qO- <IP_address>:9113/metrics
  1. Salga del shell para volver al servidor de Kubernetes.
/# exit 

Desplegar Prometheus

Ahora que sabe que su controlador de Ingress NGINX realiza un seguimiento de la métrica nginx_connections_active, necesita una herramienta para recopilar («extraer») las métricas; en este tutorial se utiliza Prometheus.

En el caso de NGINX Ingress Controller, Helm es la forma más rápida de instalar Prometheus.

  1. Añada el repositorio de Prometheus a Helm:
$ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
  1. Descarga e instala Prometheus:
$ helm install prometheus prometheus-community/prometheus \ --set server.service.type=NodePort --set server.service.nodePort=30010
  1. Verifique la instalación, que suele tardar hasta 60 segundos en completarse. En el siguiente ejemplo de salida, el comando de verificación se ejecutó apenas unos segundos después del comando helm install, por lo que vemos que la instalación está en curso y que se muestra ContainerCreating en el campo STATUS de algunos pods de Prometheus. La instalación finaliza cuando todos los pods tienen el estado Running. (La salida se distribuye en dos líneas para facilitar su lectura).
$ kubectl get podsNAME                                           READY  ...
main-nginx-ingress-779b74bb8b-mtdkr            1/1    ...
podinfo-5d76864686-fjncl                       1/1    ...
prometheus-alertmanager-d6d94cf4b-85ww5        0/2    ...
prometheus-kube-state-metrics-7cd8f95cb-86hhs  0/1    ...
prometheus-node-exporter-gqxfz                 1/1    ...
prometheus-pushgateway-56745d8d8b-qnwcb        0/1    ...
prometheus-server-b78c9449f-kwhzp              0/2    ...

      ... STATUS             RESTARTS  AGE 
      ... Running            0         3m23s 
      ... Running            0         5m41s 
      ... ContainerCreating  0         7s
      ... Running            0         7s
      ... Running            0         7s
      ... ContainerCreating  0         7s
      ... ContainerCreating  0         7s
  1. Abre Prometheus. En un entorno minikube, ejecuta el siguiente comando, que abrirá el panel de Prometheus en tu navegador predeterminado.
$ minikube service prometheus-server
  1. Una página como la siguiente confirma que el servidor está funcionando.
  2. Escriba nginx_ingress_nginx_connections_active en la barra de búsqueda para ver el valor actual de la métrica de conexiones activas. Verá una conexión activa, lo cual tiene sentido porque ha desplegado un pod de NGINX Ingress Controller.

Instalar Locust

En la siguiente sección, utilizará Locust, una herramienta de código abierto para realizar pruebas de carga, con el fin de simular un aumento repentino del tráfico y observar el rendimiento de NGINX Ingress Controller en Prometheus. Aquí desplegará Locust.

  1. Con el editor de texto que prefiera, cree un archivo YAML llamado 3-locust.yaml con el siguiente contenido (o cópielo de GitHub). Los objetos Deployment y Service definen el pod de Locust. El objeto ConfigMap define un script llamado locustfile.py que genera las solicitudes que se enviarán al pod con las cabeceras correctas.
apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: locust-script 
data: 
  locustfile.py: |- 
    from locust import HttpUser, task, between 

    class QuickstartUser(HttpUser): 
        wait_time = between(0.7, 1.3) 

        @task 
        def hello_world(self): 
            self.client.get("/", headers={"Host": "example.com"}) 
--- 
apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: locust 
spec: 
  selector: 
    matchLabels: 
      app: locust 
  template: 
    metadata: 
      labels: 
        app: locust 
    spec: 
      containers: 
        - name: locust 
          image: locustio/locust 
          ports: 
            - containerPort: 8089 
          volumeMounts: 
            - mountPath: /home/locust 
              name: locust-script 
      volumes: 
        - name: locust-script 
          configMap: 
            name: locust-script 
--- 
apiVersion: v1 
kind: Service 
metadata: 
  name: locust 
spec: 
  ports: 
    - port: 8089 
      targetPort: 8089 
      nodePort: 30015 
  selector: 
    app: locust 
  type: LoadBalancer 
  1. Despliega Locust:
$ kubectl apply -f 3-locust.yaml configmap/locust-script created 
deployment.apps/locust created 
service/locust created 

Simula un aumento repentino del tráfico y observa su efecto en el rendimiento

  1. Abre Locust en un navegador.
$ minikube service locust
  1. Introduzca los siguientes valores en los campos:
    • Número de usuarios – 1000
    • Tasa de generación – 10
    • Host – http://main-nginx-ingress
  2. Haz clic en el botón «Iniciar enjambre» para enviar tráfico a la aplicación Podinfo.
  3. Vuelva al panel de Prometheus para ver cómo responde NGINX Ingress Controller. Es posible que tenga que realizar una nueva consulta de nginx_ingress_nginx_connections_active para observar algún cambio. Como se muestra en la siguiente captura de pantalla, el único pod de NGINX Ingress Controller tiene dificultades para procesar el aumento del tráfico sin que se produzca latencia a medida que se establece un gran número de conexiones. El gráfico de Prometheus revela que unas 100 conexiones activas por pod de NGINX Ingress Controller constituyen el punto de inflexión a partir del cual se dispara la latencia. Puede utilizar esta información para determinar cuándo debe aumentar el número de pods de NGINX Ingress Controller a fin de evitar un incremento de la latencia.

Reto 4: Escalar automáticamente NGINX Ingress Controller

En el último reto, creará una configuración que escale automáticamente los recursos a medida que aumente el volumen de tráfico. El tutorial utiliza KEDA para el escalado automático, por lo que primero debe instalarlo y crear una política que defina cuándo y cómo se realiza el escalado. Al igual que en el reto 3, a continuación utilizará Locust para simular un aumento repentino del tráfico y Prometheus para observar el rendimiento de NGINX Ingress Controller cuando el escalado automático está habilitado.

Instalar KEDA

KEDA, un sistema de escalado automático de Kubernetes basado en eventos, integra un servidor de métricas (el componente que almacena y transforma las métricas para Kubernetes) y puede consumir métricas directamente desde Prometheus (así como desde otras herramientas). Crea un escalador automático horizontal de pods (HPA) con esas métricas, conecta las métricas recopiladas por Prometheus y las envía a Kubernetes.

Al igual que con NGINX Ingress Controller y Prometheus, en el tutorial se utiliza Helm para instalar KEDA.

  1. Añade KEDA al repositorio de Helm:
$ helm repo add kedacore https://kedacore.github.io/charts 
"kedacore" has been added to your repositories 
  1. Instala KEDA:
$ helm install keda kedacore/keda NAME: keda 
NAMESPACE: default 
STATUS: deployed 
REVISION: 1 
TEST SUITE: None
  1. Compruebe que KEDA se esté ejecutando en dos pods. (Para facilitar la lectura, se han abreviado algunos valores de la columna NAME. Además, se ha omitido la columna RESTARTS; el valor es 0 para todos los pods).
$ kubectl get pods NAME                                    READY  STATUS     AGE 
keda-operator-8644dcdb79-492x5 1/1 Running 59s keda-operator-metrics-apiserver-66d... 1/1 Running 59s 
locust-77c699c94d-dvb5n                 1/1    Running  8m59s 
main-nginx-ingress-779b74bb8b-v7ggw     1/1    Running    48m 
podinfo-5d76864686-c98rb                1/1    Running    50m 
prometheus-alertmanager-d6d94cf4b-8...  2/2    Running    37m 
prometheus-kube-state-metrics-7cd8f...  1/1    Running    37m 
prometheus-node-exporter-j4qf4          1/1    Running    37m 
prometheus-pushgateway-56745d8d8b-9n4nl 1/1    Running    37m 
prometheus-server-b78c9449f-6ktn9       2/2    Running    37m

Crear una política de escalado automático

Ahora, use la definición de recurso personalizado (CRD) ScaledObject de KEDA para definir los parámetros que determinan cómo escala NGINX Ingress Controller. La siguiente configuración:

  • Activa el escalado automático en función del valor de la métrica nginx_connections_active recopilada por Prometheus
  • Despliega un nuevo pod cuando los pods existentes alcanzan 100 conexiones activas cada uno
  • Escala automáticamente los pods de NGINX Ingress Controller desde un único pod hasta un máximo de 20 pods

Siga estos pasos:

  1. Con el editor de texto que prefiera, cree un archivo YAML llamado 4-scaled-object.yaml con el siguiente contenido (o cópielo de GitHub). Este archivo define un ScaledObject de KEDA.
apiVersion: keda.sh/v1alpha1 kind: ScaledObject 
metadata: 
 name: nginx-scale 
spec: 
 scaleTargetRef: 
   kind: Deployment 
   name: main-nginx-ingress 
minReplicaCount: 1 
maxReplicaCount: 20 
cooldownPeriod: 30 
pollingInterval: 1 
triggers: 
- type: prometheus 
  metadata: 
    serverAddress: http://prometheus-server 
    metricName: nginx_connections_active_keda 
    query: | 
      sum(avg_over_time(nginx_ingress_nginx_connections_active{app="main-nginx-ingress"}[1m])) 
    threshold: "100" 
  1. Despliega el ScaledObject:
$ kubectl apply -f 4-scaled-object.yaml scaledobject.keda.sh/nginx-scale created 

Simular un aumento repentino del tráfico y observar el efecto del escalado automático en el rendimiento

Para comprobar realmente la eficacia del escalado automático, duplica el número de conexiones con respecto al Reto 3.

  1. Vuelve al servidor de Locust en el navegador. Introduce los siguientes valores en los campos y haz clic en el botón Iniciar enjambre:
    • Número de usuarios – 2000
    • Tasa de generación – 10
    • Host – http://main-nginx-ingress
  2. Vuelve a los paneles de Prometheus y Locust. El recuadro rosa situado debajo del gráfico de Prometheus muestra cómo aumenta y disminuye el número de pods de NGINX Ingress Controller.
  3. Vuelva al terminal e inspeccione manualmente el HPA de KEDA. El campo «REPLICAS» de la salida muestra el número actual de réplicas de pods desplegadas. (La salida se distribuye en dos líneas para facilitar su lectura).
$ kubectl get hpa
NAME                  REFERENCE                      ... 
keda-hpa-nginx-scale  Deployment/main-nginx-ingress  ... 

    ... TARGETS           MINPODS   MAXPODS   REPLICAS   AGE 
    ... 101500m/100 (avg) 1         20        10         2m45s

Próximos pasos

Basar el escalado automático únicamente en el número de conexiones activas puede presentar una limitación. Si NGINX Ingress Controller llega a estar tan saturado (incluso con el escalado) que tiene que descartar conexiones, el escalador automático detecta menos conexiones activas, interpreta que las solicitudes han disminuido y reduce el número de réplicas. Esto puede empeorar el rendimiento, pero se puede evitar utilizando una combinación de métricas. Por ejemplo, nginxplus_connections_dropped (disponible con NGINX Ingress Controller basado en NGINX Plus) lleva un registro de esas conexiones de clientes descartadas.

Para probar NGINX Ingress Controller con NGINX Plus y NGINX App Protect, inicie su prueba gratuita de 30 días hoy mismo o póngase en contacto con nosotros para hablar sobre sus casos de uso.

Para probar NGINX Ingress Controller con NGINX Open Source, puede obtener el código fuente de la versión, o descargar un contenedor precompilado de DockerHub.


Compartir
Etiquetas: F5 NGINX, 2022, Tech

Artículos relacionados del blog

Únete a F5 NGINX en AppWorld 2024
NGINX | 04/01/2024

Únete a F5 NGINX en AppWorld 2024

Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
NGINX | 26/09/2023

Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source

La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.

Exposición de APIs en Kubernetes
NGINX | 10/03/2022

Exposición de APIs en Kubernetes

La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
NGINX | 23/08/2021

NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto

Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.

Presentamos NGINX Plus R22
NGINX | 09/06/2020

Presentamos NGINX Plus R22

NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.

Presentamos NGINX Plus R17
NGINX | 11/12/2018

Presentamos NGINX Plus R17

NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.