Dans le monde du déploiement continu moderne, la capacité à déployer des applications sans interruption de service est devenue cruciale. Les stratégies de déploiement Blue-Green et Canary représentent deux approches majeures pour atteindre cet objectif. Ces techniques permettent de minimiser les risques tout en garantissant une expérience utilisateur optimale lors des mises à jour.
Comprendre les concepts fondamentaux
Le déploiement Blue-Green
Le déploiement Blue-Green consiste à maintenir deux environnements de production identiques : l'environnement "Blue" qui héberge la version actuelle, et l'environnement "Green" qui recevra la nouvelle version. Une fois la nouvelle version validée, le trafic est basculé de Blue vers Green via un simple changement de routage.
Le déploiement Canary
La stratégie Canary expose progressivement les utilisateurs à la nouvelle version. On commence par rediriger un faible pourcentage du trafic (par exemple 5%) vers la nouvelle version, puis on augmente graduellement ce pourcentage en surveillant les métriques de performance et d'erreurs.
Implémentation en .NET
Configuration du déploiement Blue-Green
// Program.cs
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Configuration du routage pour Blue-Green
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
var app = builder.Build();
// Middleware de routage Blue-Green
app.MapReverseProxy(proxyPipeline =>
{
proxyPipeline.Use(async (context, next) =>
{
var deploymentType = context.Request.Headers["X-Deployment-Type"];
context.Request.Headers["X-Version"] =
deploymentType == "blue" ? "v1" : "v2";
await next();
});
});
}
}
Implémentation Canary avec ASP.NET Core
public class CanaryRoutingMiddleware
{
private readonly RequestDelegate _next;
private readonly Random _random;
private const double CANARY_PERCENTAGE = 0.05; // 5% du trafic
public CanaryRoutingMiddleware(RequestDelegate next)
{
_next = next;
_random = new Random();
}
public async Task InvokeAsync(HttpContext context)
{
var shouldRouteToCanary = _random.NextDouble() < CANARY_PERCENTAGE;
if (shouldRouteToCanary)
{
context.Request.Headers["X-Version"] = "canary";
}
await _next(context);
}
}
Bonnes pratiques et recommandations
- Monitoring approfondi : Implémentez des métriques détaillées pour suivre la santé des déploiements
- Automatisation : Utilisez des pipelines CI/CD pour automatiser les déploiements
- Tests de smoke : Validez rapidement les fonctionnalités critiques après chaque déploiement
- Rollback automatisé : Préparez des procédures de rollback en cas de problème
Monitoring et observabilité
public class DeploymentMetricsMiddleware
{
private readonly RequestDelegate _next;
private readonly IMetricsCollector _metrics;
public DeploymentMetricsMiddleware(RequestDelegate next,
IMetricsCollector metrics)
{
_next = next;
_metrics = metrics;
}
public async Task InvokeAsync(HttpContext context)
{
var version = context.Request.Headers["X-Version"].ToString();
var stopwatch = Stopwatch.StartNew();
try
{
await _next(context);
_metrics.RecordSuccess(version, stopwatch.ElapsedMilliseconds);
}
catch (Exception ex)
{
_metrics.RecordError(version, ex);
throw;
}
}
}
Tests et validation
[Fact]
public async Task CanaryRouting_ShouldRespectPercentage()
{
// Arrange
var middleware = new CanaryRoutingMiddleware(next: (context) =>
Task.CompletedTask);
var context = new DefaultHttpContext();
var iterations = 10000;
var canaryCount = 0;
// Act
for (int i = 0; i < iterations; i++)
{
await middleware.InvokeAsync(context);
if (context.Request.Headers["X-Version"] == "canary")
canaryCount++;
}
// Assert
var percentage = (double)canaryCount / iterations;
Assert.InRange(percentage, 0.04, 0.06); // ±1% de marge
}
Intégration avec Azure
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "contoso.onmicrosoft.com",
"TenantId": "your-tenant-id",
"ClientId": "your-client-id"
},
"Deployment": {
"BlueSlot": {
"Url": "https://blue-slot.azurewebsites.net",
"ApiKey": "blue-key"
},
"GreenSlot": {
"Url": "https://green-slot.azurewebsites.net",
"ApiKey": "green-key"
}
}
}
Gestion des erreurs et résilience
public class DeploymentHealthCheck : IHealthCheck
{
private readonly IHttpClientFactory _clientFactory;
public async Task CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
var client = _clientFactory.CreateClient("deployment");
try
{
var response = await client.GetAsync("/health");
return response.IsSuccessStatusCode
? HealthCheckResult.Healthy()
: HealthCheckResult.Unhealthy();
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy(ex.Message);
}
}
}
Conclusion
Les stratégies de déploiement Blue-Green et Canary sont essentielles pour les équipes DevOps modernes. Elles permettent de réduire les risques liés aux déploiements tout en maintenant une haute disponibilité. L'écosystème .NET offre tous les outils nécessaires pour implémenter ces stratégies de manière robuste et évolutive.
Pour réussir leur mise en œuvre, il est crucial de :
- Automatiser les processus de déploiement
- Mettre en place un monitoring approfondi
- Préparer des procédures de rollback
- Tester rigoureusement chaque déploiement