.NET Core Microservices and Azure Kubernetes Service

2 min read

 

.NET Core Microservices Architecture on Azure Kubernetes Service

A Comprehensive Technical Guide for Enterprise Architects


Executive Summary

Deploying .NET Core microservices on Azure Kubernetes Service (AKS) is now the enterprise standard for building scalable, resilient, cloud-native applications in the Microsoft ecosystem.

For senior .NET developers and architects, mastering this architecture opens doors to high-impact cloud engineering roles, where organizations expect deep expertise in containerization, orchestration, distributed systems, and infrastructure-as-code.

AKS combines:


  • ASP.NET Coreโ€™s high performance



  • Kubernetesโ€™ orchestration and self-healing



  • Azureโ€™s managed services ecosystem


Together, they enable automatic scaling, rolling deployments, service discovery, distributed tracing, and workload isolationโ€”all critical for modern enterprise systems.


Core Architecture: Internal Mechanics & Patterns

The Microservices Foundation on AKS

AKS provides a managed Kubernetes control plane, eliminating the operational burden of maintaining Kubernetes masters while preserving full node-level control.

A typical AKS microservices architecture includes:


  • Containerized services
    Each microservice runs as a Docker container inside Kubernetes Pods.



  • Azure CNI networking (Cilium)
    Pods receive IPs from the VNet, enabling native network policies and deep traffic visibility.



  • Ingress & API Gateway pattern
    An NGINX ingress controller exposes a single entry point for HTTP/HTTPS traffic.



  • Externalized state
    Stateless services persist data to Azure Cosmos DB, Azure SQL, Redis, or Service Bus.



API Gateway & Request Routing

The ingress controller acts as the edge gateway, responsible for:


  • Request routing to backend services



  • SSL termination



  • Authentication and authorization



  • Rate limiting and IP filtering



  • Request aggregation


Advanced setups may use multiple ingress controllers per cluster for tenant isolation or environment separation.


Namespace Strategy & Service Organization

Namespaces map naturally to bounded contexts (DDD):


  • order-fulfillment



  • payments



  • inventory



  • platform-observability


This improves:


  • RBAC boundaries



  • Resource quotas



  • Operational clarity



Communication Patterns

A hybrid communication model is recommended:


  • Synchronous REST
    For queries and immediate responses



  • Asynchronous messaging
    For state changes and workflows using RabbitMQ + MassTransit


This balances consistency, decoupling, and resilience.


Service Discovery & Health Management

Kubernetes Services provide stable DNS endpoints.

Health management includes:


  • Liveness probes โ€“ restart crashed services



  • Readiness probes โ€“ control traffic flow



  • ASP.NET Core Health Checks โ€“ native integration



Technical Implementation: Modern .NET Practices

Health Checks (ASP.NET Core 8+)

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHealthChecks()
    .AddCheck<DatabaseHealthCheck>("database")
    .AddCheck<RedisHealthCheck>("redis");

var app = builder.Build();

app.MapHealthChecks("/health/live");
app.MapHealthChecks("/health/ready");

app.Run();
public sealed class DatabaseHealthCheck : IHealthCheck
{
    private readonly IDbConnection _connection;

    public DatabaseHealthCheck(IDbConnection connection)
        => _connection = connection;

    public async Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        try
        {
            await _connection.OpenAsync(cancellationToken);
            return HealthCheckResult.Healthy("Database reachable");
        }
        catch (Exception ex)
        {
            return HealthCheckResult.Unhealthy("Database failure", ex);
        }
    }
}

Kubernetes Deployment (Production-Ready)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  namespace: order-fulfillment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
        - name: order-service
          image: myregistry.azurecr.io/order-service:1.0.0
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "250m"
              memory: "256Mi"
            limits:
              cpu: "500m"
              memory: "512Mi"
          readinessProbe:
            httpGet:
              path: /health/ready
              port: 8080
          livenessProbe:
            httpGet:
              path: /health/live
              port: 8080

Distributed Tracing (Application Insights + OpenTelemetry)

builder.Services.AddApplicationInsightsTelemetry();

builder.Services.AddOpenTelemetry()
    .WithTracing(tracing =>
    {
        tracing
            .AddAspNetCoreInstrumentation()
            .AddHttpClientInstrumentation()
            .AddAzureMonitorTraceExporter();
    });

Resilient Service-to-Service Calls (Polly)

builder.Services.AddHttpClient<IOrderClient, OrderClient>()
    .AddTransientHttpErrorPolicy(p =>
        p.WaitAndRetryAsync(3, retry => TimeSpan.FromSeconds(Math.Pow(2, retry))))
    .AddTransientHttpErrorPolicy(p =>
        p.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));

Event-Driven Architecture (MassTransit + RabbitMQ)

builder.Services.AddMassTransit(x =>
{
    x.AddConsumer<OrderCreatedConsumer>();

    x.UsingRabbitMq((context, cfg) =>
    {
        cfg.Host("rabbitmq://rabbitmq");
        cfg.ConfigureEndpoints(context);
    });
});
public class OrderCreatedConsumer : IConsumer<OrderCreatedEvent>
{
    public async Task Consume(ConsumeContext<OrderCreatedEvent> context)
    {
        // Persist order, emit downstream events
    }
}

Distributed Caching (Redis โ€“ Cache-Aside Pattern)

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration.GetConnectionString("Redis");
});

Scaling & Performance

Horizontal Pod Autoscaler (HPA)

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
  minReplicas: 3
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

Common Pitfalls (Real-World)


  1. Shared databases between services



  2. Excessive synchronous REST chains



  3. No observability or tracing



  4. Poor resource requests/limits



  5. Ignoring network policies



Optimization Tricks


  • Spot node pools for non-critical workloads (70% cost savings)



  • Pod Disruption Budgets



  • Vertical Pod Autoscaler



  • Docker layer caching



  • Readiness vs liveness probe tuning



  • GitOps with Terraform + ArgoCD



When AKS Microservices Make Sense

ScenarioRecommendation
10+ servicesโœ… AKS
High trafficโœ… AKS
Small team / MVPโŒ Monolith
Strong ACIDโŒ Microservices

Final Takeaway

AKS + .NET Core is a power tool, not a starter kit.

When used correctly, it delivers scalability, resilience, and velocity unmatched by traditional architectures. When misused, it introduces unnecessary complexity.

For enterprise systems with multiple teams, frequent deployments, and global scaleโ€”this architecture is worth the investment.


 

Leave a Reply

Your email address will not be published. Required fields are marked *