For AI agents: the complete documentation index is available at https://docs.ovhcloud.com/fr/llms.txt, the full documentation bundle is available at https://docs.ovhcloud.com/fr/llms-full.txt, and this page is available as Markdown at https://docs.ovhcloud.com/fr/guides/public-cloud/containers-orchestration/managed-kubernetes/tracing-jaeger.md.

Tracing distribué avec Jaeger sur un OVHcloud Managed Kubernetes Service

Voir en Markdown

Découvrez comment mettre en place le tracing distribué sur OVHcloud Managed Kubernetes Service avec Jaeger.

Objectif

Jaeger est une plateforme open source de tracing distribué.

Jaeger

Elle peut être utilisée pour superviser des systèmes distribués basés sur des microservices :

  • Propagation de contexte distribué
  • Supervision des transactions distribuées
  • Analyse des causes racines
  • Analyse des dépendances entre services
  • Optimisation des performances et de la latence

Jaeger contient plusieurs composants :

Jaeger

Pour en savoir plus, consultez la documentation sur l'architecture et les composants de Jaeger.

Dans ce guide, vous allez :

  • Installer Jaeger Operator
  • Déployer les composants Jaeger
  • Accéder à l'interface utilisateur
  • Déployer votre application instrumentée
  • Visualiser les traces

Vous pouvez utiliser la fonction Reset cluster dans la section Public Cloud de l' pour réinitialiser votre cluster avant de suivre ce tutoriel.

Prérequis

Ce tutoriel suppose que vous disposez déjà d'un cluster OVHcloud Managed Kubernetes fonctionnel et de connaissances de base sur son fonctionnement. Pour en savoir plus sur ces sujets, consultez le guide de démarrage rapide d'OVHcloud Managed Kubernetes Service.

Vous devez également avoir installé Helm sur votre poste de travail et sur votre cluster. Reportez-vous au tutoriel Comment installer Helm sur OVHcloud Managed Kubernetes Service.

En pratique

Ce guide vous montre comment déployer Jaeger en tant que backend de la plateforme de tracing distribué, puis comment déployer votre application instrumentée qui enverra ses traces à Jaeger.

Installation de Jaeger

Pour ce tutoriel, nous utilisons le chart Helm de Jaeger.

Ajoutez le dépôt Helm de Jaeger :

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

Ces commandes ajoutent le dépôt Helm de Jaeger à votre dépôt local de charts Helm et mettent à jour les dépôts de charts installés :

$ helm repo add jaegertracing https://jaegertracing.github.io/helm-charts
helm repo update
"jaegertracing" has been added to your repositories
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "sealed-secrets" chart repository
...
...Successfully got an update from the "prometheus-community" chart repository
Update Complete. ⎈Happy Helming!⎈

Le dépôt Jaeger fournit deux charts : jaeger et jaeger-operator. Pour ce guide, vous allez déployer le chart jaeger-operator, qui permet de configurer facilement une installation minimale.

Pour en savoir plus sur Jaeger Operator pour Kubernetes, consultez la documentation officielle.

Installez la dernière version de Jaeger avec la commande helm install :

helm install jaeger-operator jaegertracing/jaeger-operator --namespace observability --create-namespace --set rbac.clusterRole=true

Cette commande installe la dernière version de Jaeger Operator ainsi que le namespace observability :

$ helm install jaeger-operator jaegertracing/jaeger-operator --namespace observability --create-namespace --set rbac.clusterRole=true
manifest_sorter.go:192: info: skipping unknown hook: "crd-install"
NAME: jaeger-operator
LAST DEPLOYED: Thu Mar 17 12:06:49 2022
NAMESPACE: observability
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
jaeger-operator is installed.

Check the jaeger-operator logs
  export POD=$(kubectl get pods -l app.kubernetes.io/instance=jaeger-operator -lapp.kubernetes.io/name=jaeger-operator --namespace observability --output name)
  kubectl logs $POD --namespace=observability

Grâce au remplacement de la valeur rbac.clusterRole=true, vous demandez à l'opérateur de surveiller tous les namespaces.

Vérifiez que Jaeger Operator est bien en cours d'exécution :

kubectl get pod -n observability
$ kubectl get pod -n observability
NAME                               READY   STATUS    RESTARTS   AGE
jaeger-operator-67f8dd68c9-5qj26   1/1     Running   0          3m5s

