Назад | Перейти на главную страницу

Kubernetes: горизонтальное автоматическое масштабирование на основе показателей в другом пространстве имен

Я хотел бы настроить горизонтальное автоматическое масштабирование для развертывания на основе показателей входящего контроллера, развернутого в другом пространстве имен.

У меня есть развертывание (petclinic) развернутый в определенном пространстве имен (petclinic).

У меня есть входной контроллер (nginx-ingress) развернут в другом пространстве имен (nginx-ingress).

Контроллер входящего трафика был развернут с Helm и Tiller, поэтому у меня есть следующие ServiceMonitor организация:

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

У меня также есть экземпляр Prometheus Operaton, он нашел эту сущность и обновил конфигурацию Prometheus с помощью этой строфы:

- 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

У меня также есть экземпляр Prometheus-Adapter, поэтому у меня есть custom.metrics.k8s.io API в списке доступных API.

Метрики собираются и отображаются, поэтому следующая команда:

$ kubectl get --raw "/apis/custom.metrics.k8s.io/v1beta1/namespaces/nginx-ingress/ingresses/petclinic/nginx_ingress_controller_requests" | jq .

дает следующий результат:

{
  "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"
    }
  ]
}

Пока все хорошо, правда?

И мне нужно настроить объект HPA для моего развертывания. Что-то вроде этого:

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

Конечно, это неверно, так как nginx_ingress_controller_requests относится к nginx-ingress namespace, поэтому он не работает (ну, как и ожидалось):

    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"}}}

И вот что я вижу в лог-файле 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]

HPA ищет эту метрику в пространстве имен развертывания, но мне нужно, чтобы она была получена из nginx-ingress пространство имен, вот так:

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]

Увы, autoscaling/v2beta1 API не имеет spec.metrics.object.target.namespace entity, поэтому я не могу «попросить» его получить значение из другого пространства имен. :-(

Кто-нибудь будет так добр, чтобы помочь мне решить эту головоломку? Есть ли способ настроить автоматическое масштабирование на основе пользовательских показателей, принадлежащих другому пространству имен?

Может быть, есть способ сделать эту метрику доступной в том же пространстве имен, которому принадлежит это расширение ingress.extension?

Заранее благодарим за любые подсказки и советы.

Ах, я понял это. Вот часть конфигурации адаптера Prometheus, которая мне нужна:

    rules:
    - seriesQuery: '{__name__=~"^nginx_ingress_.*",namespace!=""}'
      seriesFilters: []
      resources:
        template: <<.Resource>>
        overrides:
          exported_namespace:
            resource: "namespace"
      name:
        matches: ""
        as: ""
      metricsQuery: sum(<<.Series>>{<<.LabelMatchers>>}) by (<<.GroupBy>>)

Та-да! :-)

Я бы предпочел экспортировать внешнюю метрику из prometheus, поскольку они не зависят от пространства имен.

@Volodymyr Melnyk Вам нужен адаптер Prometheus для экспорта пользовательской метрики в пространство имен petclinic, и я не вижу, чтобы это было решено в вашей конфигурации, может быть, вы также сделали другие конфигурации, о которых забыли упомянуть?