Autoescalado de aplicacións Kubernetes usando Prometheus e KEDA

Autoescalado de aplicacións Kubernetes usando Prometheus e KEDABalloon Man de Cimuanos

A escalabilidade é un requisito fundamental para as aplicacións na nube. Con Kubernetes, escalar unha aplicación é tan sinxelo como aumentar o número de réplicas para a implantación adecuada ou ReplicaSet - pero é un proceso manual.

Kubernetes permite que as aplicacións se escalan automaticamente (por exemplo, pods nunha implementación ou ReplicaSet) de forma declarativa utilizando a especificación Horizontal Pod Autoscaler. O criterio predeterminado para a escala automática son as métricas de uso da CPU (métricas de recursos), pero podes integrar métricas personalizadas e proporcionadas externamente.

Equipo Kubernetes aaS de Mail.ru traduciu un artigo sobre como usar métricas externas para escalar automaticamente unha aplicación de Kubernetes. Para mostrar como funciona todo, o autor usa métricas de solicitude de acceso HTTP, que se recollen mediante Prometheus.

En lugar da escala automática horizontal dos pods, utilízase Kubernetes Event Driven Autoscaling (KEDA), un operador de Kubernetes de código aberto. Intégrase de forma nativa co Horizontal Pod Autoscaler para proporcionar un autoescalado continuo (incluíndo a/desde cero) para cargas de traballo dirixidas por eventos. Código dispoñible en GitHub.

Breve descrición do sistema

Autoescalado de aplicacións Kubernetes usando Prometheus e KEDA

O diagrama mostra unha breve descrición de como funciona todo:

  1. A aplicación ofrece métricas de conta de accesos HTTP en formato Prometheus.
  2. Prometheus está configurado para recoller estas métricas.
  3. O escalador de Prometheus en KEDA está configurado para escalar automaticamente a aplicación en función do número de accesos HTTP.

Agora vouvos falar en detalle de cada elemento.

KEDA e Prometeo

Prometheus é un conxunto de ferramentas de monitorización e alerta de sistemas de código aberto, parte Fundación Cloud Native Computing. Recopila métricas de varias fontes e gárdaas como datos de series temporais. Para visualizar os datos pode usar grafana ou outras ferramentas de visualización que funcionen coa API de Kubernetes.

KEDA admite o concepto de escalador: actúa como ponte entre KEDA e o sistema externo. A implementación do escalador é específica para cada sistema obxectivo e extrae datos del. A continuación, KEDA utilízaos para controlar a escala automática.

Os escaladores admiten varias fontes de datos, por exemplo, Kafka, Redis, Prometheus. É dicir, KEDA pódese usar para escalar automaticamente as implantacións de Kubernetes usando as métricas de Prometheus como criterios.

Aplicación de proba

A aplicación de proba Golang proporciona acceso vía HTTP e realiza dúas funcións importantes:

  1. Usa a biblioteca cliente de Prometheus Go para instrumentar a aplicación e proporcionar a métrica http_requests, que contén un reconto de acertos. O punto final onde están dispoñibles as métricas de Prometheus está situado no URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. En resposta a unha solicitude GET a aplicación aumenta o valor da chave (access_count) en Redis. Este é un xeito sinxelo de facer o traballo como parte dun manejador HTTP e tamén de comprobar as métricas de Prometheus. O valor da métrica debe ser o mesmo que o 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)
       }
    

A aplicación está implantada en Kubernetes mediante Deployment. Tamén se crea un servizo ClusterIP, permite ao servidor Prometheus obter métricas da aplicación.

Aquí manifesto de implantación da aplicación.

Servidor Prometheus

O manifesto de implantación de Prometheus consta de:

  • ConfigMap — para transferir a configuración de Prometheus;
  • Deployment — para implementar Prometheus nun clúster de Kubernetes;
  • ClusterIP — servizo de acceso á IU Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — para a detección automática de servizos en Kubernetes (descubrimento automático).

Aquí manifesto para executar Prometheus.

KEDA Prometheus ScaledObject

O escalador actúa como ponte entre KEDA e o sistema externo do que se deben obter as métricas. ScaledObject é un recurso personalizado que é necesario despregar para sincronizar a implantación coa fonte do evento, neste caso Prometheus.

ScaledObject contén información de escala de implantación, metadatos da fonte de eventos (como segredos de conexión, nome da cola), intervalo de sondeo, período de recuperación e outros datos. Dá como resultado o recurso de escalado automático correspondente (definición HPA) para escalar a implantación.

Cando un obxecto ScaledObject se elimina, borra a definición HPA correspondente.

Aquí está a definición ScaledObject para o noso exemplo, usa 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]))

Considere os seguintes puntos:

  1. El sinala Deployment Con nome go-prom-app.
  2. Tipo de disparador - Prometheus. Menciónase o enderezo do servidor Prometheus xunto co nome da métrica, o limiar e Consulta PromQL, que se utilizará. Consulta PromQL - sum(rate(http_requests[2m])).
  3. Conforme pollingInterval,KEDA solicita un obxectivo a Prometheus cada quince segundos. Polo menos un baixo (minReplicaCount), e o número máximo de vainas non supera maxReplicaCount (neste exemplo - dez).