La méthode la plus simple pour créer une instance Jaeger consiste à créer un fichier YAML qui installera l'image AllInOne par défaut. Cette image « all-in-one » regroupe : agent, collector, query, ingester et l'interface utilisateur de Jaeger au sein d'un seul pod, en utilisant par défaut un stockage en mémoire.

Pour ce guide, vous allez déployer les composants Jaeger selon cette méthode simple, adaptée au développement, aux tests et aux démonstrations, mais pour une stratégie de production, consultez la documentation officielle.

Une fois que le pod jaeger-operator du namespace observability est prêt, créez un fichier jaeger.yaml avec le contenu suivant :

apiVersion: jaegertracing.io/v1
kind: Jaeger
metadata:
  name: jaeger
spec:
  query:
    serviceType: LoadBalancer
Info

Dans ce fichier manifeste YAML, vous spécifiez que vous souhaitez accéder à l'interface utilisateur de Jaeger (jaeger-query) via un Load Balancer.

Puis appliquez-le :

kubectl apply -f jaeger.yaml

Ces commandes créent une nouvelle CRD Jaeger ainsi qu'une instance nommée jaeger :

$ kubectl apply -f jaeger.yaml
jaeger.jaegertracing.io/jaeger created

Vous pouvez maintenant vérifier que l'instance Jaeger est bien en cours d'exécution avec les commandes suivantes :

kubectl get jaeger
kubectl get pods -l app.kubernetes.io/instance=jaeger

Ces commandes permettent de vérifier que les instances ont bien été créées, de lister les objets Jaeger et de lister les pods en cours d'exécution :

$ kubectl get jaeger
NAME       STATUS    VERSION   STRATEGY   STORAGE   AGE
jaeger   Running   1.30.0    allinone   memory    4s

$ kubectl get pods -l app.kubernetes.io/instance=jaeger
NAME                        READY   STATUS    RESTARTS   AGE
jaeger-59ccc99bcc-zpscb   1/1     Running   0          80s

Vous pouvez également vérifier que tous les services Jaeger ont bien été déployés :

$ kubectl get svc -l app=jaeger
NAME                          TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                                  AGE
jaeger-agent                ClusterIP      None           <none>           5775/UDP,5778/TCP,6831/UDP,6832/UDP      3d21h
jaeger-collector            ClusterIP      10.3.197.39    <none>           9411/TCP,14250/TCP,14267/TCP,14268/TCP   3d21h
jaeger-collector-headless   ClusterIP      None           <none>           9411/TCP,14250/TCP,14267/TCP,14268/TCP   3d21h
jaeger-query                LoadBalancer   10.3.114.168   51.210.210.101   16686:30598/TCP,16685:30835/TCP          3d21h

Accès à l'interface utilisateur de Jaeger

Vous pouvez maintenant récupérer l'URL de l'interface utilisateur de Jaeger avec la commande suivante :

export JAEGER_URL=$(kubectl get svc jaeger-query -o jsonpath='{.status.loadBalancer.ingress[].ip}')
echo Jaeger URL: http://$JAEGER_URL:16686

Vous devriez obtenir le résultat suivant :

$ export JAEGER_URL=$(kubectl get svc jaeger-query -o jsonpath='{.status.loadBalancer.ingress[].ip}')

$ echo Jaeger URL: http://$JAEGER_URL:16686
Jaeger URL: http://51.210.210.101:16686

Ouvrez votre navigateur et accédez à l'interface Jaeger.

Jaeger Query

Déployer votre application instrumentée

Pour relier votre application au backend Jaeger, vous devez utiliser un outil comme OpenTelemetry.

OpenTelemetry

OpenTelemetry est un ensemble d'outils, d'API et de SDK. Il permet d'instrumenter, de générer, de collecter et d'exporter des données de télémétrie (métriques, logs et traces) afin de vous aider à analyser les performances et le comportement de votre logiciel.

OpenTelemetry s'intègre avec des bibliothèques et frameworks populaires tels que Spring, Express, Quarkus, ainsi qu'avec de nombreux langages. Consultez la documentation pour découvrir comment intégrer votre application.

Pour ce guide, vous allez déployer une application Golang, instrumentée avec OpenTelemetry, qui enverra ses traces à un fournisseur : votre collector Jaeger.

