Deploying .NET Core Apps in Azure Kubernetes (AKS)

Kumar Allamraju
5 min readDec 30, 2020

I came from Java/J2EE background and I haven’t had a chance to use .NET Core until I started working in Microsoft. Here’s my attempt to deploy .NET Core Containerized Apps to AKS in few steps. We are going to start with a plain vanilla .NET Core Web API

Prerequisites

Let’s get started

  1. Create a new .NET Web API project in your local machine
dotnet new webapi -lang c# -n dotnetAKS

2. Create a Docker Image

In order to create a Docker image we have to create 2 new files in your main project folder: Dockerfile and .dockerignore

Let’s add some typical patterns for .NET applications to .dockerignore file to prevent them from being transferred to the Docker daemon when building the Docker image.

Creating Docker Images for .NET Core Applications is pretty straight forward. Microsoft provides all the required Base-Images to make your application run in a Linux-based container. We are going to create a so-called multi-stage Docker Image.

That means we are starting from a Base-Image that contains .NET Core SDK to compile and publish the application inside the image. Once that’s done, we’ll leverage another Base-Image that just holds all the required stuff to run .NET Core Applications and copy our previously published application into the new Base-Image. From here, we expose the desired port and start the application.

Here’s my Dockerfile

#Dockerfile
FROM mcr.microsoft.com/dotnet/core/sdk:3.1-buster AS builder
WORKDIR /src
COPY ./dotnetAKS.csproj .
RUN dotnet restore dotnetAKS.csproj
COPY . .
RUN dotnet build dotnetAKS.csproj -c Debug -o /src/out
FROM mcr.microsoft.com/dotnet/core/aspnet:3.1-buster-slim
WORKDIR /app
COPY --from=builder /src/out .
EXPOSE 80
ENTRYPOINT ["dotnet", "dotnetAKS.dll"]

Build the Docker image

#build the Docker image
docker build -t . dotnetaks:0.0.1

3. Create a Resource Group, Azure Container Registry

#create a resource group
az group create -n acrRG -l westus2
# check if your desired name is available
az acr check-name -n mediumacr
# create ACR
az acr create -g acrRG -n mediumacr \
--sku Basic \
--admin-enabled false
#store the ACR id in a variable. We'll need this in the later steps.
ACR_ID=$(az acr show -n mediumacr -g acrRG --query id -o tsv)

4. Push the local Docker image(s) to ACR

#re-tag the existing docker image
docker tag dotnetaks:0.0.1 mediumacr.azurecr.io/dotnetaks:0.0.1
#login to your azure subscription
az login
#authenticate against ACR
az acr login -n mediumacr
#push the docker image to ACR
docker push mediumacr.azurecr.io/dotnetaks:0.0.1
#Run the below command to verify your image has been successfully pushed to ACR
az acr repository list -n mediumacr

5. Create a Kubernetes Cluster

In order to keep the costs low, I’m going to create an AKS Cluster with a single node.

#Create an AKS cluster and also attach the ACR
az aks create -n dotnetAKSCluster -g acrRG \
--enable-managed-identity \
--attach-acr $ACR_ID \
--node-count 1
#Install kubectl
az aks install-cli
#download cluster configuration for kubectl
az aks get-credentials -g acrRG -n dotnetAKSCluster

6. Create Kubernetes Deployment Manifests

In Kubernetes, we don’t deploy Docker images directly. The smallest unit of work in Kubernetes is a so-called Pod. A pod offers a bunch of configuration opportunities to control the entire lifecycle of a containerized application.

If you install the latest Kubernetes extension in your VS Code, just create a yaml file and type “Pod” or “Deployment” or “Service”, VS Code automatically writes the entire code for you.

Replace the sample code with the correct values.

# pod.yml
apiVersion: v1
kind: Pod
metadata:
name: first-netcore-app
labels:
app: dotnet-aks
component: netcore-app
spec:
containers:
- image: mediumacr.azurecr.io/dotnetaks:0.0.1
name: webapi
ports:
- containerPort: 80

Besides the Pod, we need to expose our API to the public. To make Pods accessible (either cluster-wide or externally), we have to create a Service in Kubernetes.

# service.yml
apiVersion: v1
kind: Service
metadata:
labels:
app: dotnet-aks
name: dotnet-aks
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 80
selector:
app: dotnet-aks
component: netcore-app
type: LoadBalancer

This code will instruct Azure to create a public load balancer and route the internet traffic into our Kubernetes Cluster.

Kubernetes supports different types of services. In production applications, you typically don’t use LoadBalancer; instead, you use an Ingress controller (like, for example, NGINX Ingress or Azure Application Gateway Ingress Controller) that controls inbound traffic. Cluster internal services would be of type NodePort or ClusterIP.

7. Deploy your Application

Deploying yamls (artifacts) to Kubernetes is very simple; we use kubectl apply

kubectl apply -f pod.yaml
kubectl appply -f service.yaml
PS: You can combine Pod and Service in one yaml file separated by 3 hyphens (---)

Kubernetes will now pull our Docker image from ACR to instantiate the Pod and will also create a Service. Especially creating the service can take some time because the public IP has to be allocated and the Load Balancer has to be provisioned. You can use kubectl to watch for all services and wait until the external IP is associated.

bash-3.2$ kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
dotnet-aks LoadBalancer 10.0.186.199 13.91.201.83 8080:31197/TCP 51s app=dotnet-aks,component=netcore-app
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 12m <none>

Access the service.

#get the weather data from ASP.NET Core API in AKS
curl http://13.91.201.83:8080/weatherforeccast | jq
[
{
"date": "2020-12-31T19:20:10.4677142+00:00",
"temperatureC": 54,
"temperatureF": 129,
"summary": "Warm"
},
{
"date": "2021-01-01T19:20:10.4677389+00:00",
"temperatureC": 44,
"temperatureF": 111,
"summary": "Sweltering"
},
{
"date": "2021-01-02T19:20:10.4677393+00:00",
"temperatureC": -1,
"temperatureF": 31,
"summary": "Scorching"
},
{
"date": "2021-01-03T19:20:10.4677396+00:00",
"temperatureC": -19,
"temperatureF": -2,
"summary": "Mild"
},
{
"date": "2021-01-04T19:20:10.4677398+00:00",
"temperatureC": 3,
"temperatureF": 37,
"summary": "Scorching"
}
]

You can also check your Pod(s) and Services to get the IP addresses.

#get pods and endpoints
kubectl get pods -o wide
kubectl get endpoints

Summary

Voila!!. In few simple steps, we were able to deploy .NET Core App to an AKS Cluster. The same process can be applied to any other containerized Apps (Python, Java, Node.js, Go). We have only scratched the surface. You can dive deeper from here and adopt features like Deployments, ConfigMaps, and Secrets in Kubernetes.

References

--

--