Découvrir

SEALED SECRETS: Sécurisation des données sensibles dans kubernetes

Dans un monde où les architectures distribuées et les microservices sont devenus la norme, le besoin d’une observabilité efficace n’a jamais été aussi critique. Les systèmes modernes génèrent une quantité massive de logs, de métriques et de traces, rendant leur analyse de plus en plus complexe. C’est ici qu’OpenTelemetry intervient.

OpenTelemetry est une initiative open source soutenue par la Cloud Native Computing Foundation (CNCF). Son objectif est de fournir un standard unique pour la collecte de traces, de logs et de métriques, facilitant ainsi l’observabilité des applications cloud-native. Il est compatible avec de nombreux langages et environnements, ce qui en fait un choix privilégié pour les entreprises cherchant à unifier leur approche du monitoring.

OpenTelemetry : Un standard unifié pour les traces et métriques

Pourquoi adopter OpenTelemetry ?

  • Standardisation : OpenTelemetry unifie les traces, métriques et logs sous une même spécification.
  • Interopérabilité : Compatible avec Prometheus, Jaeger, Zipkin et bien d’autres outils.
  • Flexibilité : OpenTelemetry permet d’utiliser divers backends sans modifier le code source. L’implémentation repose sur une API abstraite qui découple la collecte des données de leur stockage. Ainsi, une organisation peut commencer avec Jaeger pour les traces et migrer ensuite vers Zipkin ou un service managé comme AWS X-Ray sans modifier l’instrumentation de l’application. Seule la configuration de l’exportateur change.

Adoption massive : Soutenu par Microsoft, Google, et d’autres acteurs majeurs de l’industrie.

Un œil sur les composants clés

    1. Traces : Permet d’analyser le parcours des requêtes à travers les services.
    2. Métriques : Collecte et analyse les performances de l’application.
    3. Logs (bientôt standardisés) : Complète les informations des traces et métriques.

Comprendre les exportateurs OpenTelemetry

Un exportateur est un composant qui permet d’envoyer les données collectées par OpenTelemetry vers un backend spécifique. Grâce à l’architecture modulaire d’OpenTelemetry, vous pouvez changer d’exportateur sans modifier votre code source, en ajustant simplement la configuration.

Exemples d'exportateurs disponibles :

  • Tracing : 
    • – Jaeger
    • – Zipkin
    • – AWS X-Ray
    • – Grafana Tempo
  • Métriques :
    • – Prometheus
    • – New Relic
    • – Datadog
  • Logs (en cours de standardisation) :
    • – OpenSearch
    • – Loki

L’intérêt principal de cette approche est que vous pouvez débuter avec un outil open source comme Jaeger et migrer plus tard vers une solution managée comme AWS X-Ray, sans avoir à réécrire votre instrumentation.

Exploitation des données OpenTelemetry avec Grafana

Grafana est une plateforme open source de visualisation et d’analyse des données qui peut être utilisée pour exploiter les métriques, traces et logs collectés par OpenTelemetry. Grâce à ses nombreux connecteurs, il permet d’afficher des tableaux de bord interactifs en temps réel.

Intégration d'OpenTelemetry avec Grafana

  1. Collecte des métriques avec Prometheus :
    • OpenTelemetry peut exporter les métriques vers Prometheus.
    • Grafana peut se connecter à Prometheus pour afficher ces métriques sous forme de graphiques et d’alertes.
  2. Visualisation des traces avec Grafana Tempo :
    • OpenTelemetry peut exporter des traces vers Tempo.
    • Grafana permet ensuite d’explorer les requêtes et leurs dépendances via un affichage détaillé des traces.
  3. Gestion des logs avec Loki :
    • OpenTelemetry peut envoyer des logs vers Loki.
    • Grafana permet de les visualiser et de corréler les logs avec les traces et métriques.

Grâce à cette intégration, Grafana devient un outil puissant pour centraliser l’observabilité de votre infrastructure en exploitant les données issues d’OpenTelemetry.

Tutoriel : Mise en place d'OpenTelemetry dans une API .NET

Nous allons intégrer OpenTelemetry dans une application ASP.NET Core minimaliste.

Prérequis

  • .NET 6 ou supérieur installé sur votre machine
  • Un outil de monitoring supporté (ici Loki)
  • Un éditeur de code (Visual Studio, VS Code, JetBrains Rider)

Installation et configuration

1. Création d’un projet ASP.NET Core et ajout des dépendances nécessaires

				
					mkdir OpenTelemetryDemo
cd OpenTelemetryDemo
dotnet new webapi
				
			

Les dépendances à installer:

				
					dotnet add package OpenTelemetry
dotnet add package OpenTelemetry.Extensions.Hosting
dotnet add package OpenTelemetry.Exporter.OpenTelemetryProtocol
dotnet add package OpenTelemetry.Logs
dotnet add package OpenTelemetry.Trace
dotnet add package OpenTelemetry.Instrumentation.AspNetCore
dotnet add package OpenTelemetry.Instrumentation.Http
dotnet add package Microsoft.Extensions.Logging

				
			

2. Ajout d’un fichier docker-compose.yaml au projet avec le contenu suivant:

				
					version: '3.8'

