Как собирать метрики с приложений, расположенных вне кластера?

  1. Сконфигурируйте Service по аналогии с сервисом для сбора метрик с вашего приложения, но без указания параметра spec.selector.
  2. Создайте Endpoints для этого Service, явно указав в них IP:PORT, по которым ваши приложения отдают метрики.

    Имена портов в Endpoints должны совпадать с именами этих портов в Service.

Пример

Метрики приложения доступны без TLS, по адресу http://10.182.10.5:9114/metrics.

1apiVersion: v1
2kind: Service
3metadata:
4  name: my-app
5  namespace: my-namespace
6  labels:
7    prometheus.deckhouse.io/custom-target: my-app
8spec:
9  ports:
10  - name: http-metrics
11    port: 9114
12---
13apiVersion: v1
14kind: Endpoints
15metadata:
16  name: my-app
17  namespace: my-namespace
18subsets:
19  - addresses:
20    - ip: 10.182.10.5
21    ports:
22    - name: http-metrics
23      port: 9114

Как добавить дополнительные дашборды в вашем проекте?

Добавление пользовательских дашбордов для Grafana в Deckhouse реализовано с помощью подхода Infrastructure as a Code. Чтобы ваш дашборд появился в Grafana, необходимо создать в кластере специальный ресурс — GrafanaDashboardDefinition.

Пример:

