Surveiller votre cluster Kubernetes et vos applications avec kube-prometheus-stack

Surveiller votre cluster Kubernetes et vos applications avec kube-prometheus-stack

Introduction

Il y a quelques mois, j'ai migré définitivement tous mes services (blog, git, etc.) que j'auto-héberge de la technologie docker-compose à Kubernetes en utilisant la solution K3S. Ce changement m'a demandé un certain nombre de modifications : créer des objets Deployment, Service, Ingress et j'en passe, nécessaires au bon fonctionnement des applications à déployer.

De plus, je me suis également basé sur des charts Helm publics dans le but de gagner du temps en personnalisant certains paramètres. L'objectif aujourd'hui est de vous présenter un chart très complet qui s'appelle kube-prometheus-stack anciennement baptisé prometheus-operator.

Ce chart permet de déployer de nombreux objets Kubernetes reliés à trois outils principaux :

  • Prometheus : Outil de surveillance qui collecte et stocke des métriques provenant de diverses sources ayant comme capacité de lever ou non des alertes suivant la santé des serveurs, services ou applications observés ;
  • Grafana : Plateforme de visualisation de données qui s'intègre avec Prometheus, permettant de créer des tableaux de bord afin d'offrir une vue graphique ;
  • Alertmanager : Composant qui est aussi en relation avec Prometheus qui propose l'envoi de notification à la suite du déclenchement d'une alerte.

Pourquoi avoir choisi ces outils ? Ils sont tous les trois open source et Prometheus est référencé auprès de la CNCF (Cloud Native Computing Foundation) au statut Graduated depuis 2018. C'est donc une solution mature qui a fait ses preuves dans des contextes de production notamment.

Pour finir, le but de cet article est non seulement d'installer kube-prometheus-stack mais aussi de voir l'ensemble des étapes nécessaires pour superviser une application.

Prêt pour l'installation ? C'est parti !

Mise en place du chart

Comme pour tout chart Helm, vous aurez besoin du client helm sur votre poste afin de pouvoir dialoguer avec votre cluster et installer kube-prometheus-stack.

Avant d'installer quoi que ce soit, pour ceux qui sont sur K3S comme moi, je vous recommande de désactiver certaines règles de Prometheus qui sont par défauts et que ce dernier ne pourra pas surveiller, car certains composants Kubernetes ne sont pas sous forme de Pod avec K3S. C'est le cas du controller manager, kube-proxy et scheduler.

Voici un extrait de mon values.yaml qui a pour but de surcharger les valeurs par défaut du chart :

defaultRules:
  rules:
    kubeControllerManager: false
    kubeProxy: false
    kubeSchedulerAlerting: false
  ## Disabled PrometheusRule alerts
  disabled:
    KubeControllerManagerDown: true
    KubeProxyDown: true
    KubeSchedulerDown: true

On désactive ces trois règles par défaut, mais aussi la création des objets PrometheusRule pour ces trois composants. En effet, ce chart va créer plusieurs CRD (CustomResourceDefinition) comme l'objet PrometheusRule qui a pour but de déployer des règles dans Prometheus qui seront chargées directement dans la configuration principale.

kube-prometheus-stack déploie entre autre un opérateur Kubernetes, il va donc constamment surveiller certaines objets comme les PrometheusRule de manière à alimenter la configuration de Prometheus.

Exemple ici avec une règle déployée automatiquement qui surveille les erreurs au sein de la configuration de Prometheus :

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
[...]
spec:
  groups:
  - name: prometheus
    rules:
    - alert: PrometheusBadConfig
      annotations:
        description: Prometheus {{$labels.namespace}}/{{$labels.pod}} has failed to
          reload its configuration.
        runbook_url: https://runbooks.prometheus-operator.dev/runbooks/prometheus/prometheusbadconfig
        summary: Failed Prometheus configuration reload.
      expr: |-
        # Without max_over_time, failed scrapes could create false negatives, see
        # https://www.robustperception.io/alerting-on-gauges-in-prometheus-2-0 for details.
        max_over_time(prometheus_config_last_reload_successful{job="kube-prometheus-stack-prometheus",namespace="kube-prometheus-stack"}[5m]) == 0
      for: 10m
      labels:
        severity: critical