Notre fichier main.go contient :

  • l'import des dépendances OpenTelemetry,
  • une méthode tracerProvider qui initie une connexion à un fournisseur Jaeger
  • une méthode main() qui se connecte au collector Jaeger précédemment déployé et crée et envoie un span chaque fois que la route HTTP / est appelée
package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	"os"
	"time"

	"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/attribute"
	"go.opentelemetry.io/otel/exporters/jaeger"
	"go.opentelemetry.io/otel/sdk/resource"
	tracesdk "go.opentelemetry.io/otel/sdk/trace"
	semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
)

const (
	service     = "go-what-is-my-pod-with-tracing"
	environment = "development"
	id          = 1
)

func tracerProvider(url string) (*tracesdk.TracerProvider, error) {
	// Create the Jaeger exporter
	exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
	if err != nil {
		return nil, err
	}
	tp := tracesdk.NewTracerProvider(
		// Always be sure to batch in production.
		tracesdk.WithBatcher(exp),
		// Record information about this application in a Resource.
		tracesdk.WithResource(resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceNameKey.String(service),
			attribute.String("environment", environment),
			attribute.Int64("ID", id),
		)),
	)
	return tp, nil
}

func main() {

	// Tracer
	tp, err := tracerProvider("http://jaeger-collector-headless.default.svc.cluster.local:14268/api/traces")
	if err != nil {
		log.Fatal(err)
	}

	// Register our TracerProvider as the global so any imported
	// instrumentation in the future will default to using it.
	otel.SetTracerProvider(tp)

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	// Cleanly shutdown and flush telemetry when the application exits.
	defer func(ctx context.Context) {
		// Do not make the application hang when it is shutdown.
		ctx, cancel = context.WithTimeout(ctx, time.Second*5)
		defer cancel()
		if err := tp.Shutdown(ctx); err != nil {
			log.Fatal(err)
		}
	}(ctx)

	tr := tp.Tracer("component-main")

	ctx, span := tr.Start(ctx, "hello")
	defer span.End()

	// HTTP Handlers
	helloHandler := func(w http.ResponseWriter, r *http.Request) {
		// Use the global TracerProvider
		tr := otel.Tracer("hello-handler")
		_, span := tr.Start(ctx, "hello")
		span.SetAttributes(attribute.Key("mykey").String("value"))
		defer span.End()

		podName := os.Getenv("MY_POD_NAME")
		fmt.Fprintf(w, "Hello %q!", podName)
	}

	otelHandler := otelhttp.NewHandler(http.HandlerFunc(helloHandler), "Hello")

	http.Handle("/", otelHandler)

	log.Println("Listening on localhost:8080")

	log.Fatal(http.ListenAndServe(":8080", nil))
}
Info

Le code source de l'application est disponible sur GitHub.

Nous avons déjà packagé une application Golang dans une image Docker et l'avons publiée dans notre dépôt Docker Hub ovhplatform afin que vous puissiez l'utiliser directement.

Pour déployer l'application sur votre OVHcloud Managed Kubernetes Service, créez un fichier deployment.yaml avec le contenu suivant :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: what-is-my-pod-with-tracing-deployment
  labels:
    app: what-is-my-pod-with-tracing
spec:
  replicas: 3
  selector:
    matchLabels:
      app: what-is-my-pod-with-tracing
  template:
    metadata:
      labels:
        app: what-is-my-pod-with-tracing
    spec:
      containers:
      - name: what-is-my-pod-with-tracing
        image: ovhplatform/what-is-my-pod-with-tracing:1.0.2
        ports:
        - containerPort: 8080
        env:
          - name: MY_POD_NAME
            valueFrom:
              fieldRef:
                fieldPath: metadata.name

Ce fichier manifeste de déploiement YAML définit que notre application, basée sur l'image ovhplatform/what-is-my-pod-with-tracing:1.0.2, sera déployée avec 3 réplicas (3 pods). Nous transmettons le nom du pod via une variable d'environnement afin de l'afficher dans notre application what-is-my-pod-with-tracing.

Ensuite, créez un fichier svc.yaml avec le contenu suivant pour définir notre service (un service expose un déploiement) :

