Hoje em dia é comum termos a necessidade de trabalhar com várias instâncias de um serviço para atender cargas de trabalho que em determinados momentos uma única pode não ser o suficiente.
O Kubernetes possui o componente HorizontalPodAutoscaler(HPA) que nos permite de forma automática controlar a quantidade de replicas do serviço baseado em métricas, ou seja permite definir o momento em que deve ser adicionado replicas ao seu "pool" de instâncias do seu serviço, evitando assim desperdício de recurso que seria o caso de um gerência estática.
E como podemos escalar baseado em métricas de aplicação?
Por padrão só conseguimos utilizar o HPA com métricas de CPU ou memoria, porém com o Prometheus podemos obter métricas da aplicação que por sua vez serão enviadas para a API Kubernetes.
O que iremos utilizar?
Para seguir artigo será necessário ter instalado o Helm e o nosso cluster que sugiro utilizar opções como Kind, Minikube e afin.
Instalação Prometheus Stack e Adapter
Prometheus Stack
Este é uma coleção de documentos para configuração do seu Prometheus para o Kubernetes, além de já instalar o Grafana que também sera utilizado aqui.
Primeiramente vamos criar uma namespace para nossos serviços de monitoramento
kubectl create namespace monitoring
E em seguida já podemos instalar o Prometheus Stack através do Helm
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring --set grafana.service.type=NodePort --set prometheus.service.type=NodePort
Pode ser observado que foi adicionado argumentos definindo os tipos de serviço como NodePort tendo em vista facilitar nosso acesso as interfaces fora do cluster, porém em um ambiente de produção o recomendado é utilizar Ingress.
Apos a execução dos comandos é esperado esse resultado ao listar nossos deployments
~$ kubectl get deployments -n monitoring
NAME READY UP-TO-DATE AVAILABLE AGE
prometheus-grafana 1/1 1 1 19h
prometheus-kube-prometheus-operator 1/1 1 1 19h
prometheus-kube-state-metrics 1/1 1 1 19h
Prometheus Adapter
Esse é o resposável por ser conectar ao nosso Prometheus e obter as metricas coletadas pelo mesmo e envia-las para a API Metricas do Kubernetes disponibilizando o uso das mesmas no nosso HPA.
Crie o arquivo customValues.yaml
, pois nele iremos configurar a url para nosso prometheus e configuração adicional para obter métricas requisições por segundo que iremos utilizar logo mais a frente.
prometheus:
url: "http://prometheus-kube-prometheus-prometheus"
rules:
custom:
- seriesQuery: '{container!="POD",namespace!="",pod!=""}'
resources:
template: <<.Resource>>
name:
matches: "^(.*)_seconds_count"
as: "${1}_per_second"
metricsQuery: (sum(rate(<<.Series>>{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>))
_A url do prometheus definida é baseada no DNS interno do serviço visto que o mesmo foi também na namespace monitoring _
helm install prometheus-adapter prometheus-community/prometheus-adapter -n monitoring -f customValues.yaml
Instalando nossa aplicação no cluster
Para este exemplo utilizei de uma aplicação SpringBoot+Kotlin que está disponível em GitHub.
Toda a especificação do chart dessa aplicação se encontra em /chart, que segue a seguinte estrutura:
chart/
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── serviceaccount.yaml
│ ├── servicemonitor.yaml
│ └── service.yaml
└── values.yaml
Dentre os yaml's acima o servicemonitor.yaml
é responsável por definir a captura de metricas do serviço, que no nosso caso é no path /actuator/prometheus
.
Gerando imagem aplicação
Para gerar a imagem da aplicação iremos usar o seguinte comando gradle:
gradle bootBuildImage
Após isso já teremos disponível em docker local a imagem spring-auto-scaling:0.0.1
, feito isso poderemos agora intalar nosso chart no cluster.
Instalando via Helm
helm install article chart/
Verificando estado atual do HPA
Podemos fazer isso com kubectl:
~$ kubectl get hpa
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
article-spring-auto-scaling Deployment/article-spring-auto-scaling 418m/1 1 5 1 65m
A Coluna TARGETS representa a métrica alvo, onde temos 418m(O K8's utiliza 'm' para unidades fracionarias da métrica que nesse caso seria 0,4/1) de 1 como media entre as quantidade de replicas que também se encontra em 1. A carga atual se deve ao fato de termos o Prometheus obtendo as métricas do nosso serviço através do ServiceMonitor.
Incrementando carga
Iremos executar um pod com busybox para fazer chamadas á nossa aplicação em loop, irá tentar gerando uma carga de 10 requisições por segundo.
kubectl run -i --tty load-generator --rm --image=busybox --restart=Never -- /bin/sh -c "while sleep 0.1; do wget -q -O- http://article-spring-auto-scaling/users/latest; done"
Devemos levar em conta o tempo de resposta da aplicação, pois as chamadas são sequencias e não paralelas, porém já é o suficiente para vermos funcionar.
Eventos HPA
kubectl describe hpa article-spring-auto-scaling
Como podemos para que para tentar atingir a media máxima de 1 req/s enviou eventos para aumentar o numero replicas para nosso deployment e chegou ao número de 4 replicas sendo 5 o número máximo de replicas permitidas.
Uma excelente boa prática é definição de valores limites, pois não queremos que um serviço escale infinitamente dentro nosso cluster.
Conclusão
Podemos ver que o escalonamento de automático de aplicações é grande aliado, juntamente com a possibilidade de usar métricas customizadas que podem estar bem alinhadas a necessidade do negócio.As configurações e definições de escalonamento também devem ser constantemente monitoradas e refinidas, pois os requisitos sempre mudam e afinal não existe bala de prata.
Top comments (2)
Some comments may only be visible to logged-in visitors. Sign in to view all comments.