Pré-requis
- Un cluster GKE up and running
- Connaissance de base de Kubernetes et GitOps
- ArgoCD installé et configuré
Étapes
1. Qu’est ce qu’on va installer ?
| Outil | Description |
|---|---|
| Prometheus | Système de surveillance open-source qui collecte et stocke des métriques sous forme de séries temporelles en interrogeant périodiquement des endpoints HTTP. |
| Kube State Metrics | Service Kubernetes qui expose l’état des objets du cluster (pods, deployments, nodes…) sous forme de métriques consommables par Prometheus. |
| Grafana | Plateforme de visualisation qui permet de créer des dashboards interactifs à partir de sources de données comme Prometheus. |
| Alertmanager | Composant de l’écosystème Prometheus qui gère le routage, le regroupement et l’envoi des alertes vers des canaux de notification (Slack, e-mail, PagerDuty…). |
| Loki | Système d’agrégation de logs inspiré de Prometheus, conçu pour indexer uniquement les métadonnées des logs afin de réduire les coûts de stockage. |
| Alloy | Agent de collecte de données de Grafana Labs, successeur de Grafana Agent, capable de collecter métriques, logs et traces pour les acheminer vers différents backends. |
1. Installation de la kube-prometheus-stack (Prometheus + Grafana + Alertmanager)
Si vous avez suivi l’article précédent, rien de plus simple : il suffit d’ajouter une nouvelle application dans apps/ dans notre repo de CD.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: kube-prometheus-stack
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://prometheus-community.github.io/helm-charts
chart: kube-prometheus-stack
targetRevision: 86.0.1
helm:
releaseName: kube-prometheus-stack
valueFiles: []
values: |
grafana:
enabled: true
adminPassword: admin
service:
type: ClusterIP
prometheus:
prometheusSpec:
retention: 7d
resources:
requests:
cpu: 200m
memory: 512Mi
limits:
memory: 2Gi
storageSpec: {}
alertmanager:
enabled: true
kubeStateMetrics:
enabled: true
nodeExporter:
enabled: true
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
On push ce fichier kube-prometheus-stack.yaml et Argo se charge de déployer la stack de monitoring dans notre cluster.
Après quelques minutes d’attente, vous devriez voir les pods de Prometheus, Grafana et Alertmanager en cours d’exécution dans le namespace monitoring :
kubectl get pods -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-kube-prometheus-stack-alertmanager-0 2/2 Running 0 2m30s
kube-prometheus-stack-admission-create-ljf79 0/1 Pending 0 41s
kube-prometheus-stack-grafana-6ddb85bf55-j5shg 3/3 Running 0 2m35s
kube-prometheus-stack-kube-state-metrics-5fc57bf8f9-vhfhq 1/1 Running 0 2m35s
kube-prometheus-stack-operator-585c4957f7-2r772 1/1 Running 0 2m35s
prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 2m30s
---
Grafana est désormais accessible via un port-forwarding :
kubectl port-forward -n monitoring svc/kube-prometheus-stack-grafana 3000:80
Rendez-vous sur http://localhost:3000 et connectez-vous avec les identifiants admin/admin.
Cliquez ensuite sur “Dashboards” pour voir la liste des dashboards disponibles par défaut avec la chart :

3. Collecte des Logs avec Loki
Là encore il suffit de créer une nouvelle application ArgoCD qui pointe vers le chart Helm de Loki pour déployer un stack de collecte de logs dans notre cluster.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: loki
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://grafana.github.io/helm-charts
chart: loki
targetRevision: 7.0.0
helm:
releaseName: loki
values: |
deploymentMode: SingleBinary
loki:
auth_enabled: false
commonConfig:
replication_factor: 1
storage:
type: filesystem
schemaConfig:
configs:
- from: "2024-01-01"
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
singleBinary:
replicas: 1
persistence:
size: 10Gi
read:
replicas: 0
write:
replicas: 0
backend:
replicas: 0
gateway:
enabled: true
chunksCache:
enabled: false
resultsCache:
enabled: false
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
- ServerSideApply=true
Enfin il faut indiquer à Grafana où trouver Loki pour pouvoir visualiser les logs dans notre dashboard.
Pour cela, on ajoute une datasource Loki dans Grafana en utilisant un ConfigMap Kubernetes :
spec:
source:
helm:
values: |
grafana:
additionalDataSources:
- name: Loki
type: loki
access: proxy
url: http://loki-gateway.monitoring.svc.cluster.local
jsonData:
maxLines: 1000
Et voilà le résultat :