apiVersion: v1
kind: Service
metadata:
  labels:
    app: what-is-my-pod-with-tracing
  name: what-is-my-pod-with-tracing
spec:
  ports:
  - port: 8080
  selector:
    app: what-is-my-pod-with-tracing
  type: LoadBalancer

Appliquez les fichiers manifestes de déploiement et de service à votre cluster avec les commandes suivantes :

kubectl apply -f deployment.yaml
kubectl apply -f svc.yaml

Le résultat devrait être le suivant :

$ kubectl apply -f deployment.yml
deployment.apps/what-is-my-pod-with-tracing-deployment created

$ kubectl apply -f svc.yml
service/what-is-my-pod-with-tracing created

Vous pouvez vérifier que votre application est bien en cours d'exécution et que le service est créé en exécutant les commandes suivantes :

kubectl get pod -l app=what-is-my-pod-with-tracing
kubectl get svc -l app=what-is-my-pod-with-tracing

Le résultat devrait être le suivant :

$ kubectl get pod -l app=what-is-my-pod-with-tracing
NAME                                                      READY   STATUS    RESTARTS   AGE
what-is-my-pod-with-tracing-deployment-84b56684d8-6kw6z   1/1     Running   0          3m
what-is-my-pod-with-tracing-deployment-84b56684d8-bcsxh   1/1     Running   0          3m
what-is-my-pod-with-tracing-deployment-84b56684d8-wbjmz   1/1     Running   0          3m

$ kubectl get svc -l app=what-is-my-pod-with-tracing
NAME                          TYPE           CLUSTER-IP    EXTERNAL-IP      PORT(S)          AGE
what-is-my-pod-with-tracing   LoadBalancer   10.3.118.87   135.125.84.198   8080:32365/TCP   3m

Pour générer du trafic, vous devez récupérer l'IP externe de votre service :

export APP_URL=$(kubectl get svc what-is-my-pod-with-tracing -o jsonpath='{.status.loadBalancer.ingress[].ip}')
echo Application URL: http://$APP_URL:8080/

Puis générez du trafic avec la commande curl :

curl http://$APP_URL:8080/

Vous devriez obtenir le résultat suivant :

$ export APP_URL=$(kubectl get svc what-is-my-pod-with-tracing -o jsonpath='{.status.loadBalancer.ingress[].ip}')

$ echo $APP_URL
135.125.84.198

$ curl http://$APP_URL:8080/
Hello "what-is-my-pod-with-tracing-deployment-84b56684d8-6kw6z"!%

$ curl http://$APP_URL:8080/
Hello "what-is-my-pod-with-tracing-deployment-84b56684d8-6kw6z"!%

$ curl http://$APP_URL:8080/
Hello "what-is-my-pod-with-tracing-deployment-84b56684d8-wbjmz"!%

Visualiser les traces

Ouvrez votre navigateur et retournez sur l'interface Jaeger (http://$JAEGER_URL:16686).

Jaeger query services

Vous devriez maintenant voir deux services disponibles :

  • go-what-is-my-pod-with-tracing
  • jaeger-query

Sélectionnez le service go-what-is-my-pod-with-tracing et cliquez sur le bouton Find Traces.

Jaeger query traces

Vous pouvez maintenant cliquer sur une trace pour visualiser des informations utiles.

Jaeger query trace details

Suppression (nettoyage)

Supprimez les composants Jaeger (créés par l'opérateur) :

kubectl delete -f jaeger.yaml

Attendez que les composants soient supprimés, puis vous pouvez désinstaller l'opérateur.

Pour désinstaller Jaeger Operator, puisque vous l'avez installé via Helm, vous pouvez utiliser la commande helm uninstall afin de supprimer le chart Helm de Jaeger installé :

helm uninstall jaeger-operator -n observability

Supprimez le namespace observability :

kubectl delete ns observability

Et supprimez l'application déployée :

kubectl delete -f deployment.yaml
kubectl delete -f svc.yaml

Aller plus loin

  • Si vous avez besoin d'une formation ou d'une assistance technique pour la mise en oeuvre de nos solutions, contactez votre commercial ou cliquez sur ce lien pour obtenir un devis et demander une analyse personnalisée de votre projet à nos experts de l’équipe Professional Services.

  • Échangez avec notre communauté d'utilisateurs.

Cette page vous a-t-elle aidé ?