Este documento descreve como ativar o dimensionamento automático de pods horizontal (HPA) para o Google Cloud Managed Service for Prometheus. Pode ativar a HPA através de uma das seguintes ações:
- Usando o KEDA (Kubernetes Event-driven Autoscaling), uma solução de código aberto que foi aprovada pela Cloud Native Computing Foundation.
- Usando a biblioteca Custom Metrics Stackdriver Adapter desenvolvida e suportada pela Google Cloud.
- Usando a biblioteca Prometheus Adapter de terceiros.
Não pode usar o adaptador do Stackdriver e o adaptador do Prometheus em conjunto no mesmo cluster porque as respetivas definições de recursos sobrepõem-se, conforme descrito na Resolução de problemas. Recomendamos que escolha apenas uma solução para HPA.
Use o KEDA
O KEDA (Kubernetes Event-driven Autoscaling) é o escalador automático lançado mais recentemente que usa métricas do Prometheus e está a tornar-se uma solução preferencial na comunidade do Prometheus.
Para começar, consulte a documentação do KEDA para integração com o Google Cloud Managed Service for Prometheus.
Use o adaptador do Stackdriver de métricas personalizadas
O adaptador do Stackdriver de métricas personalizadas suporta a consulta de métricas do Managed Service for Prometheus a partir da versão v0.13.1 do adaptador.
Para configurar um exemplo de configuração do HPA com o adaptador do Stackdriver Custom Metrics, faça o seguinte:
- Configure a coleção gerida no seu cluster.
Instale o adaptador do Stackdriver de métricas personalizadas no cluster.
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml
Implemente um exportador de métricas do Prometheus de exemplo e um recurso HPA:
kubectl apply -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/examples/prometheus-to-sd/custom-metrics-prometheus-sd.yaml
Este comando implementa uma aplicação de exportação que emite a métrica
foo
e um recurso HPA. O HPA aumenta a escala desta aplicação até 5 réplicas para alcançar o valor alvo da métricafoo
.Se usar a Workload Identity Federation para o GKE, também tem de conceder a função Leitor do Monitoring à conta de serviço na qual o adaptador é executado. Ignore este passo se não tiver a Workload Identity Federation para o GKE ativada no seu cluster do Kubernetes.
export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format 'get(projectNumber)') gcloud projects add-iam-policy-binding projects/PROJECT_ID \ --role roles/monitoring.viewer \ --member=principal://iam.googleapis.com/projects/$PROJECT_NUMBER/locations/global/workloadIdentityPools/PROJECT_ID.svc.id.goog/subject/ns/custom-metrics/sa/custom-metrics-stackdriver-adapter
Defina um recurso PodMonitoring colocando a seguinte configuração num ficheiro com o nome
podmonitoring.yaml
.apiVersion: monitoring.googleapis.com/v1 kind: PodMonitoring metadata: name: prom-example spec: selector: matchLabels: run: custom-metric-prometheus-sd endpoints: - port: 8080 interval: 30s
Implemente o novo recurso PodMonitoring:
kubectl -n default apply -f podmonitoring.yaml
Em alguns minutos, o Managed Service for Prometheus processa as métricas extraídas do exportador e armazena-as no Cloud Monitoring com um nome de formato longo. As métricas do Prometheus são armazenadas com as seguintes convenções:
- O prefixo
prometheus.googleapis.com
. - Normalmente, este sufixo é um de
gauge
,counter
,summary
ouhistogram
, embora as métricas não tipadas possam ter o sufixounknown
ouunknown:counter
. Para validar o sufixo, procure a métrica no Cloud Monitoring através do Explorador de métricas.
- O prefixo
Atualize o HPA implementado para consultar a métrica do Cloud Monitoring. A métrica
foo
é carregada comoprometheus.googleapis.com/foo/gauge
. Para tornar a métrica consultável pelo recurso HorizontalPodAutoscaler implementado, use o nome no formato longo no HPA implementado, mas tem de o modificar substituindo todas as barras invertidas (/
) pelo caráter de barra vertical (|
):prometheus.googleapis.com|foo|gauge
. Para mais informações, consulte a secção Métricas disponíveis no Stackdriver do repositório do adaptador do Stackdriver de métricas personalizadas.Atualize o HPA implementado executando o seguinte comando:
kubectl edit hpa custom-metric-prometheus-sd
Altere o valor do campo
pods.metric.name
defoo
paraprometheus.googleapis.com|foo|gauge
. A secçãospec
deve ter o seguinte aspeto:spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "20" type: AverageValue type: Pods minReplicas: 1
Neste exemplo, a configuração do HPA procura o valor médio da métrica
prometheus.googleapis.com/foo/gauge
para ser20
. Uma vez que a implementação define o valor da métrica como40
, o controlador HPA aumenta o número de pods até ao valor do campomaxReplicas
(5
) para tentar reduzir o valor médio da métrica em todos os pods para20
.A consulta HPA tem âmbito no espaço de nomes e no cluster em que o recurso HPA está instalado, pelo que as métricas idênticas noutros clusters e espaços de nomes não afetam o seu escalamento automático.
Para ver o aumento da escala da carga de trabalho, execute o seguinte comando:
kubectl get hpa custom-metric-prometheus-sd --watch
O valor do campo
REPLICAS
é alterado de1
para5
.NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/20 1 5 5 *
Para reduzir a escala da implementação, atualize o valor da métrica alvo para um valor superior ao valor da métrica exportada. Neste exemplo, a implementação define o valor da métrica
prometheus.googleapis.com/foo/gauge
como40
. Se definir o valor alvo para um número superior a40
, a implementação é reduzida.Por exemplo, use
kubectl edit
para alterar o valor do campopods.target.averageValue
na configuração da HPA de20
para100
.kubectl edit hpa custom-metric-prometheus-sd
Modifique a secção de especificações para corresponder ao seguinte:
spec: maxReplicas: 5 metrics: - pods: metric: name: prometheus.googleapis.com|foo|gauge target: averageValue: "100" type: AverageValue type: Pods minReplicas: 1
Para ver a redução da escala da carga de trabalho, execute o seguinte comando:
kubectl get hpa custom-metric-prometheus-sd --watch
O valor do campo
REPLICAS
é alterado de5
para1
. Por design, isto acontece mais lentamente do que quando aumenta o número de pods:NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE custom-metric-prometheus-sd Deployment/custom-metric-prometheus-sd 40/100 1 5 1 *
Para limpar o exemplo implementado, execute os seguintes comandos:
kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/deploy/production/adapter_new_resource_model.yaml kubectl delete -f https://raw.githubusercontent.com/GoogleCloudPlatform/k8s-stackdriver/master/custom-metrics-stackdriver-adapter/examples/prometheus-to-sd/custom-metrics-prometheus-sd.yaml kubectl delete podmonitoring/prom-example
Para mais informações, consulte o exemplo do Prometheus no repositório do adaptador do Stackdriver de métricas personalizadas ou consulte o artigo Dimensionar uma aplicação.
Use o adaptador do Prometheus
As configurações do prometheus-adapter existentes podem ser usadas para o dimensionamento automático com apenas algumas alterações. A configuração do prometheus-adapter para dimensionar através do serviço gerido para Prometheus tem duas restrições adicionais em comparação com o dimensionamento através do Prometheus a montante:
As consultas têm de ser encaminhadas através do proxy da IU do frontend do Prometheus, tal como quando consulta o serviço gerido para Prometheus através da API ou da IU do Prometheus. Para o prometheus-adapter, tem de editar a
prometheus-adapter
implementação para alterar oprometheus-url
valor da seguinte forma:--prometheus-url=http://frontend.NAMESPACE_NAME.svc:9090/
onde NAMESPACE_NAME é o espaço de nomes onde o front-end está implementado.
Não pode usar um correspondente de expressões regulares (
=~
ou!~
) num nome de métrica no campo.seriesQuery
da configuração das regras. Em alternativa, tem de especificar totalmente os nomes das métricas. Para algumas soluções alternativas, consulte o artigo Compatibilidade com PromQL.
Uma vez que os dados podem demorar um pouco mais a ficar disponíveis no Managed Service for Prometheus em comparação com o Prometheus a montante, a configuração de uma lógica de escala automática excessivamente ansiosa pode causar um comportamento indesejável. Embora não haja garantia de atualização dos dados, os dados estão normalmente disponíveis para consulta 3 a 7 segundos após serem enviados para o Managed Service for Prometheus, excluindo qualquer latência de rede.
Todas as consultas emitidas pelo prometheus-adapter têm âmbito global. Isto significa que, se tiver aplicações em dois espaços de nomes que emitem métricas com nomes idênticos, uma configuração do HPA que use essa métrica é dimensionada com base nos dados de ambas as aplicações. Recomendamos que use sempre filtros namespace
ou cluster
no seu PromQL para evitar a escalabilidade com dados incorretos.
Para configurar uma configuração de HPA de exemplo com o prometheus-adapter e a recolha gerida, siga estes passos:
- Configure a coleção gerida no seu cluster.
- Implemente o proxy da IU do frontend do Prometheus no seu cluster. Se usar a federação de identidades da carga de trabalho para o GKE, também tem de configurar e autorizar uma conta de serviço.
- Implemente os manifestos no diretório
examples/hpa/
no repositório prometheus-engine:example-app.yaml
: uma implementação e um serviço de exemplo que emitem métricas.pod-monitoring.yaml
: um recurso que configura a obtenção de métricas de exemplo.hpa.yaml
: o recurso HPA que configura o dimensionamento para a sua carga de trabalho.
Certifique-se de que o
prometheus-adapter
está instalado no seu cluster. Isto pode ser feito implementando o manifesto de instalação de exemplo no seu cluster. Este manifesto está configurado para:- Consultar um proxy de front-end implementado no espaço de nomes
default
. - Emita PromQL para calcular e devolver a métrica
http_requests_per_second
da implementação de exemplo.
- Consultar um proxy de front-end implementado no espaço de nomes
Execute os seguintes comandos, cada um numa sessão de terminal separada:
- Gere carga HTTP no serviço
prometheus-example-app
:kubectl run -i --tty load-generator --rm --image=busybox:1.28 --restart=Never -- /bin/sh -c "while sleep 0.01; do wget -q -O- http://prometheus-example-app; done"
- Monitorize o redimensionador automático horizontal de pods:
kubectl get hpa prometheus-example-app --watch
- Veja o aumento da carga de trabalho:
kubectl get po -lapp.kubernetes.io/name=prometheus-example-app --watch
- Gere carga HTTP no serviço
Pare a geração de carga HTTP com Ctrl+C e veja a carga de trabalho diminuir.
Resolução de problemas
O adaptador do Stackdriver de métricas personalizadas usa definições de recursos com os mesmos nomes que os do adaptador do Prometheus, prometheus-adapter. Esta sobreposição de nomes significa que a execução de mais do que um adaptador no mesmo cluster causa erros.
A instalação do adaptador do Prometheus num cluster que tinha anteriormente o adaptador do Stackdriver de métricas personalizadas instalado pode gerar erros, como FailedGetObjectMetric
, devido a nomes em conflito. Para resolver este problema, pode ter de eliminar os apiservices v1beta1.external.metrics.k8s.io
, v1beta1.custom.metrics.k8s.io
e v1beta2.custom.metrics.k8s.io
registados anteriormente pelo adaptador de métricas personalizadas.
Sugestões de resolução de problemas:
Algumas métricas do sistema do Cloud Monitoring, como as métricas do Pub/Sub, têm um atraso de 60 segundos ou mais. Uma vez que o adaptador do Prometheus executa consultas com a data/hora atual, a consulta destas métricas com o adaptador do Prometheus pode resultar incorretamente na ausência de dados. Para consultar métricas com atraso, use o modificador
offset
no PromQL para alterar a compensação de tempo da sua consulta pela quantidade necessária.Para verificar se o proxy da IU de front-end está a funcionar como previsto e não existem problemas com as autorizações, execute o seguinte comando num terminal:
kubectl -n NAMESPACE_NAME port-forward svc/frontend 9090
Em seguida, abra outro terminal e execute o seguinte comando:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up'
Quando o proxy da IU de front-end está a funcionar corretamente, a resposta no segundo terminal é semelhante à seguinte:
curl --silent 'localhost:9090/api/v1/series?match%5B%5D=up' | jq . { "status": "success", "data": [ ... ] }
Se receber um erro 403, significa que o proxy da IU de front-end não está configurado corretamente. Para ver informações sobre como resolver um erro 403, consulte o guia configure e autorize uma conta de serviço.
Para verificar se o apiserver de métricas personalizadas está disponível, execute o seguinte comando:
kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io
Quando o apiserver está disponível, a resposta é semelhante à seguinte:
$ kubectl get apiservices.apiregistration.k8s.io v1beta1.custom.metrics.k8s.io NAME SERVICE AVAILABLE AGE v1beta1.custom.metrics.k8s.io monitoring/prometheus-adapter True 33m
Para verificar se o HPA está a funcionar conforme esperado, execute o seguinte comando:
$ kubectl describe hpa prometheus-example-app Name: prometheus-example-app Namespace: default Labels:
Annotations: Reference: Deployment/prometheus-example-app Metrics: ( current / target ) "http_requests_per_second" on pods: 11500m / 10 Min replicas: 1 Max replicas: 10 Deployment pods: 2 current / 2 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive True ValidMetricFound the HPA was able to successfully calculate a replica count from pods metric http_requests_per_second ScalingLimited False DesiredWithinRange the desired count is within the acceptable range Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal SuccessfulRescale 47s horizontal-pod-autoscaler New size: 2; reason: pods metric http_requests_per_second above target Quando a resposta contém uma declaração como
FailedGetPodsMetric
, o HPA falha. A imagem seguinte ilustra uma resposta à chamadadescribe
quando o HPA está a falhar:$ kubectl describe hpa prometheus-example-app Name: prometheus-example-app Namespace: default Reference: Deployment/prometheus-example-app Metrics: ( current / target ) "http_requests_per_second" on pods:
/ 10 Min replicas: 1 Max replicas: 10 Deployment pods: 1 current / 1 desired Conditions: Type Status Reason Message ---- ------ ------ ------- AbleToScale True ReadyForNewScale recommended size matches current size ScalingActive False FailedGetPodsMetric the HPA was unable to compute the replica count: unable to get metric http_requests_per_second: unable to fetch metrics from custom metrics API: the server could not find the metric http_requests_per_second for pods ScalingLimited False DesiredWithinRange the desired count is within the acceptable range Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedGetPodsMetric 104s (x11 over 16m) horizontal-pod-autoscaler unable to get metric http_requests_per_second: unable to fetch metrics from custom metrics API: the server could not find the metric http_requests_per_second for pods Quando o HPA falha, certifique-se de que está a gerar métricas com o
load-generator
. Pode verificar a API de métricas personalizadas diretamente com o comando:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq .
Um resultado bem-sucedido é semelhante ao seguinte:
$ kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [ { "name": "namespaces/http_requests_per_second", "singularName": "", "namespaced": false, "kind": "MetricValueList", "verbs": [ "get" ] }, { "name": "pods/http_requests_per_second", "singularName": "", "namespaced": true, "kind": "MetricValueList", "verbs": [ "get" ] } ] }
Se não existirem métricas, não são apresentados dados em
"resources"
no resultado, por exemplo:kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/" | jq . { "kind": "APIResourceList", "apiVersion": "v1", "groupVersion": "custom.metrics.k8s.io/v1beta1", "resources": [] }