4. Collecte des logs de notre application
Pour l’heure, les logs de notre application nginx ne sont pas collectés par Loki. Nous allons déployer Alloy en tant que DaemonSet dans notre cluster pour collecter les logs de tous les pods et les envoyer à Loki, il s’agit ici encore d’ajouter une nouvelle application ArgoCD dans notre repo de CD :
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: alloy
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://grafana.github.io/helm-charts
chart: alloy
targetRevision: 1.16.1
helm:
releaseName: alloy
values: |
alloy:
configMap:
content: |
discovery.kubernetes "pods" {
role = "pod"
}
discovery.relabel "pods" {
targets = discovery.kubernetes.pods.targets
rule {
source_labels = ["__meta_kubernetes_namespace"]
target_label = "namespace"
}
rule {
source_labels = ["__meta_kubernetes_pod_name"]
target_label = "pod"
}
rule {
source_labels = ["__meta_kubernetes_pod_container_name"]
target_label = "container"
}
rule {
source_labels = ["__meta_kubernetes_pod_label_app"]
target_label = "app"
}
}
loki.source.kubernetes "pods" {
targets = discovery.relabel.pods.output
forward_to = [loki.write.default.receiver]
}
loki.write "default" {
endpoint {
url = "http://loki-gateway.monitoring.svc.cluster.local/loki/api/v1/push"
}
}
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
La configuration utilise la syntaxe River d’Alloy pour :
- Découvrir tous les pods Kubernetes
- Extraire les labels namespace, pod, container et app
- Envoyer les logs vers votre Loki gateway
- Alloy sera déployé comme DaemonSet et collectera les logs de votre nginx. Dans Grafana, vous pourrez les consulter avec :
{namespace=“demo”, app=“nginx”}
De retour sur Grafana, la liste des filtres disponibles est désormais bien plus fournie :


Résultat
Dans cet article nous avons vu comment installer une stack de monitoring complète sur Kubernetes avec Prometheus, Grafana et Loki, le tout déployé en GitOps via ArgoCD. Nous avons également vu comment collecter les logs de nos pods sur notre cluster avec Alloy et les visualiser dans Grafana.
Si vous avez suivi toutes les étapes de cet article vous devriez avoir les workloads suivantes :
kubectl get pods -n monitoring
NAME READY STATUS RESTARTS AGE
alertmanager-kube-prometheus-stack-alertmanager-0 2/2 Running 0 21m
alloy-jb2nf 2/2 Running 0 5m22s
kube-prometheus-stack-grafana-bf74d765f-4hzlt 3/3 Running 0 23m
kube-prometheus-stack-kube-state-metrics-6b747b7c5f-hjjwd 1/1 Running 0 23m
kube-prometheus-stack-operator-59c5d9f8c-q6phj 1/1 Running 0 23m
kube-prometheus-stack-prometheus-node-exporter-zhmfp 1/1 Running 0 23m
loki-0 2/2 Running 0 32m
loki-canary-55ccd5d799-wkc7t 1/1 Running 0 32m
loki-gateway-6df7c96bc9-l92d2 1/1 Running 0 32m
prometheus-kube-prometheus-stack-prometheus-0 2/2 Running 0 21m
kubectl get pods -n demo
NAME READY STATUS RESTARTS AGE
nginx-7489fb554f-hffjv 1/1 Running 0 33m
L’essentiel des travaux est disponible sur mon repo GitHub
Ce qui vient ensuite
Nous verrons comment exposer notre application à travers la Gateway API dans le prochain article de la série, stay tuned !
Sources :
