Escalado automático de aplicaciones Kubernetes usando Prometheus y KEDA

Escalado automático de aplicaciones Kubernetes usando Prometheus y KEDAHombre Globo de Cimuanos

La escalabilidad es un requisito clave para las aplicaciones en la nube. Con Kubernetes, escalar una aplicación es tan simple como aumentar la cantidad de réplicas para la implementación adecuada o ReplicaSet - pero es un proceso manual.

Kubernetes permite escalar automáticamente las aplicaciones (es decir, pods en una implementación o ReplicaSet) de forma declarativa utilizando la especificación Horizontal Pod Autoscaler. El criterio predeterminado para el escalado automático son las métricas de uso de CPU (métricas de recursos), pero puede integrar métricas personalizadas y proporcionadas externamente.

Equipo Kubernetes aaS de Mail.ru tradujo un artículo sobre cómo utilizar métricas externas para escalar automáticamente una aplicación Kubernetes. Para mostrar cómo funciona todo, el autor utiliza métricas de solicitud de acceso HTTP, que se recopilan mediante Prometheus.

En lugar del escalado automático horizontal de pods, se utiliza Kubernetes Event Driven Autoscaling (KEDA), un operador de Kubernetes de código abierto. Se integra de forma nativa con Horizontal Pod Autoscaler para proporcionar un escalado automático fluido (incluso hacia/desde cero) para cargas de trabajo basadas en eventos. Código disponible en GitHub.

Breve descripción general del sistema.

Escalado automático de aplicaciones Kubernetes usando Prometheus y KEDA

El diagrama muestra una breve descripción de cómo funciona todo:

  1. La aplicación proporciona métricas de recuento de visitas HTTP en formato Prometheus.
  2. Prometheus está configurado para recopilar estas métricas.
  3. El escalador de Prometheus en KEDA está configurado para escalar automáticamente la aplicación en función del número de visitas HTTP.

Ahora te contaré en detalle sobre cada elemento.

KEDA y Prometeo

Prometheus es un conjunto de herramientas de alerta y monitoreo de sistemas de código abierto, parte Fundación de computación nativa de la nube. Recopila métricas de diversas fuentes y las almacena como datos de series temporales. Para visualizar datos puedes utilizar Grafana u otras herramientas de visualización que funcionan con la API de Kubernetes.

KEDA apoya el concepto de escalador: actúa como puente entre KEDA y el sistema externo. La implementación del escalador es específica de cada sistema de destino y extrae datos de él. Luego, KEDA los utiliza para controlar el escalado automático.

Los escaladores admiten múltiples fuentes de datos, por ejemplo, Kafka, Redis, Prometheus. Es decir, KEDA se puede utilizar para escalar automáticamente las implementaciones de Kubernetes utilizando las métricas de Prometheus como criterio.

Aplicación de prueba

La aplicación de prueba Golang proporciona acceso a través de HTTP y realiza dos funciones importantes:

  1. Utiliza la biblioteca cliente de Prometheus Go para instrumentar la aplicación y proporcionar la métrica http_requests, que contiene un recuento de visitas. El punto final donde están disponibles las métricas de Prometheus se encuentra en el URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. En respuesta a una solicitud GET la aplicación incrementa el valor de la clave (access_count) en Redis. Esta es una manera fácil de hacer el trabajo como parte de un controlador HTTP y también verificar las métricas de Prometheus. El valor de la métrica debe ser el mismo que el valor. access_count en Redis.
    func main() {
           http.Handle("/metrics", promhttp.Handler())
           http.HandleFunc("/test", func(w http.ResponseWriter, r 
    *http.Request) {
               defer httpRequestsCounter.Inc()
               count, err := client.Incr(redisCounterName).Result()
               if err != nil {
                   fmt.Println("Unable to increment redis counter", err)
                   os.Exit(1)
               }
               resp := "Accessed on " + time.Now().String() + "nAccess count " + strconv.Itoa(int(count))
               w.Write([]byte(resp))
           })
           http.ListenAndServe(":8080", nil)
       }
    

La aplicación se implementa en Kubernetes a través de Deployment. También se crea un servicio. ClusterIP, permite al servidor Prometheus obtener métricas de la aplicación.

aquí está manifiesto de implementación para la aplicación.

Servidor Prometeo

El manifiesto de implementación de Prometheus consta de:

  • ConfigMap — para transferir la configuración de Prometheus;
  • Deployment — para implementar Prometheus en un clúster de Kubernetes;
  • ClusterIP — servicio de acceso a UI Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — para la detección automática de servicios en Kubernetes (descubrimiento automático).

aquí está manifiesto para ejecutar Prometheus.

Objeto escalado KEDA Prometheus

El escalador actúa como un puente entre KEDA y el sistema externo del cual se deben obtener las métricas. ScaledObject es un recurso personalizado que debe implementarse para sincronizar la implementación con el origen del evento, en este caso Prometheus.

ScaledObject contiene información de escala de implementación, metadatos de origen de eventos (como secretos de conexión, nombre de cola), intervalo de sondeo, período de recuperación y otros datos. Da como resultado el recurso de escalado automático correspondiente (definición de HPA) para escalar la implementación.