1apiVersion: deckhouse.io/v1
2kind: GrafanaDashboardDefinition
3metadata:
4  name: my-dashboard
5spec:
6  folder: My folder # Папка, в которой в Grafana будет отображаться ваш дашборд.
7  definition: |
8    {
9      "annotations": {
10        "list": [
11          {
12            "builtIn": 1,
13            "datasource": "-- Grafana --",
14            "enable": true,
15            "hide": true,
16            "iconColor": "rgba(0, 211, 255, 1)",
17            "limit": 100,
18...

Системные и добавленные через GrafanaDashboardDefinition дашборды нельзя изменить через интерфейс Grafana.

Алерты, настроенные в панели dashboard, не работают с шаблонами datasource — такой dashboard является невалидным и не импортируется. В версии Grafana 9.0 функционал legacy alerting был признан устаревшим и заменён на Grafana Alerting. В связи с этим, мы не рекомендуем использовать legacy alerting (оповещения панели мониторинга) в dashboards.

Если после применения дашборд не появляется в Grafana, возможно, в JSON файле дашборда присутствует ошибка. Чтобы определить источник проблемы, воспользуйтесь командой kubectl logs -n d8-monitoring deployments/grafana-v10 dashboard-provisioner для просмотра логов компонента, который осуществляет применение дашбордов.

Как добавить алерты и/или recording-правила для вашего проекта?

Для добавления алертов существует специальный ресурс — CustomPrometheusRules.

Параметры:

  • groups — единственный параметр, в котором необходимо описать группы алертов. Структура групп полностью совпадает с аналогичной в prometheus-operator.

Пример:

1apiVersion: deckhouse.io/v1
2kind: CustomPrometheusRules
3metadata:
4  name: my-rules
5spec:
6  groups:
7  - name: cluster-state-alert.rules
8    rules:
9    - alert: CephClusterErrorState
10      annotations:
11        description: Storage cluster is in error state for more than 10m.
12        summary: Storage cluster is in error state
13        plk_markup_format: markdown
14      expr: |
15        ceph_health_status{job="rook-ceph-mgr"} > 1

Как подключить дополнительные data source для Grafana?

Для подключения дополнительных data source к Grafana существует специальный ресурс — GrafanaAdditionalDatasource.

Параметры ресурса подробно описаны в документации к Grafana. Тип ресурса смотрите в документации по конкретному datasource.

Пример:

1apiVersion: deckhouse.io/v1
2kind: GrafanaAdditionalDatasource
3metadata:
4  name: another-prometheus
5spec:
6  type: prometheus
7  access: Proxy
8  url: https://another-prometheus.example.com/prometheus
9  basicAuth: true
10  basicAuthUser: foo
11  jsonData:
12    timeInterval: 30s
13    httpMethod: POST
14  secureJsonData:
15    basicAuthPassword: bar

Как обеспечить безопасный доступ к метрикам?

Для обеспечения безопасности настоятельно рекомендуем использовать kube-rbac-proxy.

Пример безопасного сбора метрик с приложения, расположенного в кластере

Чтобы настроить защиту метрик приложения с использованием kube-rbac-proxy и последующего сбора метрик с помощью Prometheus, выполните следующие шаги:

  1. Создайте ServiceAccount с указанными ниже правами:

    1---
    2apiVersion: v1
    3kind: ServiceAccount
    4metadata:
    5  name: rbac-proxy-test
    6---
    7apiVersion: rbac.authorization.k8s.io/v1
    8kind: ClusterRoleBinding
    9metadata:
    10  name: rbac-proxy-test
    11roleRef:
    12  apiGroup: rbac.authorization.k8s.io
    13  kind: ClusterRole
    14  name: d8:rbac-proxy
    15subjects:
    16- kind: ServiceAccount
    17  name: rbac-proxy-test
    18  namespace: default
    

    Обратите внимание, что используется встроенная в Deckhouse ClusterRole d8:rbac-proxy.

  2. Создайте конфигурацию для kube-rbac-proxy:

    1---
    2apiVersion: v1
    3kind: ConfigMap
    4metadata:
    5  name: rbac-proxy-config-test
    6  namespace: rbac-proxy-test
    7data:
    8  config-file.yaml: |+
    9    authorization:
    10      resourceAttributes:
    11        namespace: default
    12        apiVersion: v1
    13        resource: services
    14        subresource: proxy
    15        name: rbac-proxy-test
    

    Более подробную информацию по атрибутам можно найти в документации Kubernetes.

  3. Создайте Service и Deployment для вашего приложения, где kube-rbac-proxy займет позицию sidecar-контейнера:

    1---
    2apiVersion: v1
    3kind: Service
    4metadata:
    5  name: rbac-proxy-test
    6  labels:
    7    prometheus.deckhouse.io/custom-target: rbac-proxy-test
    8spec:
    9  ports:
    10  - name: https-metrics
    11    port: 8443
    12    targetPort: https-metrics
    13  selector:
    14    app: rbac-proxy-test
    15---
    16apiVersion: apps/v1
    17kind: Deployment
    18metadata:
    19  name: rbac-proxy-test
    20spec:
    21  replicas: 1
    22  selector:
    23    matchLabels:
    24      app: rbac-proxy-test
    25  template:
    26    metadata:
    27      labels:
    28        app: rbac-proxy-test
    29    spec:
    30      securityContext:
    31        runAsUser: 65532
    32      serviceAccountName: rbac-proxy-test
    33      containers:
    34      - name: kube-rbac-proxy
    35        image: quay.io/brancz/kube-rbac-proxy:v0.14.0
    36        args:
    37        - "--secure-listen-address=0.0.0.0:8443"
    38        - "--upstream=http://127.0.0.1:8081/"
    39        - "--config-file=/kube-rbac-proxy/config-file.yaml"
    40        - "--logtostderr=true"
    41        - "--v=10"
    42        ports:
    43        - containerPort: 8443
    44          name: https-metrics
    45        volumeMounts:
    46        - name: config
    47          mountPath: /kube-rbac-proxy
    48      - name: prometheus-example-app
    49        image: quay.io/brancz/prometheus-example-app:v0.1.0
    50        args:
    51        - "--bind=127.0.0.1:8081"
    52      volumes:
    53      - name: config
    54        configMap:
    55          name: rbac-proxy-config-test
    
  4. Назначьте необходимые права на ресурс для Prometheus:

    1---
    2apiVersion: rbac.authorization.k8s.io/v1
    3kind: ClusterRole
    4metadata:
    5  name: rbac-proxy-test-client
    6rules:
    7- apiGroups: [""]
    8  resources: ["services/proxy"]
    9  verbs: ["get"]
    10---
    11apiVersion: rbac.authorization.k8s.io/v1
    12kind: ClusterRoleBinding
    13metadata:
    14  name: rbac-proxy-test-client
    15roleRef:
    16  apiGroup: rbac.authorization.k8s.io
    17  kind: ClusterRole
    18  name: rbac-proxy-test-client
    19subjects:
    20- kind: ServiceAccount
    21  name: prometheus
    22  namespace: d8-monitoring
    

После шага 4 метрики вашего приложения должны появиться в Prometheus.

Пример безопасного сбора метрик с приложения, расположенного вне кластера

Предположим, что есть доступный через интернет сервер, на котором работает node-exporter. По умолчанию node-exporter слушает на порту 9100 и доступен на всех интерфейсах. Необходимо обеспечить контроль доступа к node-exporter для безопасного сбора метрик. Ниже приведен пример такой настройки.

Требования:

  • Из кластера должен быть доступ к сервису kube-rbac-proxy, который запущен на удаленном сервере.
  • От удаленного сервера должен быть доступ к API-серверу кластера.

Выполните следующие шаги:

  1. Создайте ServiceAccount с указанными ниже правами:

    1---
    2apiVersion: v1
    3kind: ServiceAccount
    4metadata:
    5  name: prometheus-external-endpoint-server-01
    6  namespace: d8-service-accounts
    7---
    8apiVersion: rbac.authorization.k8s.io/v1
    9kind: ClusterRole
    10metadata:
    11  name: prometheus-external-endpoint
    12rules:
    13- apiGroups: ["authentication.k8s.io"]
    14  resources:
    15  - tokenreviews
    16  verbs: ["create"]
    17- apiGroups: ["authorization.k8s.io"]
    18  resources:
    19  - subjectaccessreviews
    20  verbs: ["create"]
    21---
    22apiVersion: rbac.authorization.k8s.io/v1
    23kind: ClusterRoleBinding
    24metadata:
    25  name: prometheus-external-endpoint-server-01
    26roleRef:
    27  apiGroup: rbac.authorization.k8s.io
    28  kind: ClusterRole
    29  name: prometheus-external-endpoint
    30subjects:
    31- kind: ServiceAccount
    32  name: prometheus-external-endpoint-server-01
    33  namespace: d8-service-accounts
    
  2. Сгенерируйте kubeconfig для созданного ServiceAccount (пример генерации kubeconfig для ServiceAccount).

  3. Положите получившийся kubeconfig на удаленный сервер. Необходимо указать путь к этому kubeconfig в настройках kube-rbac-proxy (в примере используется путь ${PWD}/.kube/config).

  4. Настройте node-exporter на удаленном сервере с доступом к нему только на локальном интерфейсе (чтобы он слушал 127.0.0.1:9100).
  5. Запустите kube-rbac-proxy на удаленном сервере:

    1docker run --network host -d -v ${PWD}/.kube/config:/config quay.io/brancz/kube-rbac-proxy:v0.14.0 --secure-listen-address=0.0.0.0:8443 \
    2  --upstream=http://127.0.0.1:9100 --kubeconfig=/config --logtostderr=true --v=10
    
  6. Проверьте, что порт 8443 доступен по внешнему адресу удаленного сервера.

  7. Создайте в кластере Service и Endpoint, указав в качестве <server_ip_address> внешний адрес удаленного сервера:

    1---
    2apiVersion: v1
    3kind: Service
    4metadata:
    5  name: prometheus-external-endpoint-server-01
    6  labels:
    7    prometheus.deckhouse.io/custom-target: prometheus-external-endpoint-server-01
    8spec:
    9  ports:
    10  - name: https-metrics
    11    port: 8443
    12---
    13apiVersion: v1
    14kind: Endpoints
    15metadata:
    16  name: prometheus-external-endpoint-server-01
    17subsets:
    18  - addresses:
    19    - ip: <server_ip_address>
    20    ports:
    21    - name: https-metrics
    22      port: 8443
    

Как добавить Alertmanager?

Создайте кастомный ресурс CustomAlertmanager с типом Internal.

Пример:

1apiVersion: deckhouse.io/v1alpha1
2kind: CustomAlertmanager
3metadata:
4  name: webhook
5spec:
6  type: Internal
7  internal:
8    route:
9      groupBy: ['job']
10      groupWait: 30s
11      groupInterval: 5m
12      repeatInterval: 12h
13      receiver: 'webhook'
14    receivers:
15    - name: 'webhook'
16      webhookConfigs:
17      - url: 'http://webhookserver:8080/'

Подробно о всех параметрах можно прочитать в описании кастомного ресурса CustomAlertmanager.

Как добавить внешний дополнительный Alertmanager?

Создайте кастомный ресурс CustomAlertmanager с типом External, который может указывать на Alertmanager по FQDN или через сервис в Kubernetes-кластере.

Пример FQDN Alertmanager:

1apiVersion: deckhouse.io/v1alpha1
2kind: CustomAlertmanager
3metadata:
4  name: my-fqdn-alertmanager
5spec:
6  external:
7    address: https://alertmanager.mycompany.com/myprefix
8  type: External

Пример Alertmanager с Kubernetes service:

1apiVersion: deckhouse.io/v1alpha1
2kind: CustomAlertmanager
3metadata:
4  name: my-service-alertmanager
5spec:
6  external:
7    service:
8      namespace: myns
9      name: my-alertmanager
10      path: /myprefix/
11  type: External

Подробно о всех параметрах можно прочитать в описании кастомного ресурса CustomAlertmanager.

Как в Alertmanager игнорировать лишние алерты?

Решение сводится к настройке маршрутизации алертов в вашем Alertmanager.

Требования:

  1. Завести получателя без параметров.
  2. Смаршрутизировать лишние алерты в этого получателя.

Ниже приведены примеры настройки CustomAlertmanager.

Чтобы получать только алерты с лейблами service: foo|bar|baz:

1receivers:
2  # Получатель, определенный без параметров, будет работать как "/dev/null".
3  - name: blackhole
4  # Действующий получатель  
5  - name: some-other-receiver
6    # ...
7route:
8  # receiver по умолчанию.
9  receiver: blackhole
10  routes:
11    # Дочерний маршрут
12    - matchers:
13        - matchType: =~
14          name: service
15          value: ^(foo|bar|baz)$
16      receiver: some-other-receiver

Чтобы получать все алерты, кроме DeadMansSwitch:

1receivers:
2  # Получатель, определенный без параметров, будет работать как "/dev/null".
3  - name: blackhole
4  # Действующий получатель.
5  - name: some-other-receiver
6  # ...
7route:
8  # receiver по умолчанию.
9  receiver: some-other-receiver
10  routes:
11    # Дочерний маршрут.
12    - matchers:
13        - matchType: =
14          name: alertname
15          value: DeadMansSwitch
16      receiver: blackhole

С подробным описанием всех параметров можно ознакомиться в официальной документации.

Почему нельзя установить разный scrapeInterval для отдельных таргетов?

Наиболее полный ответ на этот вопрос дает разработчик Prometheus Brian Brazil. Вкратце, разные scrapeInterval’ы принесут следующие проблемы:

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

Наиболее подходящее значение для scrapeInterval находится в диапазоне 10–60 секунд.

Как ограничить потребление ресурсов Prometheus?

Чтобы предотвратить ситуации, когда Variable Policy Agent (VPA) запрашивает у Prometheus или долгосрочного Prometheus больше ресурсов, чем доступно на выделенном узле для этих целей, можно явно установить ограничения для VPA с использованием параметров модуля:

  • vpa.longtermMaxCPU;
  • vpa.longtermMaxMemory;
  • vpa.maxCPU;
  • vpa.maxMemory.

Как настроить ServiceMonitor или PodMonitor для работы с Prometheus?

Добавьте лейбл prometheus: main к Pod/Service Monitor. Добавьте в пространство имён, в котором находится Pod/Service Monitor, лейбл prometheus.deckhouse.io/monitor-watcher-enabled: "true".

Пример:

1---
2apiVersion: v1
3kind: Namespace
4metadata:
5  name: frontend
6  labels:
7    prometheus.deckhouse.io/monitor-watcher-enabled: "true"
8---
9apiVersion: monitoring.coreos.com/v1
10kind: ServiceMonitor
11metadata:
12  name: example-app
13  namespace: frontend
14  labels:
15    prometheus: main
16spec:
17  selector:
18    matchLabels:
19      app: example-app
20  endpoints:
21    - port: web

Как настроить Probe для работы с Prometheus?

Добавьте лейбл prometheus: main к Probe. Добавьте в пространство имён, в котором находится Probe, лейбл prometheus.deckhouse.io/probe-watcher-enabled: "true".

Пример:

1---
2apiVersion: v1
3kind: Namespace
4metadata:
5  name: frontend
6  labels:
7    prometheus.deckhouse.io/probe-watcher-enabled: "true"
8---
9apiVersion: monitoring.coreos.com/v1
10kind: Probe
11metadata:
12  labels:
13    app: prometheus
14    component: probes
15    prometheus: main
16  name: cdn-is-up
17  namespace: frontend
18spec:
19  interval: 30s
20  jobName: httpGet
21  module: http_2xx
22  prober:
23    path: /probe
24    scheme: http
25    url: blackbox-exporter.blackbox-exporter.svc.cluster.local:9115
26  targets:
27    staticConfig:
28      static:
29      - https://example.com/status

Как настроить PrometheusRules для работы с Prometheus?

Добавьте в пространство имён, в котором находятся PrometheusRules, лейбл prometheus.deckhouse.io/rules-watcher-enabled: "true".

Пример:

1---
2apiVersion: v1
3kind: Namespace
4metadata:
5  name: frontend
6  labels:
7    prometheus.deckhouse.io/rules-watcher-enabled: "true"

Как увеличить размер диска

  1. Для увеличения размера отредактируйте PersistentVolumeClaim, указав новый размер в поле spec.resources.requests.storage.
    • Увеличение размера возможно, если в StorageClass поле allowVolumeExpansion установлено в true.
  2. Если используемое хранилище не поддерживает изменение диска на лету, в статусе PersistentVolumeClaim появится сообщение Waiting for user to (re-)start a pod to finish file system resize of volume on node..
  3. Перезапустите под для завершения изменения размера файловой системы.

Как получить информацию об алертах в кластере?

Информацию об активных алертах можно получить не только в веб-интерфейсе Grafana/Prometheus, но и в CLI. Это может быть полезным, если у вас есть только доступ к API-серверу кластера и нет возможности открыть веб-интерфейс Grafana/Prometheus.

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

1kubectl get clusteralerts

Пример вывода:

1NAME               ALERT                                      SEVERITY   AGE     LAST RECEIVED   STATUS
2086551aeee5b5b24   ExtendedMonitoringDeprecatatedAnnotation   4          3h25m   38s             firing
3226d35c886464d6e   ExtendedMonitoringDeprecatatedAnnotation   4          3h25m   38s             firing
4235d4efba7df6af4   D8SnapshotControllerPodIsNotReady          8          5d4h    44s             firing
527464763f0aa857c   D8PrometheusOperatorPodIsNotReady          7          5d4h    43s             firing
6ab17837fffa5e440   DeadMansSwitch                             4          5d4h    41s             firing

Выполните следующую команду для просмотра конкретного алерта:

1kubectl get clusteralerts <ALERT_NAME> -o yaml

Пример:

1# kubectl get clusteralerts 235d4efba7df6af4 -o yaml
2alert:
3  description: |
4    The recommended course of action:
5    1. Retrieve details of the Deployment: `kubectl -n d8-snapshot-controller describe deploy snapshot-controller`
6    2. View the status of the Pod and try to figure out why it is not running: `kubectl -n d8-snapshot-controller describe pod -l app=snapshot-controller`
7  labels:
8    pod: snapshot-controller-75bd776d76-xhb2c
9    prometheus: deckhouse
10    tier: cluster
11  name: D8SnapshotControllerPodIsNotReady
12  severityLevel: "8"
13  summary: The snapshot-controller Pod is NOT Ready.
14apiVersion: deckhouse.io/v1alpha1
15kind: ClusterAlert
16metadata:
17  creationTimestamp: "2023-05-15T14:24:08Z"
18  generation: 1
19  labels:
20    app: prometheus
21    heritage: deckhouse
22  name: 235d4efba7df6af4
23  resourceVersion: "36262598"
24  uid: 817f83e4-d01a-4572-8659-0c0a7b6ca9e7
25status:
26  alertStatus: firing
27  lastUpdateTime: "2023-05-15T18:10:09Z"
28  startsAt: "2023-05-10T13:43:09Z"

{% alert level=”info” %} Присутствие специального алерта DeadMansSwitch в кластере говорит о работоспособности Prometheus. {% endalert %}

Как добавить дополнительные эндпоинты в scrape config?

Добавьте в пространство имён, в котором находится ScrapeConfig, лейбл prometheus.deckhouse.io/scrape-configs-watcher-enabled: "true".

Пример:

1---
2apiVersion: v1
3kind: Namespace
4metadata:
5  name: frontend
6  labels:
7    prometheus.deckhouse.io/scrape-configs-watcher-enabled: "true"

Добавьте ScrapeConfig, который имеет обязательный лейбл prometheus: main:

1apiVersion: monitoring.coreos.com/v1alpha1
2kind: ScrapeConfig
3metadata:
4  name: example-scrape-config
5  namespace: frontend
6  labels:
7    prometheus: main
8spec:
9  honorLabels: true
10  staticConfigs:
11    - targets: ['example-app.frontend.svc.{{ .Values.global.discovery.clusterDomain }}.:8080']
12  relabelings:
13    - regex: endpoint|namespace|pod|service
14      action: labeldrop
15    - targetLabel: scrape_endpoint
16      replacement: main
17    - targetLabel: job
18      replacement: kube-state-metrics
19  metricsPath: '/metrics'