Containerize .NET Core App and Deploy to K8s with NGINX Ingress Controller as NLB

Kubernetes is one of the widely adopted platform today for orchestrating your container workloads. There are various approaches when it comes to deploy your containers to Kubernetes. In this blog post, we will cover step by step information of building and containerizing a simple ASP.NET Core application and deploy to Azure Kubernetes Services with Nginx Controller as a front end.

Following is the solution architecture that shows various components inside AKS. The consumer application communicates to the Nginx Ingress Controller which redirects the traffic to the K8s services resource and then to the container running inside a K8s pod.

image

Pre-requisites:

Following are the pre-requisites needed to be setup/installed before starting the implementation:

– VS Code

– Docker extension for VS Code

– Active Azure subscription

– AKS (Azure Kubernetes Services) provisioned

– ACR (Azure Container Registry) provisioned

– Helm charts

– kubectl

– Azure CLI

Once the pre-requisites are setup, lets proceed with the step-by-step tutorial to containerize and deploy the ASP.NET Core application in AKS.

Create a new ASP.NET MVC application

To create a new ASP.NET Core application, open the command prompt and use the dotnet CLI as shown below:

dotnet new mvc

Running the above command will create the ASP.NET MVC project and restore the NuGet packages.

clip_image004

Create a Dockerfile

Open this app in VS Code, and create a new Dockerfile by using the Docker extension. You can hit Ctrl+Shift+P and search for Docker: Add Docker Files to Workspace… option.

clip_image006

Select .NET: ASP.NET Core

clip_image008

Select Linux

clip_image010

Enter port 80

clip_image012

Finally, it creates a Dockerfile as shown below:

clip_image014

Build and Run the Docker image

To build a docker image, go to the folder where Dockerfile is resided, and execute the following command:

docker build -t nginxdemoapp:1.0 .

Once the image is built, run the application through docker run.

Docker run -d -p 6778:80 nginxdemoapp:1.0

This will spin up the container and you can access it from http://localhost:6778

Push to ACR

To push this image to ACR, we need to first tag it. Tag the image with the ACR repository, in my case it is mycontainerregistry.azurecr.io. Tag the image by running following command:

docker tag nginxdemoapp:1.0 mycontainerregistry.azurecr.io/nginxdemoapp:1.0

Once the image is tagged, Login to ACR using az CLI.

az acr login

Now push it by running the following command:

docker push mycontainerregistry.azurecr.io/nginxdemoapp:1.0

Once the image is pushed, you can also verify by going to Azure portal and seeing that image listed under Repositories.

Create a Deployment resource in AKS

We will first create a deployment resource object in K8s using the YAML file. Here is the k8sdeployment.yaml file that creates a deployment object inside K8s.

apiVersion: apps/v1

kind: Deployment

metadata:

name: nginxdemoapp

spec:

replicas: 2

selector:

matchLabels:

app: jos

component: nginxdemoapp

template:

metadata:

labels:

app: jos

component: nginxdemoapp

spec:

containers:

image: “mycontainerregistry.azurecr.io/nginxdemoapp:1.0”

name: nginxdemoapp

ports:

containerPort: 80

imagePullSecrets:

– name: mycontainerregistry

The mycontainerregistry is the secret that allows K8s to pull image from ACR. You can create the secret by running the following command:

kubectl create secret docker-registry mycontainerregistry –docker-server=mycontainerregistry.azurecr.io –docker-email=youremail –docker-username=mycontainerregistry –docker-password=yourpassword

To create the deployment, run the kubectl apply command as shown below:

kubectl apply -f k8sdeployment.yaml

Once the deployment is created, verify that 2 pods will be running by executing the kubectl get pods command

Deploy a K8s Ingress Controller

A Kubernetes ingress controller acts as a layer 7 load balancer. For Kubernetes services, these features include reverse proxy, configurable traffic routing, and TLS termination. The ingress controller is installed and configured to take the place of the load balancer.

To start with, lets first create a separate namespace as shown below:

kubectl create namespace ingress

Then, add the ingress-nginx repository in Helm

helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

Update the repository by executing helm update

Next, install the NGINX ingress controller. We set the replicaCount to 2 to install two ingress controllers for redundancy.

helm install nginx-ingress ingress-nginx/ingress-nginx –namespace ingress –set controller.replicaCount=2 –set controller.nodeSelector.”beta\.kubernetes\.io/os”=linux –set defaultBackend.nodeSelector.”beta\.kubernetes\.io/os”=linux

After running the above command, ensure the ingress controller service is running

Kubectl get services –namespace ingress

Create a Service resource in AKS

We will create a service file named K8sservice.yaml to create a K8s service object for our .NET Core app and set its type as ClusterIP so it can be accessible only within the K8s cluster itself.

apiVersion: v1

kind: Service

metadata:

labels:

app: jos

name: nginxdemoapp

spec:

ports:

– port: 80

targetPort: 80

protocol: TCP

type: ClusterIP

selector:

app: jos

component: nginxdemoapp

Create the service by running the command below:

kubectl apply -f K8sservice.yaml

Verify the service is created by executing the following:

kubectl get services

Create an Ingress resource in AKS

We create a ingress resource which allows to access the service using Ingress controller. Create a new K8sIngress.yaml file and add following code.

apiVersion: networking.k8s.io/v1beta1

kind: Ingress

metadata:

name: nginxdemoapp-web-ingress

annotations:

kubernetes.io/ingress.class: nginx

spec:

rules:

– host: frontend.{IngressControllerIP}.nip.io

http:

paths:

– backend:

serviceName: nginxdemoapp

servicePort: 80

path: /

Change the IP {IngressControllerIP} with your nginx-ingress-ingress-nginx-controller external IP address and run the kubectl apply command to create this resource.

kubectl apply -f K8sIngress.yaml

Verify the resource is created by running

kubectl get ingress

Finally test the application by going to the http://frontend… URL.

clip_image016

Hope this helps!