Cuando un objeto ScaledObject se elimina, se borra la definición HPA correspondiente.

Aquí está la definición ScaledObject para nuestro ejemplo, utiliza un escalador Prometheus:

apiVersion: keda.k8s.io/v1alpha1
kind: ScaledObject
metadata:
 name: prometheus-scaledobject
 namespace: default
 labels:
   deploymentName: go-prom-app
spec:
 scaleTargetRef:
   deploymentName: go-prom-app
 pollingInterval: 15
 cooldownPeriod:  30
 minReplicaCount: 1
 maxReplicaCount: 10
 triggers:
 - type: prometheus
   metadata:
     serverAddress: 
http://prometheus-service.default.svc.cluster.local:9090
     metricName: access_frequency
     threshold: '3'
     query: sum(rate(http_requests[2m]))

Tenga en cuenta los siguientes puntos:

  1. el apunta a Deployment Con nombre go-prom-app.
  2. Tipo de disparador - Prometheus. La dirección del servidor Prometheus se menciona junto con el nombre de la métrica, el umbral y consulta PromQL, que será utilizado. Consulta PromQL - sum(rate(http_requests[2m])).
  3. según pollingIntervalKEDA solicita un objetivo a Prometheus cada quince segundos. Al menos uno menos (minReplicaCount), y el número máximo de vainas no excede maxReplicaCount (en este ejemplo, diez).

puede instalar minReplicaCount igual a cero. En este caso, KEDA activa la implementación de cero a uno y luego expone el HPA para un mayor escalamiento automático. También es posible el orden inverso, es decir, escalar de uno a cero. En el ejemplo, no seleccionamos cero porque se trata de un servicio HTTP y no de un sistema bajo demanda.

La magia dentro del autoescalado

El umbral se utiliza como disparador para escalar la implementación. En nuestro ejemplo, la consulta PromQL sum(rate (http_requests [2m])) devuelve la tasa de solicitudes HTTP agregada (solicitudes por segundo), medida durante los últimos dos minutos.

Dado que el valor umbral es tres, significa que habrá uno por debajo mientras el valor sum(rate (http_requests [2m])) menos que tres. Si el valor aumenta, se agrega un sub adicional cada vez sum(rate (http_requests [2m])) aumenta en tres. Por ejemplo, si el valor es de 12 a 14, entonces el número de pods es cuatro.

¡Ahora intentemos configurarlo!

Preajuste

Todo lo que necesitas es un clúster de Kubernetes y una utilidad configurada. kubectl. Este ejemplo utiliza un clúster minikube, pero puedes tomar cualquier otro. Para instalar un cluster hay руководство.

Instale la última versión en Mac:

curl -Lo minikube 
https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 
&& chmod +x minikube
sudo mkdir -p /usr/local/bin/
sudo install minikube /usr/local/bin/

Establecer kubectlpara acceder al clúster de Kubernetes.

Instale la última versión en Mac:

curl -LO 
"https://storage.googleapis.com/kubernetes-release/release/$(curl -s
https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
kubectl version

Instalación KEDA

Puede implementar KEDA de varias maneras, se enumeran en documentación. Estoy usando YAML monolítico:

kubectl apply -f
https://raw.githubusercontent.com/kedacore/keda/master/deploy/KedaScaleController.yaml

KEDA y sus componentes están instalados en el espacio de nombres. keda. Comando para comprobar:

kubectl get pods -n keda

Espere a que se inicie KEDA Operador y vaya a Running State. Y después de eso, continúa.

Instalación de Redis usando Helm

Si no tienes Helm instalado, usa este liderazgo. Comando para instalar en Mac:

brew install kubernetes-helm
helm init --history-max 200

helm init inicializa la interfaz de línea de comando local y también instala Tiller al clúster de Kubernetes.

kubectl get pods -n kube-system | grep tiller

Espere a que el módulo Tiller entre en estado En ejecución.

Nota del traductor: El autor utiliza Helm@2, que requiere la instalación del componente del servidor Tiller. Ahora Helm@3 es relevante, no requiere una parte del servidor.

Después de instalar Helm, un comando es suficiente para iniciar Redis:

helm install --name redis-server --set cluster.enabled=false --set 
usePassword=false stable/redis

Verifique que Redis se haya iniciado exitosamente:

kubectl get pods/redis-server-master-0

Espere a que Redis entre en estado Running.

Implementación de aplicaciones

Comando de implementación:

kubectl apply -f go-app.yaml

//output
deployment.apps/go-prom-app created
service/go-prom-app-service created

Comprueba que todo ha comenzado:

kubectl get pods -l=app=go-prom-app

Espere a que Redis entre en estado Running.

Implementación de un servidor Prometheus

El manifiesto de Prometheus utiliza Descubrimiento del servicio Kubernetes para Prometheus. Permite el descubrimiento dinámico de pods de aplicaciones según la etiqueta de servicio.

kubernetes_sd_configs:
   - role: service
   relabel_configs:
   - source_labels: [__meta_kubernetes_service_label_run]
     regex: go-prom-app-service
     action: keep

