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

  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

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

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

Пример:

1apiVersion: deckhouse.io/v1
2kind: GrafanaDashboardDefinition
3metadata:
4  name: my-dashboard
5spec:
6  folder: My folder # Папка, в которой в Grafana будет отображаться ваш dashboard.
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 dashboard’ы нельзя изменить через интерфейс Grafana.

Как добавить алерты и/или 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?

Создайте custom resource 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/'

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

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

Создайте custom resource 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

Подробно о всех параметрах можно прочитать в описании custom resource 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?

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

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

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

Добавьте лейбл prometheus: main к Pod/Service Monitor. Добавьте в namespace, в котором находится 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. Добавьте в namespace, в котором находится 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?

Добавьте в namespace, в котором находятся 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

Пример:

1# kubectl get clusteralerts
2NAME               ALERT                                      SEVERITY   AGE     LAST RECEIVED   STATUS
3086551aeee5b5b24   ExtendedMonitoringDeprecatatedAnnotation   4          3h25m   38s             firing
4226d35c886464d6e   ExtendedMonitoringDeprecatatedAnnotation   4          3h25m   38s             firing
5235d4efba7df6af4   D8SnapshotControllerPodIsNotReady          8          5d4h    44s             firing
627464763f0aa857c   D8PrometheusOperatorPodIsNotReady          7          5d4h    43s             firing
7ab17837fffa5e440   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"

Помните о специальном алерте DeadMansSwitch — его присутствие в кластере говорит о работоспособности Prometheus.

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

Добавьте в namespace, в котором находится 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'