Инструменты Prometheus#

Prometheus#

Prometheus - это инструмент для мониторинга и оповещения систем. Prometheus собирает и хранит свои метрики в виде данных временных рядов, то есть информация о метриках хранится с меткой времени, на которой она была записана, наряду с необязательными парами ключ-значение, называемыми метками.

Общий принцип работы Prometheus:

  1. Prometheus читает секцию конфигурационного файла scrape_configs, согласно которой настраивает свой внутренний механизм Service Discovery (обнаружения сервисов).

  2. Для каждой target (цели мониторинга), каждый scrape_interval (частота опрашивания цели мониторинга), выполняется HTTP-запрос к этой цели. В ответ получаются метрики в своем формате, которые сохраняются в базу.

  3. Каждый evaluation_interval (оценка запроса для оповещения) обрабатываются правила, на основании которых:

    • или отправляются alerts (оповещения);

    • или записываются новые метрики (результат выполнения правила).

  4. Механизм Service Discovery взаимодействует с DropApp API (в основном для получения endpoints).

  5. Механизм Service Discovery обновляет targets (список целей).

Prometheus-operator автоматически обнаруживает изменения на сервере API DropApp в любом из вышеперечисленных объектов и обеспечивает синхронизацию сопоставления развертываний и конфигураций.

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

Имя метрики указывает на основной измеряемый показатель системы. Например, http_requests_total - итоговое число полученных запросов HTTP.

Имя метрики может содержать символы ASCII, цифры, подчеркивания и двоеточия. Проверку имени метрики можно выполнить с помощью регулярного выражения [a-zA-Z_:][a-zA-Z0-9_:]*.

Примечание

Двоеточие зарезервировано для пользовательских правил записи. Они не должны использоваться экспортерами или другими инструментами.

Метки позволяют использовать размерную модель данных Prometheus: любая заданная комбинация меток для одного и того же имени метрики идентифицирует конкретный размерный экземпляр этой метрики.

Например: все HTTP-запросы, в которых использовался метод POST, отправляются в обработчик /api/tracks. Язык запросов позволяет выполнять фильтрацию и агрегирование на основе этих измерений. Изменение любого значения метки, включая добавление или удаление метки, создаст новый временной ряд.

Имя метки может содержать символы ASCII, цифры и подчеркивания. Имена меток с двойным подчеркиванием (_name_) зарезервированы для внутреннего использования. Проверку имени метки можно выполнить с помощью регулярного выражения [a-zA-Z_][a-zA-Z0-9_]*. Значения меток могут содержать любые символы Unicode. Метка с пустым значением считается эквивалентной несуществующей метке.

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

Конфигурация Prometheus#

У сервера Prometheus есть config (конфигурационный файл) и rule files (файлы с правилами).

В config имеются следующие секции:

  • scrape_configs — настройки поиска целей для мониторинга;

  • rule_files — список директорий с правилами, которые необходимо загрузить;

  • alerting — настройки поиска Prometheus-alertmanager, в которые отправляются alerts (оповещения). Результатом работы является список endpoints, в которые Prometheus будет отправлять предупреждения.

Пример scrape_configs:

scrape_configs.yaml
scrape_configs:
  # Общие настройки
