Deploying C# on Kubernetes: A Basic Guide
Kubernetes (K8s) has become the de facto standard for orchestrating containerized applications. If you develop in C# (.NET), sooner or later the question will arise: how to package your application and run it in the cloud or on your own cluster. In this guide, we will walk through the complete cycle — from creating a simple web API in ASP.NET Core to deploying it on Kubernetes.
This article is aimed at developers who are already familiar with the basics of C# and Docker, but are just starting to work with Kubernetes.
1. Preparing the .NET Application and Docker Image
Before deploying an application to Kubernetes, it needs to be packaged into a container. Let's create a minimal web API in C#.
- Create a new project:
dotnet new webapi -n MyK8sAppcd MyK8sApp - Ensure the application listens on port 80. In the
Program.csfile (orappsettings.json), specify:builder.WebHost.UseUrls("http://0.0.0.0:80"); - Create a
Dockerfilein the project root:FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS baseWORKDIR /appEXPOSE 80
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS buildWORKDIR /srcCOPY ["MyK8sApp.csproj", "."]RUN dotnet restore "./MyK8sApp.csproj"COPY . .RUN dotnet build "MyK8sApp.csproj" -c Release -o /app/build
FROM build AS publishRUN dotnet publish "MyK8sApp.csproj" -c Release -o /app/publish
FROM base AS finalWORKDIR /appCOPY --from=publish /app/publish .ENTRYPOINT ["dotnet", "MyK8sApp.dll"] - Build the image and push it to a registry (e.g., Docker Hub):
docker build -t yourdockerhub/my-k8s-app:v1 .docker push yourdockerhub/my-k8s-app:v1
Important: Replace yourdockerhub with your actual username. For local testing, you can use minikube and skip publishing the image — just build it locally.
2. Creating Kubernetes Manifests
Kubernetes uses declarative YAML files to describe the desired state of the cluster. We will need two main objects: Deployment (pod management) and Service (network access).
2.1. Deployment
Create a file deployment.yaml:
apiVersion: apps/v1kind: Deploymentmetadata: name: my-k8s-app-deployment labels: app: my-k8s-appspec: replicas: 2 selector: matchLabels: app: my-k8s-app template: metadata: labels: app: my-k8s-app spec: containers: - name: my-k8s-app image: yourdockerhub/my-k8s-app:v1 ports: - containerPort: 80 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" livenessProbe: httpGet: path: /health port: 80 initialDelaySeconds: 5 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 80 initialDelaySeconds: 3 periodSeconds: 5In this manifest, we specify:
- replicas: 2 — two instances of the application for fault tolerance.
- resources — CPU and memory limits (important for stable cluster operation).
- livenessProbe and readinessProbe — health checks. Add
/healthand/readyendpoints to your controller.
2.2. Service
Create a file service.yaml:
apiVersion: v1kind: Servicemetadata: name: my-k8s-app-servicespec: selecto