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
O diagrama mostra uma breve descrição de como tudo funciona:
O aplicativo fornece métricas de contagem de ocorrências HTTP no formato Prometheus.
O Prometheus está configurado para coletar essas métricas.
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:
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",
})
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.
O aplicativo é implantado no Kubernetes via Deployment. Um serviço também é criado ClusterIP, permite que o servidor Prometheus obtenha métricas do aplicativo.
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:
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])).
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.
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:
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.
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:
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:
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:
//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.