- job_name: kube-prometheus/custom/0    # Название scrape job
                                        # Показывается в разделе Service Discovery
  scrape_interval: 30s                  # Частота сбора данных в секундах
  scrape_timeout: 10s                   # Таймаут в секундах на запрос
  metrics_path: /metrics                # Путь к метрикам
  scheme: http                          # Выбор типа соединения, доступные значения `http` или `https`

  # Настройки Service Discovery
  kubernetes_sd_configs:                
  - api_server: null                    # Использовать адрес API-сервера из переменных
                                        # Окружение (которые есть в каждом pod)
    role: endpoints                     # Источник targets  (endpoints)
    namespaces:
      names:                            # Поиск endpoints в указанных namespaces
      - alice
      - bob

  # Настройки фильтрации enpoints и relabel 
  # Перечень меток для всех получаемых метрик
  relabel_configs:
  # Фильтр по значению метки prometheus_custom_target,
  # полученного из service, связанного с endpoint
  - source_labels: [__meta_kubernetes_service_label_prometheus_custom_target]
    regex: .+                           # Может использоваться любая не пустая метка
    action: keep
    
  # Фильтр по имени порта
  - source_labels: [__meta_kubernetes_endpoint_port_name]
    regex: http-metrics                 # Для имени порта http-metrics
    action: keep
    
  - source_labels: [__meta_kubernetes_service_label_prometheus_custom_target]
    regex: (.*)
    target_label: job
    replacement: custom-$1
    action: replace
    
  # Метка namespace
  - source_labels: [__meta_kubernetes_namespace]
    regex: (.*)
    target_label: namespace
    replacement: $1
    action: replace
    
  # Метка service
  - source_labels: [__meta_kubernetes_service_name]
    regex: (.*)
    target_label: service
    replacement: $1
    action: replace
    
  # Метка instance (имя pod)
  - source_labels: [__meta_kubernetes_pod_name]
    regex: (.*)
    target_label: instance
    replacement: $1
    action: replace

Метка job, используемое значение метки prometheus_custom_target в случае service, добавляется префикс custom.

Метка job — служебная в Prometheus. Определяет название группы, в которой будет показываться target на странице targets, а также она будет у каждой метрики, полученной у этих targets (для последующей фильтрации rules и dashboards)

Пример rule_files:

