Gostaria de configurar o dimensionamento automático horizontal para uma implantação com base nas métricas do controlador de ingresso implantado em outro namespace.
Eu tenho uma implantação ( petclinic
) implantada em um determinado namespace ( petclinic
).
Eu tenho um controlador de ingresso ( nginx-ingress
) implantado em outro namespace ( nginx-ingress
).
O controlador de ingresso foi implantado com Helm e Tiller, então tenho a seguinte ServiceMonitor
entidade:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"monitoring.coreos.com/v1","kind":"ServiceMonitor","metadata":{"annotations":{},"creationTimestamp":"2019-08-19T10:48:00Z","generation":5,"labels":{"app":"nginx-ingress","chart":"nginx-ingress-1.12.1","component":"controller","heritage":"Tiller","release":"nginx-ingress"},"name":"nginx-ingress-controller","namespace":"nginx-ingress","resourceVersion":"7391237","selfLink":"/apis/monitoring.coreos.com/v1/namespaces/nginx-ingress/servicemonitors/nginx-ingress-controller","uid":"0217c466-5b78-4e38-885a-9ee65deb2dcd"},"spec":{"endpoints":[{"interval":"30s","port":"metrics"}],"namespaceSelector":{"matchNames":["nginx-ingress"]},"selector":{"matchLabels":{"app":"nginx-ingress","component":"controller","release":"nginx-ingress"}}}}
creationTimestamp: "2019-08-21T13:12:00Z"
generation: 1
labels:
app: nginx-ingress
chart: nginx-ingress-1.12.1
component: controller
heritage: Tiller
release: nginx-ingress
name: nginx-ingress-controller
namespace: nginx-ingress
resourceVersion: "7663160"
selfLink: /apis/monitoring.coreos.com/v1/namespaces/nginx-ingress/servicemonitors/nginx-ingress-controller
uid: 33421be7-108b-4b81-9673-05db140364ce
spec:
endpoints:
- interval: 30s
port: metrics
namespaceSelector:
matchNames:
- nginx-ingress
selector:
matchLabels:
app: nginx-ingress
component: controller
release: nginx-ingress
Eu também tenho a instância do Prometheus Operaton, ele encontrou essa entidade e atualizou a configuração do Prometheus com esta estrofe:
- job_name: nginx-ingress/nginx-ingress-controller/0
honor_labels: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- nginx-ingress
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_label_app
regex: nginx-ingress
- action: keep
source_labels:
- __meta_kubernetes_service_label_component
regex: controller
- action: keep
source_labels:
- __meta_kubernetes_service_label_release
regex: nginx-ingress
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: metrics
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: metrics
Também tenho uma instância do Prometheus-Adapter, então tenho a custom.metrics.k8s.io
API na lista de APIs disponíveis.
As métricas estão sendo coletadas e expostas, então o seguinte comando:
$ kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/nginx-ingress/ingresses/petclinic/nginx_ingress_controller_requests" | jq .
dá o seguinte resultado:
{
"kind": "MetricValueList",
"apiVersion": "custom.metrics.k8s.io/v1beta1",
"metadata": {
"selfLink": "/apis/custom.metrics.k8s.io/v1beta1/namespaces/nginx-ingress/ingresses/petclinic/nginx_ingress_controller_requests"
},
"items": [
{
"describedObject": {
"kind": "Ingress",
"namespace": "nginx-ingress",
"name": "petclinic",
"apiVersion": "extensions/v1beta1"
},
"metricName": "nginx_ingress_controller_requests",
"timestamp": "2019-08-20T12:56:50Z",
"value": "11"
}
]
}
Até aí tudo bem, certo?
E o que eu preciso é configurar a entidade HPA para minha implantação. Fazendo algo assim:
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
name: petclinic
namespace: petclinic
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: petclinic
minReplicas: 1
maxReplicas: 10
metrics:
- type: Object
object:
metricName: nginx_ingress_controller_requests
target:
apiVersion: extensions/v1beta1
kind: Ingress
name: petclinic
targetValue: 10k
Claro, isso está incorreto, pois nginx_ingress_controller_requests
está relacionado ao nginx-ingress
namespace, então não funciona (bem, como era esperado):
annotations:
autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2019-08-19T18:43:42Z","reason":"SucceededGetScale","message":"the
HPA controller was able to get the target''s current scale"},{"type":"ScalingActive","status":"False","lastTransitionTime":"2019-08-19T18:55:26Z","reason":"FailedGetObjectMetric","message":"the
HPA was unable to compute the replica count: unable to get metric nginx_ingress_controller_requests:
Ingress on petclinic petclinic/unable to fetch metrics
from custom metrics API: the server could not find the metric nginx_ingress_controller_requests
for ingresses.extensions petclinic"},{"type":"ScalingLimited","status":"False","lastTransitionTime":"2019-08-19T18:43:42Z","reason":"DesiredWithinRange","message":"the
desired count is within the acceptable range"}]'
autoscaling.alpha.kubernetes.io/current-metrics: '[{"type":""},{"type":"Resource","resource":{"name":"cpu","currentAverageUtilization":1,"currentAverageValue":"10m"}}]'
autoscaling.alpha.kubernetes.io/metrics: '[{"type":"Object","object":{"target":{"kind":"Ingress","name":"petclinic","apiVersion":"extensions/v1beta1"},"metricName":"nginx_ingress_controller_requests","targetValue":"10k"}}]'
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"autoscaling/v2beta1","kind":"HorizontalPodAutoscaler","metadata":{"annotations":{},"name":"petclinic","namespace":"petclinic"},"spec":{"maxReplicas":10,"metrics":[{"object":{"metricName":"nginx_ingress_controller_requests","target":{"apiVersion":"extensions/v1beta1","kind":"Ingress","name":"petclinic"},"targetValue":"10k"},"type":"Object"}],"minReplicas":1,"scaleTargetRef":{"apiVersion":"apps/v1","kind":"Deployment","name":"petclinic"}}}
E aqui está o que vejo no arquivo de log do Prometheus-Adapter:
I0820 15:42:13.467236 1 wrap.go:42] GET /apis/custom.metrics.k8s.io/v1beta1/namespaces/petclinic/ingresses.extensions/petclinic/nginx_ingress_controller_requests: (6.124398ms) 404 [[kube-controller-manager/v1.15.1 (linux/amd64) kubernetes/4485c6f/system:serviceaccount:kube-system:horizontal-pod-autoscaler] 10.103.98.0:37940]
O HPA procura essa métrica no namespace da implantação, mas preciso buscá-la no nginx-ingress
namespace, assim:
I0820 15:44:40.044797 1 wrap.go:42] GET /apis/custom.metrics.k8s.io/v1beta1/namespaces/nginx-ingress/ingresses/petclinic/nginx_ingress_controller_requests: (2.210282ms) 200 [[kubectl/v1.15.2 (linux/amd64) kubernetes/f627830] 10.103.97.0:35142]
Infelizmente, a autoscaling/v2beta1
API não tem a spec.metrics.object.target.namespace
entidade, então não posso "pedir" para buscar o valor de outro namespace. :-(
Alguém teria a gentileza de me ajudar a resolver esse quebra-cabeça? Existe uma maneira de configurar o dimensionamento automático com base nas métricas personalizadas que pertencem a outro namespace?
Talvez haja uma maneira de disponibilizar essa métrica no mesmo namespace ao qual essa ingress.extension pertence?
Desde já agradeço por quaisquer pistas e dicas.
Ah, eu descobri. Aqui está a parte da configuração do adaptador prometheus que eu precisava:
Ta-da! :-)
Minha escolha seria exportar uma métrica externa do prometheus, pois elas não são dependentes de namespace.
@Volodymyr Melnyk Você precisa do adaptador prometheus para exportar a métrica personalizada para o namespace petclinic, e não vejo isso sendo resolvido em sua configuração, talvez você também tenha feito outras configurações que esqueceu de mencionar?