En 2026, un cluster Kubernetes moyen fait tourner des dizaines de microservices, plusieurs opérateurs et des pods qui naissent et meurent en quelques secondes. Les outils de supervision classiques, pensés pour des serveurs stables, ratent une bonne partie de cette activité. OpenTelemetry s’est imposé comme la réponse standard à ce problème, et une étape clé vient d’arriver : le Kubernetes Attributes Processor a atteint la version stable 1.0.0 en septembre 2026, livrée dans la branche OpenTelemetry Collector v0.161.0. Ce tutoriel vous montre comment installer cette chaîne d’observabilité de bout en bout sur un cluster Kubernetes, pas à pas, avec des manifestes que vous pouvez copier directement.
Selon le rapport Observability Survey 2024 de Grafana Labs, “OpenTelemetry was used or actively adopted by 85% of respondents in the observability survey” (Grafana Labs, Observability Survey Report 2024). Deux ans plus tôt, la Cloud Native Computing Foundation notait déjà que “OpenTelemetry was used by 49% of respondents’ organizations for cloud-native observability” (CNCF, Cloud Native Observability Microsurvey, 2022). La progression est nette, et elle s’explique par un besoin très concret : relier les traces, les métriques et les logs à la topologie Kubernetes elle-même (namespace, pod, déploiement, nœud) sans écrire de code de corrélation maison. C’est exactement le rôle du nouveau processor stable. Ce guide s’adresse aux équipes qui gèrent déjà un cluster en production ou en pré-production et qui veulent passer d’une supervision fragmentée à une observabilité Kubernetes cohérente, reliée au cloud computing au sens large.
Pour une équipe plateforme en France ou ailleurs en Europe, l’enjeu dépasse le simple confort de débogage. Un cluster qui répartit ses workloads entre plusieurs zones, voire entre plusieurs fournisseurs cloud, perd vite toute cohérence si chaque service garde sa propre convention de nommage pour ses métriques. En standardisant la collecte autour d’OpenTelemetry, une équipe peut déplacer un service d’AWS vers Azure ou vers un cluster on-premise sans réécrire son instrumentation, et sans perdre la capacité à corréler un pic de latence avec le nœud ou le namespace qui l’a produit. C’est ce standard de portabilité qui justifie l’effort de migration, bien plus que la nouveauté de la version 1.0.0 du processor à elle seule.
OpenTelemetry en bref : traces, métriques, logs et le nouveau processor Kubernetes
OpenTelemetry regroupe trois signaux sous un même standard ouvert : les traces (le chemin d’une requête à travers les services), les métriques (compteurs, histogrammes, jauges) et les logs. Chaque signal est produit par une application instrumentée, envoyé via le protocole OTLP, puis traité par un Collector, un binaire qui reçoit, transforme et réexpédie la télémétrie vers un ou plusieurs backends. Sur Kubernetes, ce Collector tourne soit en DaemonSet (un exemplaire par nœud), soit en Deployment centralisé (souvent appelé Gateway), soit dans les deux modes combinés.
Le transport entre l’application et le Collector repose sur OTLP, un protocole qui accepte indifféremment gRPC ou HTTP/protobuf. Ce choix compte en pratique : gRPC multiplexe plusieurs flux sur une seule connexion et réduit la charge sur un pod qui émet beaucoup de spans, tandis que HTTP reste plus simple à déboguer avec des outils génériques comme curl ou un proxy de capture réseau. La plupart des SDK officiels (Python, Java, Node.js, Go, .NET) exposent les deux options via une simple variable d’environnement, ce qui permet de basculer de l’un à l’autre sans recompiler l’application.
Le changement majeur de cette rentrée 2026 concerne le k8sattributes processor. Avant sa stabilisation, enrichir une trace avec le nom du pod, du déploiement ou du nœud d’origine demandait une configuration expérimentale, sujette à rupture d’une version à l’autre. Depuis la version 1.0.0, publiée sur le blog officiel, le composant a satisfait les critères de stabilité concernant les tests, les benchmarks, la documentation et la stabilité de sa télémétrie, selon l’annonce d’OpenTelemetry. Concrètement, cela signifie que la configuration que vous écrivez aujourd’hui ne cassera plus au prochain correctif mineur du Collector.
Autre repère de version utile : les conventions sémantiques OpenTelemetry (les noms standardisés des attributs comme k8s.pod.name ou k8s.namespace.name) sont passées en état stable avec la version 1.42.0, publiée en juin 2026. Ces conventions évitent que chaque équipe invente ses propres noms d’attributs, ce qui aurait rendu l’enrichissement Kubernetes à peu près inutile pour corréler des données entre équipes. Le dépôt de publication du site OpenTelemetry, consultable sur GitHub, retrace ces jalons de version au fil des mois.
Prérequis techniques et versions à utiliser
Avant de commencer, vérifiez que votre environnement correspond à ces versions. Le tutoriel fonctionne aussi bien sur un cluster local que sur un cluster managé AWS, Azure ou GCP, du moment que vous disposez des droits pour installer des CRD (Custom Resource Definitions).
| Outil | Version à utiliser | Rôle dans le tutoriel |
|---|---|---|
| Kubernetes | 1.34 ou 1.37 (minikube, kind ou cluster managé) | Cluster cible de l’instrumentation |
| Helm | Dernière version 3.x stable | Installe l’opérateur et les charts associés |
| OpenTelemetry Operator | Chart Helm officiel open-telemetry/opentelemetry-operator | Gère les CRD OpenTelemetryCollector et Instrumentation |
| OpenTelemetry Collector Contrib | 0.161.0 | Reçoit, enrichit et exporte traces, métriques, logs |
| cert-manager | Dernière version stable | Fournit les certificats des webhooks de l’opérateur |
| kubectl | Compatible avec la version du cluster | Administration du cluster |
| Prometheus (kube-prometheus-stack) | Dernière version du chart | Stockage des métriques exportées |
| Grafana | Dernière version | Tableaux de bord et alerting |
| Istio (optionnel) | 1.31 (sortie le 27 août 2026) | mTLS et télémétrie réseau en complément |
Ces versions ne sont pas interchangeables au hasard : l’opérateur OpenTelemetry vérifie la version de l’API Kubernetes au moment de l’installation des CRD, et une image de Collector trop ancienne face à un cluster récent peut échouer silencieusement sur certains champs de configuration récemment introduits. Si vous opérez en environnement isolé (air-gapped) ou derrière un registre d’images interne, pensez à rapatrier l’image otel/opentelemetry-collector-contrib:0.161.0 et le chart Helm de l’opérateur avant de commencer, plutôt que de découvrir un blocage réseau en plein milieu du tutoriel.
Si vous partez de zéro, commencez par monter un cluster local avant de suivre ce guide. Notre tutoriel de création d’un cluster Kubernetes avec minikube couvre exactement cette étape préalable en douze points, et vous donnera un cluster fonctionnel en moins d’une heure.
Vue d’ensemble de l’architecture du tutoriel
L’architecture cible comporte quatre blocs. Premier bloc : un Collector en mode DaemonSet, installé sur chaque nœud, qui reçoit la télémétrie OTLP émise localement par les applications. Deuxième bloc : un Collector en mode Deployment, le Gateway, qui centralise les flux venant de tous les agents, applique le traitement lourd (enrichissement, filtrage, échantillonnage) et exporte vers les backends. Troisième bloc : les backends eux-mêmes, Prometheus pour les métriques et un système de traces compatible OTLP. Quatrième bloc : les applications instrumentées, soit via un SDK natif, soit via l’injection automatique proposée par l’opérateur. Une équipe qui découvre OpenTelemetry n’a pas besoin de déployer les quatre blocs le premier jour : commencer par le DaemonSet seul, sur un unique namespace de test, suffit à valider que la chaîne fonctionne avant d’étendre la couverture au reste du cluster.
Ce découpage en agent et gateway n’est pas un détail cosmétique. Il évite que chaque pod applicatif ouvre une connexion sortante directe vers un backend externe, ce qui poserait un problème de sécurité réseau et de traçabilité des flux sortants. Toute la télémétrie transite par le Gateway, qui devient le point unique de contrôle, de filtrage et d’application des règles FinOps sur le volume collecté.
Le tableau suivant résume quand privilégier chaque mode de déploiement du Collector, un choix que beaucoup d’équipes tranchent mal au premier essai.
| Mode | Où il tourne | Avantage principal | Limite à connaître |
|---|---|---|---|
| DaemonSet (agent) | Un pod par nœud | Faible latence réseau, accès direct aux logs du nœud | Ne peut pas appliquer de règles globales inter-nœuds |
| Deployment (gateway) | Un petit pool de répliques centralisées | Filtrage, échantillonnage et export centralisés | Point de passage obligé, donc cible critique à surveiller |
| Agent + Gateway combinés | Les deux en parallèle | Combine proximité locale et contrôle centralisé | Deux configurations à maintenir en cohérence |
Étapes 1 à 3 : préparer le cluster et installer l’opérateur OpenTelemetry
Étape 1 : créer les namespaces dédiés
Isolez la stack d’observabilité dans son propre namespace, séparé des applications métier. Cela simplifie les règles RBAC et les quotas de ressources appliqués plus loin dans ce tutoriel.
kubectl create namespace observability
kubectl create namespace opentelemetry-operator-system
kubectl label namespace observability purpose=telemetry
Étape 2 : installer cert-manager puis l’opérateur OpenTelemetry via Helm
L’opérateur a besoin de cert-manager pour signer les certificats de ses webhooks d’admission. Sans ces certificats, l’API Kubernetes refuse de valider les ressources OpenTelemetryCollector et Instrumentation au moment de leur création, et l’erreur renvoyée mentionne alors un échec de connexion au webhook plutôt qu’un problème de certificat, ce qui peut dérouter lors d’un premier déploiement. Installez cert-manager d’abord, attendez qu’il soit prêt, puis ajoutez le dépôt Helm officiel d’OpenTelemetry. Notre tutoriel Helm sur Kubernetes détaille la logique des charts si vous découvrez l’outil.
helm repo add jetstack https://charts.jetstack.io
helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm repo update
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager --create-namespace \
--set crds.enabled=true
kubectl wait --for=condition=Available deployment/cert-manager \
-n cert-manager --timeout=120s
helm install opentelemetry-operator open-telemetry/opentelemetry-operator \
--namespace opentelemetry-operator-system \
--set admissionWebhooks.certManager.enabled=true
Étape 3 : vérifier que l’opérateur tourne et que les CRD sont enregistrées
Avant d’aller plus loin, validez que le pod de l’opérateur est passé en état Running et que les deux CRD attendues (OpenTelemetryCollector et Instrumentation) existent bien sur le cluster.
kubectl get pods -n opentelemetry-operator-system
kubectl get crd | grep opentelemetry.io
Vous devez voir deux lignes de sortie correspondant aux CRD opentelemetrycollectors.opentelemetry.io et instrumentations.opentelemetry.io. Si rien ne s’affiche, l’installation Helm a échoué silencieusement et il faut consulter la section dépannage plus loin dans cet article.
Étapes 4 à 6 : déployer le Collector et configurer le processor Kubernetes
Étape 4 : déployer le Collector en mode DaemonSet (agent local)
Ce premier Collector tourne sur chaque nœud et reçoit la télémétrie OTLP émise par les pods locaux via gRPC (port 4317) ou HTTP (port 4318). Il applique déjà le k8sattributes processor stable pour enrichir chaque span avec les métadonnées du pod d’origine.
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otel-agent
namespace: observability
spec:
mode: daemonset
image: otel/opentelemetry-collector-contrib:0.161.0
config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
k8sattributes:
auth_type: serviceAccount
extract:
metadata:
- k8s.pod.name
- k8s.namespace.name
- k8s.deployment.name
- k8s.node.name
batch: {}
exporters:
otlp:
endpoint: otel-gateway-collector.observability.svc:4317
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [k8sattributes, batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [k8sattributes, batch]
exporters: [otlp]
Un point à retenir : le processor k8sattributes doit toujours être placé avant le batch dans la liste des processors. L’ordre déclaré dans le fichier YAML est l’ordre d’exécution réel, et un batch placé en premier regrouperait les spans avant qu’ils aient reçu leurs métadonnées Kubernetes.
Étape 5 : déployer le Collector Gateway et l’export vers Prometheus
Le Gateway centralise les flux de tous les agents et exporte les métriques vers Prometheus via remote write. C’est aussi lui qui décide de l’échantillonnage final des traces avant envoi au backend de traces.
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otel-gateway
namespace: observability
spec:
mode: deployment
replicas: 2
image: otel/opentelemetry-collector-contrib:0.161.0
config:
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
processors:
batch: {}
tail_sampling:
policies:
- name: erreurs-toujours-gardees
type: status_code
status_code: { status_codes: [ERROR] }
- name: echantillon-25-pourcent
type: probabilistic
probabilistic: { sampling_percentage: 25 }
exporters:
prometheusremotewrite:
endpoint: "http://prometheus-server.observability.svc:9090/api/v1/write"
otlp/tempo:
endpoint: tempo.observability.svc:4317
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [tail_sampling, batch]
exporters: [otlp/tempo]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheusremotewrite]
Étape 6 : vérifier le déploiement des deux Collectors
Appliquez les deux manifestes puis contrôlez que les pods du DaemonSet (un par nœud) et du Deployment Gateway (deux répliques) sont bien en état Running.
kubectl apply -f otel-agent.yaml
kubectl apply -f otel-gateway.yaml
kubectl get opentelemetrycollectors -n observability
kubectl get pods -n observability -o wide
Étapes 7 à 9 : instrumenter l’application et exporter traces, métriques et logs
Étape 7 : créer la ressource Instrumentation
L’opérateur sait injecter automatiquement un agent de télémétrie dans vos pods, sans modifier le code applicatif, via une ressource Instrumentation et une simple annotation sur le déploiement cible.
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: otel-instrumentation
namespace: default
spec:
exporter:
endpoint: http://otel-agent-collector.observability.svc:4318
propagators:
- tracecontext
- baggage
sampler:
type: parentbased_traceidratio
argument: "0.25"
python:
env:
- name: OTEL_SERVICE_NAME
value: "panier-api"
Étape 8 : annoter le déploiement applicatif pour activer l’injection
Ajoutez l’annotation correspondant au langage de votre service dans le template de pod. Redéployez ensuite pour que l’opérateur injecte le conteneur sidecar d’instrumentation lors du redémarrage des pods.
kubectl patch deployment panier-api -n default -p \
'{"spec":{"template":{"metadata":{"annotations":{"instrumentation.opentelemetry.io/inject-python":"true"}}}}}'
kubectl rollout restart deployment/panier-api -n default
kubectl rollout status deployment/panier-api -n default
Étape 9 : centraliser les logs applicatifs
Pour les logs, ajoutez un receiver filelog sur l’agent DaemonSet, pointé vers les fichiers de logs des conteneurs sur le nœud. Évitez d’activer ce même receiver sur le Gateway : un seul chemin de collecte de logs doit exister par pod, sous peine de duplication.
Pensez aussi à la rétention. Les logs bruts pèsent généralement bien plus lourd que les traces ou les métriques équivalentes, et les conserver indéfiniment au même niveau de détail dans le backend central revient cher sans apporter de valeur au-delà de quelques semaines. Une politique courante consiste à garder les logs complets sept à quatorze jours, puis à ne conserver que les logs de niveau erreur ou avertissement au-delà, en s’appuyant sur le champ severity déjà présent dans chaque enregistrement OTLP.
receivers:
filelog:
include:
- /var/log/pods/*/*/*.log
operators:
- type: container
service:
pipelines:
logs:
receivers: [filelog]
processors: [k8sattributes, batch]
exporters: [otlp]
Étapes 10 à 12 : FinOps, sécurité RBAC/mTLS et scaling du Collector
Étape 10 : restreindre les droits RBAC du Collector
Le processor k8sattributes interroge l’API Kubernetes pour résoudre les métadonnées des pods. Il a donc besoin d’un ClusterRole dédié, limité en lecture seule aux ressources strictement nécessaires.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: otel-k8sattributes
rules:
- apiGroups: [""]
resources: ["pods", "namespaces", "nodes"]
verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
resources: ["replicasets", "deployments"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: otel-k8sattributes-binding
subjects:
- kind: ServiceAccount
name: otel-agent-collector
namespace: observability
roleRef:
kind: ClusterRole
name: otel-k8sattributes
apiGroup: rbac.authorization.k8s.io
Étape 11 : chiffrer les flux internes avec mTLS (Istio 1.31 optionnel)
Si votre cluster utilise déjà un maillage de services, Istio 1.31, sorti le 27 août 2026, permet d’imposer le chiffrement mTLS entre les pods applicatifs et les Collectors sans toucher au code. C’est pertinent dès que la télémétrie traverse plusieurs namespaces ou zones réseau sensibles, selon les notes de version publiées par le projet Istio.
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: observability
spec:
mtls:
mode: STRICT
Étape 12 : relier la télémétrie à l’analyse FinOps par namespace
Puisque chaque métrique et chaque trace porte désormais l’attribut k8s.namespace.name et k8s.deployment.name, il devient possible de ventiler le coût d’infrastructure par équipe ou par service, sans outil de facturation tiers. Associez ces attributs aux étiquettes de vos nœuds et à vos rapports de capacité pour repérer les workloads les plus coûteux. Si vous gérez aussi des charges AWS, notre tutoriel FinOps AWS complète cette démarche côté facturation cloud. Pour les pics de charge qui faussent ces analyses de coût, pensez à relier cette observabilité à un autoscaling piloté par événements, comme décrit dans notre tutoriel KEDA sur Kubernetes.
Étape 13 : construire les tableaux de bord Grafana et l’alerting
Une fois les métriques dans Prometheus, créez un dashboard Grafana filtrable par namespace et par déploiement, grâce aux attributs injectés par le processor stable. Si Grafana n’est pas encore installé sur votre cluster, notre tutoriel Prometheus et Grafana sur Kubernetes couvre l’installation complète de la stack en douze étapes.
Configurez ensuite deux types d’alertes distinctes. La première surveille la latence p99 par service, calculée à partir des histogrammes de durée de requête. La seconde surveille la santé du Collector lui-même : spans rejetés, file d’attente d’export saturée, erreurs de connexion au backend. Un Collector qui tombe en panne silencieusement prive toute l’équipe de visibilité au moment précis où elle en a le plus besoin, généralement pendant un incident.
Traitez ces deux familles d’alertes avec des priorités différentes dans votre outil de gestion d’astreinte. Une alerte de latence applicative concerne l’équipe propriétaire du service concerné, identifiable directement grâce à l’attribut k8s.deployment.name. Une alerte sur la santé du Collector concerne l’équipe plateforme, puisqu’une dégradation à ce niveau affecte potentiellement tous les services du cluster en même temps, pas un seul d’entre eux.
Migrer une stack Prometheus existante sans tout casser
La majorité des clusters Kubernetes en production n’arrivent pas sur une page blanche : ils ont déjà un exporter Prometheus natif, des dashboards Grafana construits depuis des mois, et des alertes calibrées sur des noms de métriques précis. Remplacer tout cela d’un coup par une pipeline OpenTelemetry romprait ces alertes au pire moment. La bonne approche consiste à faire cohabiter les deux chemins de collecte le temps de la transition, plutôt que de couper l’ancien dès le premier déploiement.
Concrètement, laissez votre exporter Prometheus natif continuer à exposer son endpoint de scraping habituel, et ajoutez en parallèle le receiver prometheus côté Collector pour récupérer ces mêmes métriques sans toucher à l’application. Le Collector peut alors réexporter ces métriques vers le même serveur Prometheus, enrichies cette fois des attributs Kubernetes du k8sattributes processor. Gardez à l’esprit que le receiver prometheus du Collector respecte le même format d’exposition que l’exporter natif attendait déjà, ce qui veut dire qu’aucune application ne doit être modifiée pendant cette phase intermédiaire. Une fois que les dashboards Grafana ont été recréés avec les nouveaux labels et validés sur deux ou trois semaines de données réelles, vous pouvez retirer l’ancien chemin de scraping direct. Cette approche progressive évite de perdre l’historique d’alerte pendant la bascule, un point que beaucoup d’équipes négligent en se concentrant uniquement sur la partie traces du projet.
Exemples de sortie attendue
Après application des manifestes et redémarrage des pods, la commande suivante doit afficher les deux Collectors en cours d’exécution, avec leur nombre de répliques respectif.
$ kubectl get opentelemetrycollectors -n observability
NAME MODE VERSION READY
otel-agent daemonset 0.161.0 3/3
otel-gateway deployment 0.161.0 2/2
Une requête PromQL ciblant un déploiement précis grâce à l’attribut Kubernetes injecté renvoie un résultat filtré sans configuration supplémentaire côté Prometheus.
rate(http_server_duration_milliseconds_count{k8s_namespace_name="default", k8s_deployment_name="panier-api"}[5m])
Côté traces, chaque span affiché dans l’interface de votre backend doit désormais porter les attributs k8s.pod.name, k8s.node.name et k8s.deployment.name dans son panneau de métadonnées, sans ligne de code ajoutée dans le service panier-api lui-même.
Un log enrichi par le même pipeline doit afficher, dans sa section d’attributs, les mêmes clés que celles vues sur les traces. C’est ce qui permet de passer d’un log d’erreur à la trace correspondante en un clic dans la plupart des interfaces de visualisation.
{
"severity": "ERROR",
"body": "paiement refuse par la passerelle",
"attributes": {
"k8s.namespace.name": "default",
"k8s.pod.name": "panier-api-7d4f9c-x2k1p",
"k8s.deployment.name": "panier-api",
"k8s.node.name": "node-eu-west-3a-02",
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736"
}
}
Les pièges les plus courants à éviter
La plupart des incidents rencontrés après un premier déploiement ne viennent pas d’un bug du Collector lui-même, mais d’un choix de configuration fait trop vite au départ. Voici les erreurs qui reviennent le plus souvent dans les retours d’expérience d’équipes ayant déployé cette stack.
- Déployer uniquement des Collectors en DaemonSet sans Gateway central, ce qui multiplie les connexions sortantes directes vers le backend et complique tout filtrage global.
- Oublier de plafonner la cardinalité des attributs Kubernetes sur les métriques, ce qui fait grimper brutalement le volume stocké dans Prometheus.
- Mettre à jour l’image du Collector vers 0.161.0 sans relire les notes de version, alors que la stabilisation du k8sattributes processor change certains comportements par défaut.
- Laisser les flux OTLP en clair (insecure: true) en production entre les pods applicatifs et le Collector, au lieu de les réserver au seul environnement de développement.
- Confondre le rôle du sampler parentbased_traceidratio avec un filtre de rétention, ce qui fausse ensuite les statistiques de latence calculées sur un échantillon trop réduit.
- Activer l’auto-instrumentation sur tous les workloads d’un coup plutôt que namespace par namespace, ce qui rend impossible l’identification du service responsable en cas de régression de performance.
Dépannage : 8 problèmes fréquents et leurs solutions
Voici les incidents les plus signalés lors du déploiement de cette chaîne d’observabilité, avec la cause probable et la correction à appliquer. Avant de creuser plus loin, pensez à activer la télémétrie interne du Collector lui-même : il expose par défaut ses propres métriques de fonctionnement sur le port 8888, ce qui permet de voir immédiatement si le problème vient de la réception, du traitement ou de l’exportation, plutôt que de deviner en inspectant uniquement les logs du pod.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Pods du Collector en CrashLoopBackOff | Configuration YAML invalide (indentation ou champ inconnu) | Valider la configuration avec otelcol-contrib validate avant tout déploiement |
| Aucune métadonnée Kubernetes dans les traces | k8sattributes placé après batch dans la pipeline | Replacer k8sattributes immédiatement après le receiver, avant batch |
| Erreur RBAC Forbidden sur pods ou namespaces | ClusterRole absente ou mal liée au ServiceAccount du Collector | Appliquer le ClusterRole et le ClusterRoleBinding dédiés, en vérifiant que le nom du ServiceAccount référencé correspond exactement à celui généré par le manifeste OpenTelemetryCollector, car l’opérateur en dérive automatiquement le nom à partir du nom de la ressource |
| Spans reçus par l’agent mais jamais visibles côté backend | Endpoint OTLP du Gateway injoignable depuis les agents (DNS interne) | Vérifier le nom du Service Kubernetes et tester la connectivité avec kubectl exec et un client grpcurl |
| Prometheus sature en espace disque | Cardinalité trop élevée sur les attributs k8s.pod.name au niveau des métriques | Ajouter un processor attributes/metrics qui retire les labels à forte cardinalité avant exportation |
| L’opérateur Helm refuse de s’installer | cert-manager absent alors que les webhooks d’admission sont activés | Installer cert-manager en premier et attendre sa disponibilité avant d’installer l’opérateur |
| L’auto-instrumentation Python ne s’active jamais | Annotation absente ou appliquée sur le mauvais objet (Pod au lieu du template de Deployment) | Patcher le template du Deployment avec instrumentation.opentelemetry.io/inject-python puis relancer un rollout |
| Logs applicatifs dupliqués dans le backend | Le receiver filelog est actif à la fois sur l’agent et sur le Gateway | Ne conserver qu’un seul chemin de collecte des logs, sur l’agent DaemonSet uniquement |
Astuces avancées pour la production
Une fois la base en place, plusieurs ajustements améliorent la fiabilité et maîtrisent les coûts. D’abord, privilégiez l’échantillonnage à la fin de la chaîne (tail-based sampling), comme illustré à l’étape 5, plutôt qu’un échantillonnage décidé au niveau de chaque application. Cette approche garde systématiquement les traces qui contiennent une erreur, même si elles tombent en dehors de l’échantillon statistique, ce qui évite de perdre les cas les plus utiles au débogage.
Ensuite, surveillez la fiabilité des exporters eux-mêmes. Les exporters OTLP écrits en Rust ont gagné en septembre 2026, avec la release candidate 0.33.0 publiée le 18 du mois, un mécanisme de nouvelle tentative avec attente exponentielle et gigue (jitter) activé par défaut sur les protocoles HTTP et gRPC. Si votre Collector repose sur ce composant, vérifiez que cette configuration correspond à votre tolérance de latence réseau avant de la laisser telle quelle en production.
Troisième point, gardez un œil sur les conventions sémantiques. La stabilisation de la version 1.42.0 fige des noms d’attributs qui ne changeront plus, mais les versions de documentation publiées ensuite (1.54.0 en octobre 2026, puis 1.61.0 avec l’ajout du composable View matching côté SDK de métriques) continuent d’ajouter des capacités de filtrage fin et de compatibilité Prometheus renforcée. Relisez ces notes de version avant chaque montée de version du Collector, plutôt qu’après un incident.
Enfin, si votre organisation combine déjà Prometheus et OpenTelemetry, ce qui concerne près de 40 % des répondants selon le même rapport Grafana Labs, assurez-vous que les deux systèmes de labels restent cohérents entre eux. Un nom d’attribut différent entre une métrique native Prometheus et une métrique remontée via OTLP rend les tableaux de bord mixtes illisibles.
Si votre organisation opère plusieurs clusters, par exemple un cluster par région pour réduire la latence en edge compute, évitez de faire remonter chaque Gateway directement vers un backend central unique. Ajoutez un niveau intermédiaire de Collector régional qui agrège et pré-filtre avant l’envoi inter-région. Cela réduit le volume de données qui traverse les liaisons longue distance, et cela limite l’impact d’une panne réseau régionale sur la visibilité globale du reste de la flotte.
Côté répartition des coûts, évitez de tout facturer au prorata du nombre de pods : un service avec peu de pods mais un trafic de requêtes très élevé peut générer davantage de spans qu’un service avec beaucoup de réplicas mais peu sollicité. Préférez une ventilation basée sur le volume réel de télémétrie émis par namespace, mesuré directement sur les métriques internes du Collector, plutôt que sur une approximation construite à partir du nombre de ressources déployées.
Le projet complet : structure du dépôt
Pour retrouver facilement l’ensemble des manifestes de ce tutoriel, organisez votre dépôt de la façon suivante. Cette arborescence sépare clairement les Collectors, les règles RBAC, l’instrumentation applicative et les tableaux de bord.
otel-k8s-observabilite/
├── collector/
│ ├── otel-agent.yaml
│ └── otel-gateway.yaml
├── instrumentation/
│ └── instrumentation.yaml
├── rbac/
│ ├── clusterrole.yaml
│ └── clusterrolebinding.yaml
├── securite/
│ └── peerauthentication-istio.yaml
├── dashboards/
│ └── grafana-k8s-otel.json
└── README.md
Appliquez les dossiers dans cet ordre : rbac, puis collector, puis instrumentation, puis securite si vous utilisez Istio. Cet ordre respecte les dépendances : le Collector a besoin de son ClusterRole pour démarrer proprement, et l’instrumentation a besoin que l’agent Collector soit déjà joignable pour recevoir sa première trace.
Ajoutez un fichier Makefile minimal qui encapsule les commandes d’application et de vérification, afin qu’un nouveau membre de l’équipe puisse reproduire le déploiement sans relire l’intégralité de ce tutoriel. Une cible make deploy qui applique les dossiers dans le bon ordre, suivie d’une cible make check qui relance les commandes de vérification de l’étape 3 et de l’étape 6, suffit à transformer ce projet en une procédure répétable plutôt qu’en une suite de commandes copiées manuellement à chaque nouvel environnement.
Questions fréquentes
Faut-il utiliser le mode DaemonSet ou Deployment pour le Collector ?
Les deux, combinés. Le DaemonSet reçoit la télémétrie locale au plus près des pods, le Deployment Gateway centralise, filtre et exporte vers les backends. Utiliser seulement l’un des deux modes limite soit la proximité réseau, soit la capacité de filtrage global.
Le Kubernetes Attributes Processor v1.0.0 est-il rétrocompatible avec une configuration écrite pour une version antérieure ?
La stabilisation porte sur le comportement et la documentation du composant, mais une configuration écrite pour une version expérimentale antérieure doit être revalidée après migration, en particulier l’ordre des processors dans la pipeline.
OpenTelemetry remplace-t-il Prometheus ?
Non. OpenTelemetry standardise la collecte et le transport de la télémétrie, tandis que Prometheus reste un backend de stockage de métriques parmi d’autres destinations possibles. Les deux coexistent dans la majorité des déploiements observés par les enquêtes citées plus haut dans cet article.
Quel est l’impact sur les coûts de stockage des métriques ?
Un enrichissement Kubernetes mal maîtrisé augmente la cardinalité, donc le volume stocké. Limitez les attributs exportés aux seuls champs utiles au filtrage (namespace, déploiement), et retirez les attributs à cardinalité élevée comme le nom exact du pod sur les séries de métriques.
Peut-on combiner OpenTelemetry et Istio 1.31 ?
Oui, et c’est même recommandé si le cluster dispose déjà d’un maillage de services. Istio 1.31 gère le chiffrement mTLS entre les pods et le Collector, pendant qu’OpenTelemetry gère la collecte et l’enrichissement des signaux applicatifs.
Quelle version minimale de Kubernetes est nécessaire ?
Ce tutoriel a été rédigé pour des clusters en 1.34 ou 1.37. Les CRD utilisées par l’opérateur OpenTelemetry fonctionnent sur la plupart des versions supportées, mais vérifiez la compatibilité exacte dans la documentation de l’opérateur avant un déploiement en production. Sur un cluster plus ancien, testez d’abord l’installation sur un environnement de pré-production, car certains champs de configuration récents du Collector peuvent être ignorés silencieusement par une API Kubernetes qui ne les reconnaît pas encore.
Comment réduire le volume de traces en production sans perdre les cas importants ?
Activez le tail-based sampling au niveau du Gateway, avec une règle qui conserve systématiquement les traces en erreur et n’échantillonne que le trafic sans erreur. C’est la configuration présentée à l’étape 5 de ce tutoriel.
OpenTelemetry fonctionne-t-il de la même façon sur AWS, Azure et GCP ?
Le Collector et les CRD de l’opérateur sont identiques quel que soit le fournisseur cloud, car ils s’appuient uniquement sur l’API Kubernetes standard. Seuls les exporters finaux changent, selon que vous visez un backend géré par votre fournisseur ou un backend tiers compatible OTLP.
Faut-il redémarrer toute l’application pour activer l’auto-instrumentation ?
Seuls les pods concernés par l’annotation redémarrent, via un rollout restart. L’opérateur injecte l’agent au moment de la création du pod, il n’existe pas de mécanisme d’injection à chaud sur un pod déjà démarré.
Cette architecture fonctionne-t-elle avec des fonctions serverless comme AWS Lambda ou Google Cloud Functions ?
Partiellement. Les couches managées serverless n’exposent pas toujours un accès réseau direct à un Collector DaemonSet, puisqu’il n’y a pas de nœud Kubernetes persistant sous-jacent accessible. Dans ce cas, le SDK applicatif exporte généralement ses spans directement vers un Collector Gateway distant, en sautant l’étape d’enrichissement local par nœud.
Combien de répliques prévoir pour le Collector Gateway en production ?
Il n’existe pas de chiffre universel, le bon dimensionnement dépend du volume de spans par seconde et de la complexité des processors activés, en particulier le tail-based sampling qui est plus coûteux en mémoire que l’échantillonnage probabiliste simple. Commencez par deux répliques, surveillez les métriques internes du Collector exposées sur le port 8888, et ajustez en fonction de la saturation observée de la file d’attente d’export.