Desplegar:

kubectl apply -f prometheus.yaml

//output
clusterrole.rbac.authorization.k8s.io/prometheus created
serviceaccount/default configured
clusterrolebinding.rbac.authorization.k8s.io/prometheus created
configmap/prom-conf created
deployment.extensions/prometheus-deployment created
service/prometheus-service created

Comprueba que todo ha comenzado:

kubectl get pods -l=app=prometheus-server

Espere a que Prometheus entre en estado Running.

uso kubectl port-forward para acceder a la interfaz de usuario de Prometheus (o servidor API) en http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Implementación de la configuración de escalado automático de KEDA

comando para crear ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Consulte los registros del operador de KEDA:

KEDA_POD_NAME=$(kubectl get pods -n keda 
-o=jsonpath='{.items[0].metadata.name}')
kubectl logs $KEDA_POD_NAME -n keda

El resultado se parece a esto:

time="2019-10-15T09:38:28Z" level=info msg="Watching ScaledObject:
default/prometheus-scaledobject"
time="2019-10-15T09:38:28Z" level=info msg="Created HPA with 
namespace default and name keda-hpa-go-prom-app"

Consulte en aplicaciones. Una instancia debe estar ejecutándose porque minReplicaCount es igual a 1:

kubectl get pods -l=app=go-prom-app

Verifique que el recurso HPA se haya creado correctamente:

kubectl get hpa

Deberías ver algo como:

NAME                   REFERENCE                TARGETS     MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   0/3 (avg)   1         10        1          45s

Control de salud: acceso a la aplicación

Para acceder al punto final REST de nuestra aplicación, ejecute:

kubectl port-forward service/go-prom-app-service 8080

Ahora puede acceder a su aplicación Go usando la dirección http://localhost:8080. Para hacer esto, ejecute el comando:

curl http://localhost:8080/test

El resultado se parece a esto:

Accessed on 2019-10-21 11:29:10.560385986 +0000 UTC 
m=+406004.817901246
Access count 1

En este punto, consulte también Redis. Verás que la clave access_count aumentado a 1:

kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
"1"

Asegúrese de que el valor de la métrica sea http_requests lo mismo:

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 1

Creación de carga

Usaremos hey — utilidad para generar carga:

curl -o hey https://storage.googleapis.com/hey-release/hey_darwin_amd64 
&& chmod a+x hey

También puedes descargar la utilidad para Linux o Windows.

Ejecutarlo:

./hey http://localhost:8080/test

De forma predeterminada, la utilidad envía 200 solicitudes. Puede verificar esto utilizando las métricas de Prometheus y Redis.

curl http://localhost:8080/metrics | grep http_requests
//output
# HELP http_requests number of http requests
# TYPE http_requests counter
http_requests 201
kubectl exec -it redis-server-master-0 -- redis-cli get access_count
//output
201

Valide el valor de la métrica real (devuelta por la consulta PromQL):

curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'
//output
{"status":"success","data":{"resultType":"vector","result":[{"metric":{},"value":[1571734214.228,"1.686057971014493"]}]}}

En este caso el resultado real es 1,686057971014493 y se muestra en el campo value. Esto no es suficiente para escalar, ya que el umbral que establecemos es 3.

¡Más carga!

En la nueva terminal, controle la cantidad de pods de aplicaciones:

kubectl get pods -l=app=go-prom-app -w

Aumentemos la carga usando el comando:

./hey -n 2000 http://localhost:8080/test

Después de un tiempo, verá que HPA escala la implementación y lanza nuevos pods. Verifique su HPA para asegurarse de:

kubectl get hpa
NAME                   REFERENCE                TARGETS         MINPODS   MAXPODS   REPLICAS   AGE
keda-hpa-go-prom-app   Deployment/go-prom-app   1830m/3 (avg)   1         10        6          4m22s

Si la carga es inconsistente, la implementación se reducirá hasta el punto en que solo se esté ejecutando un pod. Si desea verificar la métrica real (devuelta por la consulta PromQL), use el comando:

curl -g 
'http://localhost:9090/api/v1/query?query=sum(rate(http_requests[2m]))'

limpieza

//Delete KEDA
kubectl delete namespace keda
//Delete the app, Prometheus server and KEDA scaled object
kubectl delete -f .
//Delete Redis
helm del --purge redis-server

Conclusión

KEDA le permite escalar automáticamente sus implementaciones de Kubernetes (hacia/desde cero) en función de datos de métricas externas. Por ejemplo, según las métricas de Prometheus, la longitud de la cola en Redis y la latencia del consumidor en el tema Kafka.

KEDA se integra con una fuente externa y también proporciona sus métricas a través de Metrics Server al Horizontal Pod Autoscaler.

¡Buena suerte!

Qué más leer:

  1. Mejores prácticas y mejores prácticas para ejecutar contenedores y Kubernetes en entornos de producción.
  2. Más de 90 herramientas útiles para Kubernetes: implementación, administración, monitoreo, seguridad y más.
  3. Nuestro canal Around Kubernetes en Telegram.

Fuente: habr.com

Añadir un comentario