Escalonamento automático de aplicativos Kubernetes usando Prometheus e KEDA

Escalonamento automático de aplicativos Kubernetes usando Prometheus e KEDAHomem Balão por Cimuanos

A escalabilidade é um requisito fundamental para aplicativos em nuvem. Com o Kubernetes, dimensionar um aplicativo é tão simples quanto aumentar o número de réplicas para a implantação apropriada ou ReplicaSet - mas é um processo manual.

O Kubernetes permite que os aplicativos sejam dimensionados automaticamente (ou seja, pods em uma implantação ou ReplicaSet) de maneira declarativa usando a especificação Horizontal Pod Autoscaler. O critério padrão para escalabilidade automática são métricas de uso de CPU (métricas de recursos), mas você pode integrar métricas personalizadas e fornecidas externamente.

Equipe Kubernetes aaS de Mail.ru traduziu um artigo sobre como usar métricas externas para dimensionar automaticamente um aplicativo Kubernetes. Para mostrar como tudo funciona, o autor usa métricas de solicitação de acesso HTTP, que são coletadas usando o Prometheus.

Em vez do escalonamento automático horizontal de pods, é usado o Kubernetes Event Driven Autoscaling (KEDA), um operador Kubernetes de código aberto. Ele se integra nativamente ao Horizontal Pod Autoscaler para fornecer escalonamento automático contínuo (incluindo de/para zero) para cargas de trabalho orientadas por eventos. Código disponível em GitHub.

Breve visão geral do sistema

Escalonamento automático de aplicativos Kubernetes usando Prometheus e KEDA

O diagrama mostra uma breve descrição de como tudo funciona:

  1. O aplicativo fornece métricas de contagem de ocorrências HTTP no formato Prometheus.
  2. O Prometheus está configurado para coletar essas métricas.
  3. O escalonador Prometheus no KEDA é configurado para dimensionar automaticamente o aplicativo com base no número de acessos HTTP.

Agora vou contar detalhadamente sobre cada elemento.

KEDA e Prometeu

Prometheus é um kit de ferramentas de monitoramento e alerta de sistema de código aberto, parte Fundação de computação nativa em nuvem. Coleta métricas de várias fontes e as armazena como dados de série temporal. Para visualizar dados você pode usar grafana ou outras ferramentas de visualização que funcionam com a API Kubernetes.

O KEDA apoia o conceito de escalonador - ele atua como uma ponte entre o KEDA e o sistema externo. A implementação do escalonador é específica para cada sistema de destino e extrai dados dele. KEDA então os usa para controlar o dimensionamento automático.

Os escaladores oferecem suporte a várias fontes de dados, por exemplo, Kafka, Redis, Prometheus. Ou seja, o KEDA pode ser usado para dimensionar automaticamente implantações do Kubernetes usando métricas do Prometheus como critérios.

Aplicativo de teste

A aplicação de teste Golang fornece acesso via HTTP e executa duas funções importantes:

  1. Usa a biblioteca cliente Prometheus Go para instrumentar o aplicativo e fornecer a métrica http_requests, que contém uma contagem de ocorrências. O endpoint onde as métricas do Prometheus estão disponíveis está localizado no URI /metrics.
    var httpRequestsCounter = promauto.NewCounter(prometheus.CounterOpts{
           Name: "http_requests",
           Help: "number of http requests",
       })
    
  2. Em resposta a um pedido GET o aplicativo incrementa o valor da chave (access_count) no Redis. Esta é uma maneira fácil de fazer o trabalho como parte de um manipulador HTTP e também verificar as métricas do Prometheus. O valor da métrica deve ser igual ao valor access_count em 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)
       }
    

O aplicativo é implantado no Kubernetes via Deployment. Um serviço também é criado ClusterIP, permite que o servidor Prometheus obtenha métricas do aplicativo.

aqui é manifesto de implantação do aplicativo.

Servidor Prometheus

O manifesto de implantação do Prometheus consiste em:

  • ConfigMap — para transferir a configuração do Prometheus;
  • Deployment — para implantar o Prometheus em um cluster Kubernetes;
  • ClusterIP — serviço de acesso ao UI Prometheus;
  • ClusterRole, ClusterRoleBinding и ServiceAccount — para detecção automática de serviços no Kubernetes (descoberta automática).

aqui é manifesto para executar o Prometheus.

KEDA Prometheus ScaledObject

O escalonador atua como uma ponte entre o KEDA e o sistema externo do qual as métricas precisam ser obtidas. ScaledObject é um recurso customizado que precisa ser implantado para sincronizar a implantação com a origem do evento, neste caso o Prometheus.

ScaledObject contém informações de dimensionamento de implantação, metadados de origem de eventos (como segredos de conexão, nome da fila), intervalo de sondagem, período de recuperação e outros dados. Isso resulta no recurso de escalonamento automático correspondente (definição HPA) para dimensionar a implantação.

Quando um objeto ScaledObject for excluída, a definição HPA correspondente será apagada.

Aqui está a definição ScaledObject para nosso exemplo, ele usa um escalonador 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 pontos:

  1. Ele aponta para Deployment Com nome go-prom-app.
  2. Tipo de gatilho - Prometheus. O endereço do servidor Prometheus é mencionado junto com o nome da métrica, limite e Consulta PromQL, que será usado. Consulta PromQL - sum(rate(http_requests[2m])).
  3. Conforme pollingInterval,KEDA solicita um alvo do Prometheus a cada quinze segundos. Pelo menos um abaixo (minReplicaCount), e o número máximo de pods não excede maxReplicaCount (neste exemplo - dez).

