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

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

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

Пример

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

apiVersion: v1
kind: Service
metadata:
  name: my-app
  namespace: my-namespace
  labels:
    prometheus.deckhouse.io/custom-target: my-app
spec:
  ports:
  - name: http-metrics
    port: 9114
---
apiVersion: v1
kind: Endpoints
metadata:
  name: my-app
  namespace: my-namespace
subsets:
  - addresses:
    - ip: 10.182.10.5
    ports:
    - name: http-metrics
      port: 9114

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

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

Пример:

apiVersion: deckhouse.io/v1
kind: GrafanaDashboardDefinition
metadata:
  name: my-dashboard
spec:
  folder: My folder # Папка, в которой в Grafana будет отображаться ваш дашборд.
  definition: |
    {
      "annotations": {
        "list": [
          {
            "builtIn": 1,
            "datasource": "-- Grafana --",
            "enable": true,
            "hide": true,
            "iconColor": "rgba(0, 211, 255, 1)",
            "limit": 100,
...

{% alert level=”warning” %} Системные и добавленные через GrafanaDashboardDefinition дашборды нельзя изменить через интерфейс Grafana. {% endalert %}

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

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

Параметры:

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

Пример:

apiVersion: deckhouse.io/v1
kind: CustomPrometheusRules
metadata:
  name: my-rules
spec:
  groups:
  - name: cluster-state-alert.rules
    rules:
    - alert: CephClusterErrorState
      annotations:
        description: Storage cluster is in error state for more than 10m.
        summary: Storage cluster is in error state
        plk_markup_format: markdown
      expr: |
        ceph_health_status{job="rook-ceph-mgr"} > 1

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

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

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

Пример:

apiVersion: deckhouse.io/v1
kind: GrafanaAdditionalDatasource
metadata:
  name: another-prometheus
spec:
  type: prometheus
  access: Proxy
  url: https://another-prometheus.example.com/prometheus
  basicAuth: true
  basicAuthUser: foo
  jsonData:
    timeInterval: 30s
    httpMethod: POST
  secureJsonData:
    basicAuthPassword: bar

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

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

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

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

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

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

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

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

    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: rbac-proxy-config-test
      namespace: rbac-proxy-test
    data:
      config-file.yaml: |+
        authorization:
          resourceAttributes:
            namespace: default
            apiVersion: v1
            resource: services
            subresource: proxy
            name: rbac-proxy-test
    

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

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

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: rbac-proxy-test
      labels:
        prometheus.deckhouse.io/custom-target: rbac-proxy-test
    spec:
      ports:
      - name: https-metrics
        port: 8443
        targetPort: https-metrics
      selector:
        app: rbac-proxy-test
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: rbac-proxy-test
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: rbac-proxy-test
      template:
        metadata:
          labels:
            app: rbac-proxy-test
        spec:
          securityContext:
            runAsUser: 65532
          serviceAccountName: rbac-proxy-test
          containers:
          - name: kube-rbac-proxy
            image: quay.io/brancz/kube-rbac-proxy:v0.14.0
            args:
            - "--secure-listen-address=0.0.0.0:8443"
            - "--upstream=http://127.0.0.1:8081/"
            - "--config-file=/kube-rbac-proxy/config-file.yaml"
            - "--logtostderr=true"
            - "--v=10"
            ports:
            - containerPort: 8443
              name: https-metrics
            volumeMounts:
            - name: config
              mountPath: /kube-rbac-proxy
          - name: prometheus-example-app
            image: quay.io/brancz/prometheus-example-app:v0.1.0
            args:
            - "--bind=127.0.0.1:8081"
          volumes:
          - name: config
            configMap:
              name: rbac-proxy-config-test
    
  4. Назначьте необходимые права на ресурс для Prometheus:

    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: rbac-proxy-test-client
    rules:
    - apiGroups: [""]
      resources: ["services/proxy"]
      verbs: ["get"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: rbac-proxy-test-client
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: rbac-proxy-test-client
    subjects:
    - kind: ServiceAccount
      name: prometheus
      namespace: d8-monitoring
    

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

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

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

Требования:

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

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

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

    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: prometheus-external-endpoint-server-01
      namespace: d8-service-accounts
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: prometheus-external-endpoint
    rules:
    - apiGroups: ["authentication.k8s.io"]
      resources:
      - tokenreviews
      verbs: ["create"]
    - apiGroups: ["authorization.k8s.io"]
      resources:
      - subjectaccessreviews
      verbs: ["create"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: prometheus-external-endpoint-server-01
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: prometheus-external-endpoint
    subjects:
    - kind: ServiceAccount
      name: prometheus-external-endpoint-server-01
      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 на удаленном сервере:

    docker 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 \
      --upstream=http://127.0.0.1:9100 --kubeconfig=/config --logtostderr=true --v=10
    
  6. Проверьте, что порт 8443 доступен по внешнему адресу удаленного сервера.

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

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: prometheus-external-endpoint-server-01
      labels:
        prometheus.deckhouse.io/custom-target: prometheus-external-endpoint-server-01
    spec:
      ports:
      - name: https-metrics
        port: 8443
    ---
    apiVersion: v1
    kind: Endpoints
    metadata:
      name: prometheus-external-endpoint-server-01
    subsets:
      - addresses:
        - ip: <server_ip_address>
        ports:
        - name: https-metrics
          port: 8443
    

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

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

Пример:

apiVersion: deckhouse.io/v1alpha1
kind: CustomAlertmanager
metadata:
  name: webhook
spec:
  type: Internal
  internal:
    route:
      groupBy: ['job']
      groupWait: 30s
      groupInterval: 5m
      repeatInterval: 12h
      receiver: 'webhook'
    receivers:
    - name: 'webhook'
      webhookConfigs:
      - url: 'http://webhookserver:8080/'

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

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

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

Пример FQDN Alertmanager:

apiVersion: deckhouse.io/v1alpha1
kind: CustomAlertmanager
metadata:
  name: my-fqdn-alertmanager
spec:
  external:
    address: https://alertmanager.mycompany.com/myprefix
  type: External

Пример Alertmanager с Kubernetes service:

apiVersion: deckhouse.io/v1alpha1
kind: CustomAlertmanager
metadata:
  name: my-service-alertmanager
spec:
  external:
    service:
      namespace: myns
      name: my-alertmanager
      path: /myprefix/
  type: External

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

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

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

Требования:

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

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

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

receivers:
  # Получатель, определенный без параметров, будет работать как "/dev/null".
  - name: blackhole
  # Действующий получатель  
  - name: some-other-receiver
    # ...
route:
  # receiver по умолчанию.
  receiver: blackhole
  routes:
    # Дочерний маршрут
    - matchers:
        - matchType: =~
          name: service
          value: ^(foo|bar|baz)$
      receiver: some-other-receiver

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

receivers:
  # Получатель, определенный без параметров, будет работать как "/dev/null".
  - name: blackhole
  # Действующий получатель.
  - name: some-other-receiver
  # ...
route:
  # receiver по умолчанию.
  receiver: some-other-receiver
  routes:
    # Дочерний маршрут.
    - matchers:
        - matchType: =
          name: alertname
          value: DeadMansSwitch
      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".

Пример:

---
apiVersion: v1
kind: Namespace
metadata:
  name: frontend
  labels:
    prometheus.deckhouse.io/monitor-watcher-enabled: "true"
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: example-app
  namespace: frontend
  labels:
    prometheus: main
spec:
  selector:
    matchLabels:
      app: example-app
  endpoints:
    - port: web

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

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

Пример:

---
apiVersion: v1
kind: Namespace
metadata:
  name: frontend
  labels:
    prometheus.deckhouse.io/probe-watcher-enabled: "true"
---
apiVersion: monitoring.coreos.com/v1
kind: Probe
metadata:
  labels:
    app: prometheus
    component: probes
    prometheus: main
  name: cdn-is-up
  namespace: frontend
spec:
  interval: 30s
  jobName: httpGet
  module: http_2xx
  prober:
    path: /probe
    scheme: http
    url: blackbox-exporter.blackbox-exporter.svc.cluster.local:9115
  targets:
    staticConfig:
      static:
      - https://example.com/status

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

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

Пример:

---
apiVersion: v1
kind: Namespace
metadata:
  name: frontend
  labels:
    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.

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

kubectl get clusteralerts

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

NAME               ALERT                                      SEVERITY   AGE     LAST RECEIVED   STATUS
086551aeee5b5b24   ExtendedMonitoringDeprecatatedAnnotation   4          3h25m   38s             firing
226d35c886464d6e   ExtendedMonitoringDeprecatatedAnnotation   4          3h25m   38s             firing
235d4efba7df6af4   D8SnapshotControllerPodIsNotReady          8          5d4h    44s             firing
27464763f0aa857c   D8PrometheusOperatorPodIsNotReady          7          5d4h    43s             firing
ab17837fffa5e440   DeadMansSwitch                             4          5d4h    41s             firing

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

kubectl get clusteralerts <ALERT_NAME> -o yaml

Пример:

# kubectl get clusteralerts 235d4efba7df6af4 -o yaml
alert:
  description: |
    The recommended course of action:
    1. Retrieve details of the Deployment: `kubectl -n d8-snapshot-controller describe deploy snapshot-controller`
    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`
  labels:
    pod: snapshot-controller-75bd776d76-xhb2c
    prometheus: deckhouse
    tier: cluster
  name: D8SnapshotControllerPodIsNotReady
  severityLevel: "8"
  summary: The snapshot-controller Pod is NOT Ready.
apiVersion: deckhouse.io/v1alpha1
kind: ClusterAlert
metadata:
  creationTimestamp: "2023-05-15T14:24:08Z"
  generation: 1
  labels:
    app: prometheus
    heritage: deckhouse
  name: 235d4efba7df6af4
  resourceVersion: "36262598"
  uid: 817f83e4-d01a-4572-8659-0c0a7b6ca9e7
status:
  alertStatus: firing
  lastUpdateTime: "2023-05-15T18:10:09Z"
  startsAt: "2023-05-10T13:43:09Z"

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

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

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

Пример:

---
apiVersion: v1
kind: Namespace
metadata:
  name: frontend
  labels:
    prometheus.deckhouse.io/scrape-configs-watcher-enabled: "true"

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

apiVersion: monitoring.coreos.com/v1alpha1
kind: ScrapeConfig
metadata:
  name: example-scrape-config
  namespace: frontend
  labels:
    prometheus: main
spec:
  honorLabels: true
  staticConfigs:
    - targets: ['example-app.frontend.svc.{{ .Values.global.discovery.clusterDomain }}.:8080']
  relabelings:
    - regex: endpoint|namespace|pod|service
      action: labeldrop
    - targetLabel: scrape_endpoint
      replacement: main
    - targetLabel: job
      replacement: kube-state-metrics
  metricsPath: '/metrics'