-->

22/05/2021

Containerize ASP.Net Core app on Azure Kubernetes Cluster

In my earlier post, we have deployed ASP.Net Core application to a Container hosted by a Linux Server.

There are some problems with this approach.

  1. What if the Host VM is stopped?
  2. What if Container Instance is stopped?
  3. How do we manage the deployment of any app changes?
  4. Even when we stop Host VM, you still be paying for the Disk allocated. How we can avoid that?

This is where Azure Kubernetes comes into the picture. 

Azure Kubernetes provide serverless CI/CD experience which also manages Health, Security, Auto-Scaling, Deployment and Governance aspects. More details can be found here

In this article we will be:

  • Deploy a ASP.Net Core App to a Container
  • Create a Container Image from .Net Core Container
  • Push the Image to Azure Container Registry
  • Use Kubernetes to Pull that image and create mutliple instances of the container in Kubernete Pods.
  • Expose the .Net Core App via Azure Load-Balancer.

Step 1: Create a ASP.Net Core Web App. 
I named it "DemoContainerApp". 
Since we need to containerize and generate an image of that container with out provisioning a Host, you need to select Docker support while selecting additional properties.

This may ask you to download "Docker Desktop" and "WSL 2.0 for Linux". Do it.
Now you have your ASP.Net Core App created and try running on IIS Express.


Step 2: Creating Container Registry

Go to Azure Portal, start by creating a Resource group for Container Registry. I named it "ContainerRegistryRG".  Now search for "Container Registry" and create new one.
I have created a Container Registry named "MyAppRegistry247".

Step 3: Deploy Container Image to Azure Container Registry

We will use the capabilities of Visual studio combined with Docker Desktop to create a Container hosting our App then extract an image of of that container and push it to ACR.

Now right click on the solution and select Publish, and select the Azure Container Registry you created in Step 2.
Now publish the Application. This will do the following:

  • Deploy the current .Net Core Web App, to a Docker Container Using Docker Desktop.
  • Extract the Image of that said container and push it to Azure Container Registry

To verify this, open the Docker Desktop and click on Images and you will see bot of the images.


Now open Azure portal and search for Container Registry and open "MyAppRegistry247". Go to "Respositories", you should see the container image for democontainerapp.


Step 4: Create Azure Kubernetes Service Cluster
Lets start by creating Resource Group for AKS. I named it "aksRG".
Before you create Kubernetes cluster , you need to understand about Service Principal.

To simply put, Service Principal is the AAD credentials used by Kubernetes to interact with Container Registry to pull the container image to create instances of it in kubernete pods.

If you havent dealth with next step properly, you may end up with some errors like below.

"Cannot find user or service principal in graph database for 'msi'. If the assignee is an appId, make sure the corresponding service principal is created with 'az ad sp create --id msi'"  

Execute below code to create a new Service Principal that can be used for Kubernetes interaction with ACR.
az ad sp create-for-rbac --skip-assignment --name demoAKSClusterServicePrincipal
This will generate Service principal with all the details displayed like below. 
Copy appId and password (client secret) for creating Kubernetes Cluster.  


Execute below commands
#Creating Kubernetes Cluster with Service principal association
az aks create --resource-group aksRG --name demo-aks-cluster --node-count 1 --enable-addons monitoring --service-principal  --client-secret 
#Install Kubernetes command tools
az aks install-cli --install-location=./kubectl
#Update the Kubernetes config with the service principal details
az aks get-credentials --resource-group aksRG --name demo-aks-cluster 
With above commands AKS Cluster is ready, but nothing has been deployed yet.

Step 5: Run Kubectl commands to create Container intances load balanced.
There are two parts to hosting containers on Kubernetes pods. App & Service
If you open AKS Cluster we created in step 4, you will see options "WorkLoad" and "Services" in left pane.


Workloads is defined by app.yml file which will have details of container image details and number of Pods you want to host the containers.

Services and Ingresses is defined by service.yml file have details of which workload should be hosted on what port.



Create 2 files app.yml and service.yml with below content.

app.yml Content
apiVersion: apps/v1
kind: Deployment
metadata:
  name: democontainerapp-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: democontainerapp
  template:
    metadata:
      labels:
        app: democontainerapp
    spec:
      containers:
      - name: democontainerapp
        image: myappregistry247.azurecr.io/democontainerapp
        ports:
        - containerPort: 5000
service.yml Content
apiVersion: v1
kind: Service
metadata:
  name: democontainerapp-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: democontainerapp
Open Azure Portal, open Azure Cloud Shell.
Upload both the app.yml and service.yml files.
Run below command to get the ClientID from the service principal associated to Kubernetes Cluster and create a Role based access to Container Registry so that container images can be accessed by AKS.
$AKS_RESOURCE_GROUP="aksRG"
$AKS_CLUSTER_NAME="demo-aks-cluster"
$ACR_RESOURCE_GROUP="ContainerRegistryRG"
$ACR_NAME="myappregistry247"


$CLIENT_ID=$(az aks show --resource-group $AKS_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query "servicePrincipalProfile.clientId" --output tsv)
$ACR_ID=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query "id" --output tsv)
az role assignment create --assignee $CLIENT_ID --role acrpull --scope $ACR_ID
Now run below kubectl commands to create both workloads and services using app.yml and service.yml file we uploaded earlier.
#Create workloads
kubectl apply -f app.yml
#Create service and ingress rules with ports and loadbalancers
kubectl apply -f service.yml
#Bring the External IP address of load balancers for the pods hosting containers
kubectl get service democontainerapp-service --watch

Now go to said workloads and Services and Ingresses in Kubernetes Cluster and see them for yourself.
Workloads


Services and Ingresses

Copy the External IP with port in a browser and now you can access ASP.Net core hosted in a container on Kubernetes Cluster.


In next article, we will automate the code deployment and Rolling deployments in Kubernetes using Azure DevOps Pipeline.

Hope i am helpful to fellow developers.

No comments:

Post a Comment