rule_files:
- /etc/prometheus/rules/rules-0/*
- /etc/prometheus/rules/rules-1/*

Prometheus отслеживает:

  • добавление и удаление pods (при добавлении/удалении pods DropApp изменяет endpoints, в таком случае Prometheus добавляет/удаляет цели);

  • добавление и удаление endpoints в указанных namespaces.

Изменение конфигурационного файла требуется в следующих случаях:

  • добавление нового scrape_config;

  • изменение списка namespaces.

Prometheus-operator#

Prometheus-operator обеспечивает встроенное развертывание и управление Prometheus и связанными с ним компонентами мониторинга. Это сделано для упрощения и автоматизации настройки стека мониторинга на основе Prometheus для кластеров DropApp.

Основной особенностью Prometheus-operator является мониторинг сервера API DropApp на предмет изменений в объектах и обеспечение того, чтобы текущие развертывания Prometheus соответствовали этим объектам.

Prometheus-operator действует в соответствии со следующими определениями пользовательских ресурсов (CRD или Custom Resource Definitions):

  • Prometheus — определяет желаемое развертывание кластера Prometheus;

  • PrometheusAgent — определяет желаемое развертывание Prometheus, но работает в режиме агента;

  • Prometheus-alertmanager — определяет желаемое развертывание Prometheus-alertmanager;

  • ThanosRuler — определяет желаемое развертывание ThanosRuler;

  • ServiceMonitor — декларативно определяет, как следует контролировать группы сервисов DropApp. Оператор автоматически генерирует конфигурацию очистки Prometheus на основе текущего состояния объектов на сервере API;

  • PodMonitor — декларативно определяет, как следует контролировать группу pods. Автоматически генерирует конфигурацию очистки Prometheus на основе текущего состояния объектов на сервере API;

  • Probe — декларативно определяет группы входов или статических целей. Оператор автоматически генерирует конфигурацию Prometheus на основе определения;

  • ScrapeConfig — декларативно определяет конфигурации очистки, которые должны быть добавлены в Prometheus. Это CustomResourceDefinition помогает очищать ресурсы за пределами кластера DropApp;

  • PrometheusRule — определяет желаемый набор правил оповещений и/или записей Prometheus. Оператор генерирует файл правил, который может использоваться экземплярами Prometheus;

  • AlertmanagerConfig — декларативно определяет подразделы конфигурации Prometheus-alertmanager, позволяя маршрутизировать оповещения и устанавливать правила inhibit.

Prometheus-operator отслеживает ресурсы Prometheus и генерирует для каждого из них:

  • StatefulSet (с самим Prometheus);

  • Secret с prometheus.yaml (конфигурационный файл Prometheus) и configmaps.json(конфигурационный файл для Prometheus-config-reloader).

Оператор также следит за ресурсами ServiceMonitor и за ConfigMaps с правилами, и на их основании обновляет конфиги prometheus.yaml и configmaps.json (они хранятся в secret).

Развертывание Prometheus-operator#

Для выполнения данного сценария необходимы права администратора.

Развертывание#

Первым шагом является установка пользовательских определений ресурсов оператора (CRD), а также самого оператора с необходимыми ресурсами RBAC.

  1. Выполните следующие команды для установки CRD и развертывания оператора в namespace по умолчанию:

    LATEST=$(curl -s https://<repoexample.ru>/repos/prometheus-operator/prometheus-operator/releases/latest | jq -cr .tag_name)
    curl -sL https://<repoexample.ru>/prometheus-operator/prometheus-operator/releases/download/${LATEST}/bundle.yaml | kubectl create -f -
    # Укажите актуальный путь до локального репозитория
    

    Для запуска оператора может потребоваться несколько минут.

  2. Проверьте результат, введите команду:

    kubectl wait --for=condition=Ready pods -l  app.kubernetes.io/name=prometheus-operator -n default
    
  3. Введите пользовательские ресурсы в DropApp:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: example-app
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: example-app
      template:
        metadata:
          labels:
            app: example-app
        spec:
          containers:
          - name: example-app
            image: fabxc/instrumented_app
            ports:
            - name: web
              containerPort: 8080
    

    В примере развертывания приложение с 3 копиями, которое прослушивает Prometheus и предоставляет метрики на порту 8080.

  4. Предоставьте объект Service:

    kind: Service
    apiVersion: v1
    metadata:
      name: example-app
      labels:
        app: example-app
    spec:
      selector:
        app: example-app
      ports:
      - name: web
        port: 8080
    

    Service выбирает все pod с меткой app, имеющей значение example-app. Объект Service также указывает порт, на котором отображаются метрики.

  5. Создайте объект ServiceMonitor:

    apiVersion: monitoring.coreos.com/v1
    kind: ServiceMonitor
    metadata:
      name: example-app
      labels:
        team: frontend
    spec:
      selector:
        matchLabels:
          app: example-app
      endpoints:
      - port: web
    

    ServiceMonitor выбирает все объекты Service с меткой app: example-app. Также объект ServiceMonitor присвоена метка team: frontend для назначения команды, ответственной за наблюдение за приложением/сервисом.

Сценарий развертывания Prometheus#

Предварительные условия развертывания:

  • созданы правила RBAC для учетной записи службы Prometheus;

  • развернут Prometeus-operator.

Развертывание Prometeus#

Развертывание Prometeus:

  1. Примените следующие манифесты для создания учетной записи службы и связки ClusterRole/ClusterRoleBinding:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: prometheus
    

    Выше приведен фрагмент кода, который описывает создание ServiceAccount в DropApp, где:

    • apiVersion указывает версию API DropApp, к которой принадлежит этот объект. В данном случае это версия v1;

    • kind определяет тип объекта. В данном случае ServiceAccount;

    • metadata содержит информацию о ServiceAccount, такую как имя, которое может быть использовано для идентификации ServiceAccount.

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: prometheus
    rules:
    - apiGroups: [""]
      resources:
      - nodes
      - nodes/metrics
      - services
      - endpoints
      - pods
      verbs: ["get", "list", "watch"]
    - apiGroups: [""]
      resources:
      - configmaps
      verbs: ["get"]
    - apiGroups:
      - networking.k8s.io
      resources:
      - ingresses
      verbs: ["get", "list", "watch"]
    - nonResourceURLs: ["/metrics"]
      verbs: ["get"]
    

    Выше приведено описание объекта ClusterRole в DropApp, который предоставляет разрешения для работы с ресурсами в кластере, где:

    • apiVersion определяет версию API, к которой относится объект. В данном случае, это версия v1 для API группы rbac.authorization.k8s.io;

    • kind определяет тип объекта, в данном случае ClusterRole;

    • metadata содержит информацию об объекте, такую как его имя (name), которое может использоваться для его идентификации. Также здесь указаны правила, которые определяют, какие ресурсы и операции могут быть выполнены с ними;

    • rules определяет правила доступа к ресурсам. В данном примере, правила доступа включают получение списка, чтение и наблюдение за следующими ресурсами: nodes, nodes/metrics, services, endpoints, pods и configmaps. Также здесь указаны правила доступа к ресурсам из группы networking.k8s.io, включая ingresses;

    • nonResourceURLs определяет список URL-адресов, к которым можно получить доступ без указания ресурсов. В данном случае указан только один URL-адрес - /metrics;

    • verbs определяет список операций, которые могут быть выполнены над ресурсами. В данном случае указаны операции get, list и watch.

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: prometheus
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: prometheus
    subjects:
    - kind: ServiceAccount
      name: prometheus
      namespace: default
    

    Пользовательский ресурс Prometheus определяет характеристики StatefulSet (количество копий, запросы/ограничения ресурсов и т.д.), а также то, какие ServiceMonitors должны быть включены в поле spec.serviceMonitorSelector.

  2. Добавьте возможность ввода новых сервисных мониторов без необходимости перенастройки Prometheus, примените манифест:

    apiVersion: monitoring.operationsistem.com/v1
    kind: Prometheus
    metadata:
      name: prometheus
    spec:
      serviceAccountName: prometheus
      serviceMonitorSelector:
        matchLabels:
          team: frontend
      resources:
        requests:
          memory: 400Mi
      enableAdminAPI: false
    

    В сценарии развертывания Prometheus-operator (представлен выше) создается объект ServiceMonitor с меткой team: frontend. Манифест определяет, что объект Prometheus должен выбирать все ServiceMonitors с меткой team: frontend.

  3. Убедитесь, что экземпляр был запущен, введите команду:

    kubectl get -n default prometheus prometheus -w
    

    По умолчанию Prometheus запустит ServiceMonitors из текущего namespace. Чтоб выбрать ServiceMonitors из другого namespace, обновите поле spec.serviceMonitorNamespaceSelector в Prometheus.

Сценарий использования PodMonitors#

Для использования PodMonitors выполните шаги:

  1. Используйте PodMonitor в качестве альтернативы ServiceMonitor без необходимости создания сервиса DropApp:

    apiVersion: monitoring.coreos.com/v1
    kind: PodMonitor
    metadata:
      name: example-app
      labels:
        team: frontend
    spec:
      selector:
        matchLabels:
          app: example-app
      podMetricsEndpoints:
      - port: web
    

    Метка spec.selector указывает Prometheus, какие pods следует очистить.

  2. Определите выбор PodMonitors с помощью поля thespecspec.podMonitorSelector:

    apiVersion: monitoring.coreos.com/v1
    kind: Prometheus
    metadata:
      name: prometheus
    spec:
      serviceAccountName: prometheus
      podMonitorSelector:
        matchLabels:
          team: frontend
      resources:
        requests:
          memory: 400Mi
      enableAdminAPI: false
    
Сценарий предоставления Prometheus service#

Чтобы получить доступ к интерфейсу Prometheus, сервис необходимо предоставить другим приложениям.

  1. Определите службу NodePort:

    apiVersion: v1
    kind: Service
    metadata:
      name: prometheus
    spec:
      type: NodePort
      ports:
      - name: web
        nodePort: 30900
        port: 9090
        protocol: TCP
        targetPort: web
      selector:
        prometheus: prometheus
    

    После создания Service веб-сервер Prometheus доступен по IP-адресу node на порту 30900.

Сценарий развертывания Kube Prometheus#

Инструмент kubeadm позволяет развертывать и управлять кластерами DropApp, а также автоматически настраивать кластер с некоторыми базовыми опциями.

В разделе приведены сценарии развертывания Prometheus, Prometheus-operator и Kube Prometheus, для мониторинга кластера, который был развернут с помощью kubeadm.

По умолчанию kubeadm не предоставляет доступ к сервисам. Исправить это можно путем внесения изменений в кластер DropApp.

  1. Предоставьте доступ к кластеру kube-controller-manager и kube-scheduler:

    apiVersion: kubeadm.k8s.io/v1beta2
    kind: ClusterConfiguration
    controlPlaneEndpoint: "<IP-address>:0001"
    api-server:
      extraArgs:
        authorization-mode: "Node,RBAC"
    controllerManager:
      extraArgs:
        bind-address: "0.0.0.0"
    scheduler:
      extraArgs:
        bind-address: "0.0.0.0"
    certificatesDir: "/etc/kubernetes/pki"
    etcd:
      # Локальный или внешний
      local:
        dataDir: "/var/lib/etcd"
    kubernetesVersion: "v1.23.0"
    networking:
      dnsDomain: "cluster.local"
      serviceSubnet: "<IP-address>/10"
    imageRepository: "registry.k8s.io"
    

    По умолчанию kubeadm запускает pods на устройстве на 127.0.0.1.

    В строках scheduler.extraArgs и controllerManager.extraArgs предоставляется доступ к службам kube-controller-manager и kube-scheduler для остальной части кластера.

  2. Убедитесь, что значения spec.selector служб kube-prometheus-exporter-kube-scheduler и kube-prometheus-exporter-kube-controller-manager совпадают со значениями pods.

  3. Измените адреса прослушивания kube-controller-manager и kube-scheduler:

    sed -e "s/- --bind-address=127.0.0.1/- --bind-address=0.0.0.0/" -i /etc/kubernetes/manifests/kube-controller-manager.yaml
    sed -e "s/- --bind-address=127.0.0.1/- --bind-address=0.0.0.0/" -i /etc/kubernetes/manifests/kube-scheduler.yaml
    
Сценарий настройки метрик кластера#

Метрики, которые относятся к состоянию кластера отображаются дополнительным компонентом kube-state-metrics.

Для обзора ресурсов nodes кластера используется Prometheus node_exporter. Node_exporter позволяет отслеживать ресурсы node: процессор, использование памяти и диска и многое другое.

После завершения настройки будут доступны для отслеживания:

  • состояние кластера через kube-state-metrics;

  • nodes через node_exporter;

  • kubelets;

  • api-server;

  • kube-scheduler;

  • kube-controller-manager.

Для настройки сбора метрик кластера выполните следующую последовательность:

  1. Клонируйте репозиторий:

    git clone https://<repoexample.ru>/coreos/kube-prometheus
    cd kube-prometheus/
    # Укажите актуальный путь до локального репозитория
    
  2. Cоздайте namespace, в котором должен работать набор инструментов мониторинга:

    export NAMESPACE='monitoring'
    kubectl create namespace "$NAMESPACE"
    
  3. Создайте компоненты для оператора Prometheus:

    kubectl --namespace="$NAMESPACE" apply -f manifests/prometheus-operator
    

    Компоненты станут доступны в кластере спустя некоторое время.

  4. Проверьте готовность компонентов, введите команду:

    until kubectl --namespace="$NAMESPACE" get alertmanagers.monitoring.os.com > /dev/null 2>&1; do sleep 1; printf "."; done
    
  5. Установите node-exporter, а затем kube-state-metrics:

    kubectl --namespace="$NAMESPACE" apply -f manifests/node-exporter
    kubectl --namespace="$NAMESPACE" apply -f manifests/kube-state-metrics
    
  6. Разверните приложение, а затем роли/ролевые привязки Prometeus:

    find manifests/prometheus -type f ! -name prometheus-k8s-roles.yaml ! -name prometheus-k8s-role-bindings.yaml -exec kubectl --namespace "$NAMESPACE" apply -f {} \;
    kubectl apply -f manifests/prometheus/prometheus-k8s-roles.yaml
    kubectl apply -f manifests/prometheus/prometheus-k8s-role-bindings.yaml
    
  7. Установите Prometheus-alertmanager:

    kubectl --namespace="$NAMESPACE" apply -f manifests/alertmanager
    

    В результате выполнения сценария создан кластер, доступны пользовательские интерфейсы Prometheus и Prometheus-alertmanager на портах node 30900 и 30903.