Du côté de Grafana, j'ai fait aussi quelques modifications :

  • Modification du fuseau horaire
  • Désactiver la mire d'authentification et donner l'autorisation aux utilisateurs anonymes de visualiser l'ensemble des tableaux de bord. Rassurez-vous, l'objectif est de sécuriser l'accès à Grafana avec du mTLS au sein d'un Ingress plutôt qu'utiliser un couple utilisateur / mot de passe.

Si vous souhaitez faire de même, voici les valeurs à modifier :

## Using default values from https://github.com/grafana/helm-charts/blob/main/charts/grafana/values.yaml
##
grafana:
  ## Timezone for the default dashboards
  ## Other options are: browser or a specific timezone, i.e. Europe/Luxembourg
  ##
  defaultDashboardsTimezone: Europe/Zurich

  grafana.ini:
    auth.anonymous:
      enabled: true
      org_role: Viewer
    auth:
      disable_login_form: true

Dernière partie, la configuration d'Alertmanager. Cette dernière est un peu spécifique et peut contenir des informations sensibles. Dans mon cas, j'utilise Telegram pour être notifié en cas d'erreur. Je dois donc renseigner une clé d'API dans la configuration. C'est pourquoi je préfère injecter la totalité de la configuration sous forme de secret comme ceci :

## Configuration for alertmanager
## ref: https://prometheus.io/docs/alerting/alertmanager/
##
alertmanager:
  ## Settings affecting alertmanagerSpec
  ## ref: https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/api.md#alertmanagerspec
  ##
  alertmanagerSpec:
    ## ConfigSecret is the name of a Kubernetes Secret in the same namespace as the Alertmanager object, which contains configuration for
    ## this Alertmanager instance. Defaults to 'alertmanager-' The secret is mounted into /etc/alertmanager/config.
    ##
    configSecret: alertmanager-config

Je dois évidemment créer le secret alertmanager-config en amont avec comme clé alertmanager.yaml et la configuration en base64.

Pour vous donner des exemples de configuration et l'ensemble des paramètres pouvant être utilisés, je vous recommande ce lien de la documentation officielle.

L'ensemble du paramétrage ci-dessus n'est aucunement obligatoire. Vous pouvez très bien laisser la configuration par défaut.

Tout est bon ? il est temps d'installer notre chart !

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# Avec fichier values.yaml
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --namespace kube-prometheus-stack --create-namespace -f values.yaml
# Sans fichier values.yaml
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack --namespace kube-prometheus-stack --create-namespace

Nos Pod s'exécutent sans erreur, tout est bon ! Maintenant, comment faire pour surveiller nos applications ?

Surveiller vos applications ou vos services

Dans la partie précédente, nous avons vu ce qui concerne l'installation du chart kube-prometheus-stack, comme dit précédemment ce chart embarque plusieurs éléments par défaut donc des règles Prometheus et des tableaux de bord Grafana pour l'orchestrateur Kubernetes.

Je vous laisse le soin de créer des Ingress pour Prometheus, Grafana et Alertmanager pour rendre visible leurs interfaces graphiques sinon, vous pouvez faire du port-forward pour les consulter de manière temporaire.

Néanmoins, le chart ne va pas surveiller automatiquement vos applications ou vos services, il faudra venir créer et configurer plusieurs objets.

Dans cette partie de l'article, je vous propose comme fil rouge le fait de vouloir surveiller une base de données PostgreSQL que l'on peut installer avec le chart de Bitnami. Ce chart doit exposer un service permettant d'exposer des métriques. Vous pouvez le faire en surchargeant certains paramètres avec un fichier values.yaml comme celui-ci :

metrics:
  ## @param metrics.enabled Start a prometheus exporter
  ##
  enabled: true

Ajouter un ServiceMonitor pour surveiller notre application

Le ServiceMonitor est un autre objet CRD créé en déployant le chart. Dans ce ServiceMonitor, l'objectif est de donner toutes les informations nécessaires à l'opérateur Prometheus pour initialiser la configuration de Prometheus qui viendra récupérer les métriques via le Service de l'application à surveiller, dans notre cas PostgreSQL.

Voici un exemple de ServiceMonitor :

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  labels:
    release: kube-prometheus-stack
  name: postgresql
  namespace: kube-prometheus-stack
spec:
  endpoints:
  - port: http-metrics
  namespaceSelector:
    matchNames:
    - postgresql
  selector:
    matchLabels:
      app.kubernetes.io/component: metrics
      app.kubernetes.io/instance: postgresql