services:
  dotnet-app:
    build: .
    ports:
      - "5000:5000"
    depends_on:
      otel-collector:
        condition: service_healthy
    networks:
      - observability
    environment:
      - OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317

  otel-collector:
    image: otel/opentelemetry-collector-contrib:0.96.0
    volumes:
      - ./otel-collector-config.yaml:/etc/otel-config.yaml
    command: ["--config=/etc/otel-config.yaml"]
    ports:
      - "4317:4317"
      - "4318:4318"
    networks:
      - observability
    depends_on:
      loki:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:13133"]
      interval: 30s
      timeout: 10s
      retries: 3

  loki:
    image: grafana/loki:2.9.4
    volumes:
      - loki-storage:/data/loki
    ports:
      - "3100:3100"
    networks:
      - observability
    healthcheck:
      test: ["CMD-SHELL", "curl -f http://localhost:3100/ready || exit 1"]
      interval: 10s
      timeout: 10s
      retries: 10

  grafana:
    image: grafana/grafana:10.4.3
    ports:
      - "3000:3000"
    environment:
      GF_SECURITY_ADMIN_PASSWORD: admin
      GF_FEATURE_TOGGLES_ENABLE: "export"
      GF_LOG_LEVEL: "debug"
    volumes:
      - grafana-storage:/var/lib/grafana
      - ./grafana-dashboards:/etc/grafana/provisioning/dashboards
    networks:
      - observability
    depends_on:
      loki:
        condition: service_healthy

networks:
  observability:
    driver: bridge

volumes:
  grafana-storage:
    driver: local
  loki-storage:

				
			

3. Ajout d’un fichier loki-config.yaml au projet avec le contenu suivant:

				
					auth_enabled: false

server:
  http_listen_port: 3100

ingester:
  lifecycler:
    address: 127.0.0.1
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
  chunk_idle_period: 5m
  chunk_retain_period: 30s
  max_transfer_retries: 0

schema_config:
  configs:
    - from: 2022-01-01
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /data/loki/index
    cache_location: /data/loki/cache
    shared_store: filesystem

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h


				
			

4. Ajout d’un fichier otel-collector-config.yaml au projet avec le contenu suivant :

				
					receivers:
  otlp:
    protocols:
      grpc:
      http:

processors:
  batch:

exporters:
  loki:
    endpoint: "http://loki:3100/loki/api/v1/push"
    default_labels_enabled:
      exporter: true
      job: true
      instance: true

service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [batch]
      exporters: [loki]

				
			

5. Ajout du code suivant dans le Program.cs:

				
					using OpenTelemetry.Logs;
using OpenTelemetry.Resources;
using OpenTelemetry.Trace;

var builder = WebApplication.CreateBuilder(args);

builder.Logging.ClearProviders().AddConsole().AddOpenTelemetry(options =>
{
    options.IncludeFormattedMessage = true;
    options.IncludeScopes = true;

    options.SetResourceBuilder(ResourceBuilder.CreateDefault()
        .AddService("dotnet-console-app")
        .AddAttributes(new Dictionary<string, object>
        {
            ["environment"] = "development",
            ["host"] = Environment.MachineName
        }));

    options.AddOtlpExporter(opt =>
    {
        opt.Endpoint = new Uri("http://otel-collector:4317"); // Envoie à OpenTelemetry Collector
    });
});
var app = builder.Build();


// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.MapOpenApi();
}

app.UseHttpsRedirection();

var summaries = new[]
{
    "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};

var logger = app.Services.GetRequiredService<ILogger<Program>>();

logger.LogInformation("Application starting..."); 
app.MapGet("/weatherforecast", (ILogger<Program> logger) =>
{
    logger.LogInformation("Requête reçue pour /weatherforecast");
    var forecast =  Enumerable.Range(1, 5).Select(index =>
        new WeatherForecast
        (
            DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
            Random.Shared.Next(-20, 55),
            summaries[Random.Shared.Next(summaries.Length)]
        ))
        .ToArray();
    return forecast;
})
.WithName("GetWeatherForecast");

app.Run();

record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
{
    public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}


				
			

6. Ajout d’un Dockerfile:

				
					FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
USER $APP_UID
WORKDIR /app
ENV ASPNETCORE_URLS http://+:5000

FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["OpenTelemetryDemo.csproj", "."]
RUN dotnet restore "./OpenTelemetryDemo.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "./OpenTelemetryDemo.csproj" -c $BUILD_CONFIGURATION -o /app/build

FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./OpenTelemetryDemo.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "OpenTelemetryDemo.dll"]

				
			

7. Lancement des containers avec la commande :

				
					docker-compose up --build
				
			

8. Connexion à Grafana:

On se connecte à Grafana sur l’url “http://localhost:3000”.

Il faut dans un premier temps ajouter une source de données en cliquant sur “Add your first data source”.

Choisir “Loki” et renseigner sur la page suivante l’url de connection comme ceci:

Cliquer en bas de page sur Save and Test.
Un encadré apparaît, cliquer sur “building a Dashboard”:

Cliquer sur “Add Visualization” et sélectionner la source “Loki”.

En haut à droite de la page, à la place de “Time Series”, choisir “Logs”:

En bas de page, dans les label filters, sélectionnez un label, par exemple “job” et la valeur correspondante “dotnet-console-app” qui est le nom que nous avons donné au service dans le Program.cs:

Cliquer sur “Run Query”. Nous récupérons bien nos logs:

Ouvrir une fenêtre powershell et taper la commande “curl http://localhost:5000/weatherforecast “ afin d’appeler notre api. 

Comme nous avons placé un Log dans le Endpoint correspondant, un nouveau Log devrait apparaître dans Grafana.

Dans le Program.cs:

En cliquant de nouveau sur Run Query dans Grafana, mon log est bien présent 🙂

Categories