Microservices Architecture with .NET Core and Kubernetes

paulotorrestech

Paulo Torres

Posted on July 22, 2024

Microservices Architecture with .NET Core and Kubernetes

Microservices architecture has become a cornerstone of modern software development, enabling organizations to build scalable, resilient, and maintainable applications. Combining .NET Core with Kubernetes provides a powerful platform for developing, deploying, and managing microservices. This article delves into the advanced aspects of implementing microservices architecture using .NET Core and Kubernetes, illustrated with real-world examples.

Understanding Microservices

Principle Overview

Microservices architecture decomposes a large application into smaller, independent services that communicate over well-defined APIs. Each microservice focuses on a specific business capability, facilitating better scalability and development agility.

Setting Up the Environment

Step 1: Create a New .NET Core Microservice

First, create a new .NET Core Web API project for your microservice:

dotnet new webapi -n ProductService
cd ProductService
Enter fullscreen mode Exit fullscreen mode

Step 2: Define the Microservice

In this example, we will create a simple Product Service that handles product data.

Models/Product.cs

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Controllers/ProductController.cs

[ApiController]
[Route("api/[controller]")]
public class ProductController : ControllerBase
{
    private static readonly List<Product> Products = new List<Product>
    {
        new Product { Id = 1, Name = "Laptop", Price = 1200.00M },
        new Product { Id = 2, Name = "Smartphone", Price = 800.00M }
    };

    [HttpGet]
    public ActionResult<IEnumerable<Product>> Get() => Products;

    [HttpGet("{id}")]
    public ActionResult<Product> Get(int id)
    {
        var product = Products.FirstOrDefault(p => p.Id == id);
        if (product == null) return NotFound();
        return product;
    }

    [HttpPost]
    public ActionResult Post(Product product)
    {
        Products.Add(product);
        return CreatedAtAction(nameof(Get), new { id = product.Id }, product);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Dockerize the Microservice

Create a Dockerfile to containerize the Product Service.

Dockerfile

FROM mcr.microsoft.com/dotnet/aspnet:5.0 AS base
WORKDIR /app
EXPOSE 80

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS build
WORKDIR /src
COPY ["ProductService/ProductService.csproj", "ProductService/"]
RUN dotnet restore "ProductService/ProductService.csproj"
COPY . .
WORKDIR "/src/ProductService"
RUN dotnet build "ProductService.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "ProductService.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "ProductService.dll"]
Enter fullscreen mode Exit fullscreen mode

Build and run the Docker image:

docker build -t productservice .
docker run -d -p 8080:80 --name productservice productservice
Enter fullscreen mode Exit fullscreen mode

Deploying to Kubernetes

Step 4: Create Kubernetes Deployment and Service

Create Kubernetes manifests for deploying the Product Service.

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: productservice
spec:
  replicas: 3
  selector:
    matchLabels:
      app: productservice
  template:
    metadata:
      labels:
        app: productservice
    spec:
      containers:
      - name: productservice
        image: productservice:latest
        ports:
        - containerPort: 80
Enter fullscreen mode Exit fullscreen mode

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: productservice
spec:
  selector:
    app: productservice
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer
Enter fullscreen mode Exit fullscreen mode

Deploy the service to Kubernetes:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
Enter fullscreen mode Exit fullscreen mode

Step 5: Set Up Ingress Controller

Set up an Ingress Controller to manage external access to the microservices.

ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: productservice-ingress
spec:
  rules:
  - host: productservice.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: productservice
            port:
              number: 80
Enter fullscreen mode Exit fullscreen mode

Apply the ingress configuration:

kubectl apply -f ingress.yaml
Enter fullscreen mode Exit fullscreen mode

Step 6: Configuring CI/CD Pipeline

Automate the build, test, and deployment process using CI/CD pipelines. Example with GitHub Actions:

.github/workflows/ci-cd-pipeline.yaml

name: CI/CD Pipeline

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout code
      uses: actions/checkout@v2

    - name: Set up .NET
      uses: actions/setup-dotnet@v1
      with:
        dotnet-version: '5.0.x'

    - name: Build
      run: dotnet build --configuration Release

    - name: Test
      run: dotnet test --no-build --verbosity normal

    - name: Docker Build and Push
      run: |
        docker build -t productservice .
        docker tag productservice:latest yourdockerhub/productservice:latest
        echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_HUB_USERNAME }}" --password-stdin
        docker push yourdockerhub/productservice:latest

    - name: Deploy to Kubernetes
      uses: Azure/k8s-deploy@v1
      with:
        manifests: |
          ./deployment.yaml
          ./service.yaml
          ./ingress.yaml
        images: |
          yourdockerhub/productservice:latest
Enter fullscreen mode Exit fullscreen mode

Monitoring and Scaling

Step 7: Set Up Monitoring with Prometheus and Grafana

Deploy Prometheus and Grafana to monitor the health and performance of your microservices.

kubectl create namespace monitoring
kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/bundle.yaml
Enter fullscreen mode Exit fullscreen mode

Set up Grafana for visualizing metrics:

kubectl apply -f https://raw.githubusercontent.com/grafana-operator/grafana-operator/main/deploy/grafana.yaml
Enter fullscreen mode Exit fullscreen mode

Step 8: Auto-Scaling with Horizontal Pod Autoscaler

Enable auto-scaling for the Product Service:

kubectl autoscale deployment productservice --cpu-percent=50 --min=3 --max=10
Enter fullscreen mode Exit fullscreen mode

Conclusion

Implementing microservices architecture with .NET Core and Kubernetes provides a robust framework for building scalable, resilient, and maintainable applications. By leveraging Docker for containerization, Kubernetes for orchestration, and CI/CD pipelines for automation, you can streamline the development and deployment processes. Monitoring tools like Prometheus and Grafana, along with auto-scaling capabilities, ensure that your microservices are always performing optimally. Dive into these advanced techniques to enhance your .NET Core applications and embrace the future of software development.

💖 💪 🙅 🚩
paulotorrestech
Paulo Torres

Posted on July 22, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related