Quelques petites subtilités sont à connaître :

  • Le ServiceMonitor se déploie dans le même namespace que là où vous avez installé le chart kube-prometheus-stack ;
  • Le label release: kube-prometheus-stack est obligatoire pour que le ServiceMonitor soit surveillé par Prometheus. Néanmoins, il est possible de modifier cette configuration dans le chart de kube-prometheus-stack avec le paramètre serviceMonitorSelectorNilUsesHelmValues: false ;
  • Partie endpoints, http-metrics est le nom du port au sein du Service PostgreSQL qui expose les métriques ;
  • Partie namespaceSelector dans matchNames, il est important de spécifier le nom du namespace de PostgreSQL contenant le service ;
  • Partie selector, les labels sont ceux du Service PostgreSQL qui expose les métriques.

Une fois le ServiceMonitor créé, vous devriez voir le point de terminaison au sein de l'interface de Prometheus :

kube-prometheus-stack-prometheus-target

Créer des règles avec l'objet PrometheusRule

Avec le ServiceMonitor, Prometheus récupère nos métriques par intervalles réguliers. Il convient maintenant de créer des règles pour notre base de données PostgreSQL de manière à détecter des comportements anormaux.

Plutôt que d'écrire ces règles en partant de zéro, je vous conseille ce site : Awesome Prometheus alerts. Il concentre une multitude de règles en fonction de plusieurs catégories de services ou d'applications.

Voici un exemple de fichier YAML avec l'objet PrometheusRule et la première règle Prometheus PostgreSQLDown :

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  labels:
    release: kube-prometheus-stack
  name: postgresql
  namespace: kube-prometheus-stack
spec:
  groups:
  - name: PostgreSQL
    rules:
    - alert: PostgreSQLDown
      annotations:
        description: |-
          PostgreSQL instance is down
            VALUE = {{ $value }}
            LABELS = {{ $labels }}
        summary: PostgreSQL down (instance {{ $labels.instance }})
      expr: pg_up == 0
      for: 0m
      labels:
        severity: critical
[...]

Ici aussi, le label release: kube-prometheus-stack est obligatoire, à moins de modifier dans le chart le paramètre ruleSelectorNilUsesHelmValues avec une valeur à false.

Une fois l'objet PrometheusRule déployé dans le cluster, nos règles apparaissent dans l'interface de Prometheus :

kube-prometheus-stack-prometheus-rules

Configurer un tableau de bord dans Grafana

Dernière étape, l'aspect visualisation avec la création d'un tableau de bord dans Grafana.

Comme pour la partie du dessus, l'idée n'est pas de créer un tableau de bord en partant de rien. Grafana met à disposition plusieurs tableaux de bord préconstruits et facilement réutilisables.

Pour configurer un tableau de bord au sein de Grafana, pas besoin de créer d'objets spécifiques dans ce cas précis. Une ConfigMap suffit sans oublier d'initialiser le label grafana_dashboard: "1".

apiVersion: v1
data:
  postgresql-dashboard.json: |-
[...]
kind: ConfigMap
metadata:
  name: postgresql-dashboard
  labels:
    grafana_dashboard: "1"

kube-prometheus-stack-prometheus-grafana

Récapitulatif

Voici un schéma qui regroupe l'ensemble des actions nécessaires pour surveiller vos applications dans Kubernetes. Je me suis basé sur un schéma d'OpenShift que j'ai enrichi notamment avec les PrometheusRule et les ConfigMap pour les tableaux de bord de Grafana.

kube-prometheus-stack-recap-diagram

Le mot de la fin

Bâtir une plateforme de supervision n'est pas chose aisée, même en se basant sur des règles Prometheus ou tableaux de bord Grafana proposés par la communauté, cela demandera de l'affinage au cours du temps. Notamment pour ce qui est d'ajuster les seuils pour déclencher ou non des alertes.

Néanmoins, cette trousse à outils kube-prometheus-stack composé de Prometheus, Grafana et Alertmanager permet d'obtenir très rapidement un résultat concluant tout en utilisant plusieurs solutions qui sont référencées comme standard du marché.

J'ai trouvé intéressant de faire un article dessus notamment pour montrer l'ensemble des étapes nécessaires pour superviser vos applications de bout en bout.