Pódese instalar minReplicaCount igual a cero. Neste caso, KEDA activa o despregamento cero a un e despois expón o HPA para un maior escalado automático. Tamén é posible a orde inversa, é dicir, escalar de un a cero. No exemplo, non seleccionamos cero porque se trata dun servizo HTTP e non dun sistema baixo demanda.

A maxia dentro do autoscaling

O limiar úsase como disparador para escalar a implantación. No noso exemplo, a consulta PromQL sum(rate (http_requests [2m])) devolve a taxa de solicitude HTTP agregada (solicitudes por segundo), medida nos últimos dous minutos.

Dado que o valor límite é tres, significa que haberá un por debaixo do valor sum(rate (http_requests [2m])) menos de tres. Se o valor aumenta, engádese un sub adicional cada vez sum(rate (http_requests [2m])) aumenta en tres. Por exemplo, se o valor é de 12 a 14, entón o número de pods é catro.

Agora imos tentar configuralo!

Configuración previa

Todo o que necesitas é un clúster de Kubernetes e unha utilidade configurada kubectl. Este exemplo usa un clúster minikube, pero podes levar calquera outro. Para instalar un clúster hai liderado.

Instala a ú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/

Conxunto kubectlpara acceder ao clúster de Kubernetes.

Instala a ú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

Podes implementar KEDA de varias maneiras, están listados en documentación. Estou usando YAML monolítico:

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

KEDA e os seus compoñentes instálanse no espazo de nomes keda. Comando para comprobar:

kubectl get pods -n keda

Agarde a que se inicie o operador KEDA e vaia a Running State. E despois diso, continúa.

Instalando Redis usando Helm

Se non tes Helm instalado, úsao liderado. Comando para instalar en Mac:

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

helm init inicializa a interface de liña de comandos local e tamén instala Tiller ao clúster de Kubernetes.

kubectl get pods -n kube-system | grep tiller

Agarde a que o tiller pod entre no estado de execución.

Nota do tradutor: O autor usa Helm@2, que require a instalación do compoñente do servidor Tiller. Agora Helm@3 é relevante, non require unha parte do servidor.

Despois de instalar Helm, un comando é suficiente para iniciar Redis:

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

Verifique que Redis comezou correctamente:

kubectl get pods/redis-server-master-0

Agarda a que Redis entre en estado Running.

Implantación de aplicacións

Comando de implantación:

kubectl apply -f go-app.yaml

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

Comproba que todo comezou:

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

Agarda a que Redis entre en estado Running.

Implementación dun servidor Prometheus

O manifesto de Prometeo utiliza Kubernetes Service Discovery para Prometheus. Permite o descubrimento dinámico de módulos de aplicacións en función da etiqueta do servizo.

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

Para implementar:

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

Comproba que todo comezou:

kubectl get pods -l=app=prometheus-server

Agarda a que Prometeo entre en estado Running.

Usar kubectl port-forward para acceder á interface de usuario de Prometheus (ou ao servidor API) en http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Implementando a configuración de escalado automático de KEDA

Comando para crear ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Comprobe os rexistros do operador KEDA:

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

O resultado parece algo así:

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"

Consulta nas aplicacións. Debe estar executando unha instancia porque minReplicaCount é igual a 1:

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

Verifique que o recurso HPA se creou correctamente:

kubectl get hpa

Deberías ver algo así como:

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

Verificación de saúde: acceso á aplicación

Para acceder ao punto final REST da nosa aplicación, executa:

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

Agora podes acceder á túa aplicación Go usando o enderezo http://localhost:8080. Para facelo, execute o comando:

curl http://localhost:8080/test

O resultado parece algo así:

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

Neste punto tamén comprobe Redis. Verás que a clave access_count aumentado a 1:

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

Asegúrese de que o valor da métrica é http_requests o mesmo:

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 ei - Utilidade para xerar carga:

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

Tamén podes descargar a utilidade para Linux ou Windows.

Execútalo:

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

Por defecto, a utilidade envía 200 solicitudes. Podes verificalo usando as métricas de Prometheus e 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 o valor da métrica real (devolta pola 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"]}]}}

Neste caso o resultado real é 1,686057971014493 e móstrase no campo value. Isto non é suficiente para escalar, xa que o limiar que establecemos é 3.

Máis carga!

No novo terminal, supervisa o número de módulos de aplicacións:

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

Aumentemos a carga usando o comando:

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

Despois dun tempo, verás que HPA escala a implantación e lanza novos pods. Comprobe o seu 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

Se a carga é inconsistente, o despregamento reducirase ata o punto no que só se está a executar un pod. Se desexa comprobar a métrica real (devolta pola consulta PromQL), use o comando:

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

Limpeza

//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 permíteche escalar automaticamente as túas implementacións de Kubernetes (desde e ata cero) en función de datos de métricas externas. Por exemplo, en función das métricas de Prometheus, a lonxitude da cola en Redis, a latencia do consumidor no tema de Kafka.

KEDA intégrase cunha fonte externa e tamén proporciona as súas métricas a través do servidor de métricas ao Horizontal Pod Autoscaler.

Boa sorte!

Que máis ler:

  1. Mellores prácticas e boas prácticas para executar contedores e Kubernetes en entornos de produción.
  2. Máis de 90 ferramentas útiles para Kubernetes: implantación, xestión, vixilancia, seguridade e moito máis.
  3. A nosa canle En torno a Kubernetes en Telegram.

Fonte: www.habr.com

Engadir un comentario