Pode instalar minReplicaCount igual a zero. Nesse caso, o KEDA ativa a implantação zero para um e, em seguida, expõe o HPA para maior escalabilidade automática. A ordem inversa também é possível, ou seja, escalar de um a zero. No exemplo, não selecionamos zero porque este é um serviço HTTP e não um sistema sob demanda.

A mágica do escalonamento automático

O limite é usado como um gatilho para dimensionar a implantação. Em nosso exemplo, a consulta PromQL sum(rate (http_requests [2m])) retorna a taxa agregada de solicitações HTTP (solicitações por segundo), medida nos últimos dois minutos.

Como o valor limite é três, significa que haverá um abaixo enquanto o valor sum(rate (http_requests [2m])) menos de três. Se o valor aumentar, um sub adicional será adicionado cada vez sum(rate (http_requests [2m])) aumenta em três. Por exemplo, se o valor for de 12 a 14, o número de pods será quatro.

Agora vamos tentar configurá-lo!

predefinição

Tudo que você precisa é de um cluster Kubernetes e um utilitário configurado kubectl. Este exemplo usa um cluster minikube, mas você pode pegar qualquer outro. Para instalar um cluster existe orientar.

Instale a versão mais recente no 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/

Conjunto kubectlpara acessar o cluster Kubernetes.

Instale a versão mais recente no 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

Instalação KEDA

Você pode implantar o KEDA de diversas maneiras, elas estão listadas em documentação. Estou usando YAML monolítico:

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

KEDA e seus componentes são instalados no namespace keda. Comando para verificar:

kubectl get pods -n keda

Aguarde o operador KEDA iniciar e vá para Running State. E depois disso, continue.

Instalando Redis usando Helm

Se você não tiver o Helm instalado, use este chefia. Comando para instalar no Mac:

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

helm init inicializa a interface de linha de comando local e também instala Tiller para o cluster Kubernetes.

kubectl get pods -n kube-system | grep tiller

Aguarde até que o pod Tiller entre no estado Em execução.

Nota do tradutor: O autor usa Helm@2, que requer a instalação do componente do servidor Tiller. Agora o Helm@3 é relevante, não requer uma parte do servidor.

Após instalar o Helm, um comando é suficiente para iniciar o Redis:

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

Verifique se o Redis foi iniciado com sucesso:

kubectl get pods/redis-server-master-0

Espere o Redis entrar no estado Running.

Implantação de aplicativos

Comando de implantação:

kubectl apply -f go-app.yaml

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

Verifique se tudo começou:

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

Aguarde o Redis entrar no estado Running.

Implantando um servidor Prometheus

O manifesto do Prometheus usa Descoberta de serviço Kubernetes para Prometheus. Ele permite a descoberta dinâmica de pods de aplicativos com base no rótulo do serviço.

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

Para implantar:

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

Verifique se tudo começou:

kubectl get pods -l=app=prometheus-server

Espere que Prometheus entre em estado Running.

Usar kubectl port-forward para acessar a interface do usuário do Prometheus (ou servidor API) em http://localhost:9090.

kubectl port-forward service/prometheus-service 9090

Implantando a configuração de escalonamento automático KEDA

Comando para criar ScaledObject:

kubectl apply -f keda-prometheus-scaledobject.yaml

Verifique os registros 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 é mais ou menos assim:

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"

Verifique em aplicativos. Uma instância deve estar em execução porque minReplicaCount é igual a 1:

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

Verifique se o recurso HPA foi criado com sucesso:

kubectl get hpa

Você deverá 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

Verificação de integridade: acesso ao aplicativo

Para acessar o endpoint REST do nosso aplicativo, execute:

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

Agora você pode acessar seu aplicativo Go usando o endereço http://localhost:8080. Para fazer isso, execute o comando:

curl http://localhost:8080/test

O resultado é mais ou menos assim:

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

Neste ponto, verifique também o Redis. Você verá que a chave access_count aumentou para 1:

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

Certifique-se de que o valor da métrica seja 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

Criação de carga

Nós vamos usar ei — utilitário para geração de carga:

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

Você também pode baixar o utilitário para Linux ou Windows.

Executá-lo:

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

Por padrão, o utilitário envia 200 solicitações. Você pode verificar isso usando métricas do Prometheus e também do 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 (retornada pela 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 é exibido no campo value. Isso não é suficiente para o dimensionamento, pois o limite que definimos é 3.

Mais carga!

No novo terminal, monitore o número de pods de aplicativos:

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

Vamos aumentar a carga usando o comando:

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

Depois de um tempo, você verá o HPA dimensionando a implantação e lançando novos pods. Verifique seu HPA para ter certeza:

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 for inconsistente, a implantação será reduzida ao ponto em que apenas um pod estará em execução. Se você quiser verificar a métrica real (retornada pela consulta PromQL), use o comando:

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

Очистка

//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

Conclusão

KEDA permite escalar automaticamente suas implantações do Kubernetes (de/para zero) com base em dados de métricas externas. Por exemplo, com base nas métricas do Prometheus, comprimento da fila no Redis, latência do consumidor no tópico Kafka.

KEDA se integra a uma fonte externa e também fornece suas métricas por meio do Metrics Server para o Horizontal Pod Autoscaler.

Boa sorte!

O que mais ler:

  1. Melhores práticas e práticas recomendadas para execução de contêineres e Kubernetes em ambientes de produção.
  2. Mais de 90 ferramentas úteis para Kubernetes: implantação, gerenciamento, monitoramento, segurança e muito mais.
  3. Nosso canal em torno do Kubernetes no Telegram.

Fonte: habr.com

Adicionar um comentário