Saturday, January 25, 2020

Deploying an ASP.NET Core Application On Azure Kubernetes Service

So in the first post, I have created a docker image with a simple ASP.NET Core Web API application and showed how we can deploy it into a local K8s cluster. In the second post, I wrote about how we can deploy a docker image to an Azure Container Registry (ACR).

So in this post, let's see how we can deploy a docker image with an ASP.NET Core Application on Azure Kubernetes Service (AKS). Here I will be using the docker image (kube-weather:dev) which we have published to our ACR in this post. And in this post, let's see how we can do below.
  1. Setup an AKS
  2. Grant the AKS Service Principle access to our ACR
  3. Deploy the service
1. Setup an AKS

For this, let's create a Kubernetes Service in Azure.
Kubernetes Service
I am clicking on Create.

Basics
Here I have entered some basic information. And you can select a node pool with basic Node size. And here I have Node count set to 3, even 1 should be enough and I am clicking on Next: Scale.

Scale
Here default settings should be enough and going to Next: Authentication.

Authentication
This step is important. Here we need to create a new Service Principal for our cluster. But unfortunately for some reason, we weren't provided an option to give a principal name, and we are planning on using the name in a later step. Because of that, I am creating a Service Principal using Azure CLI as below. 
PS C:\Users\Jaliya> az ad sp create-for-rbac --skip-assignment --name SP-PlayGround01-Cluster
Changing "SP-PlayGround01-Cluster" to a valid URI of "http://SP-PlayGround01-Cluster", which is the required format used for service principal names
{
  "appId": "4b7ff1c6-a2ce-4b49-a197-dedabe04717b",
  "displayName": "SP-PlayGround01-Cluster",
  "name": "http://SP-PlayGround01-Cluster",
  "password": "e22efd43-60dc-4dca-8f2d-e2fced07780a",
  "tenant": "1f4a5f26-b0bc-402c-9347-e0f7d16c098f"
}
And I am using the appId and password information which were outputted and selecting Use existing in above to configure the service principal and I am going to Next: Networking.

Networking
For networking, defaults are fine and going to Next: Monitoring.

Monitoring
And for Monitoring, I have created a Log Analytics workspace with a proper name and going to Next: Tags.

Tags
I don't have any tags, I am leaving it empty and going to Review + create. In the review step, it will do some validations and once passed, I have clicked on Create. And it will take a couple of minutes to set up the AKS.

And it's created.
playground01-kubernetes-cluster
2. Grant the service principle we created above access to our ACR

For this, let's navigate to our ACR playground01 which we have created in my previous blog post: Pushing Local Docker Image to an Azure Container Registry
ACR
From there, click on Access control (IAM) and then Add a role assignment. And from the next pane, select Role AcrPull. And from Assign access to, keep the default which is Azure AD user, group and service principal. And from the Select, search for SP-PlayGround01-Cluster and Save.

For some reason, The Role dropdown doesn't work, so I am doing the above using Azure CLI. If you are also unable to do, you can use the CLI.
az role assignment create --assignee $SERVICE_PRINCIPAL_ID --scope $ACR_REGISTRY_ID --role acrpull
$SERVICE_PRINCIPAL_ID, we already know, it's the appId that was outputted when we created the service principal from Azure CLI. We can get the $ACR_REGISTRY_ID from running below command.
az acr show --name $ACR_NAME --query id --output tsv
Here $ACR_NAME is our ACR name, in my case, it's playground01.

So I ran the command and I have verified it's created by going to View role assignments.

Now we are almost at the final step.

3. Deploy the service

From Azure CLI, I am running the following command to configure kubectl to connect to my K8s cluster.
PS C:\Users\Jaliya> az aks get-credentials --resource-group playground01-kubernetes-service --name playground01-kubernetes-cluster
Merged "playground01-kubernetes-cluster" as current context in C:\Users\Jaliya\.kube\config
Now I am creating 2 yml configuration files (the same way I have created for local deployments in one of my previous posts: Deploying an ASP.NET Core Application On a Local Kubernetes Cluster). I am not going to explain these in detail, please do read the above blog post for more information.

deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kube-weather-deployment
spec:
  selector:
    matchLabels:
      app: kube-weather-pod
  template:
    metadata:
      labels:
        app: kube-weather-pod
    spec:
      containers:
      - name: kube-weather-container
        image: playground01.azurecr.io/kube-weather:dev
        resources:
          limits:
            memory: "128Mi"
            cpu: "500m"
        ports:
        - containerPort: 80
The only difference in this file from my previous blog post sample is the image. Instead of picking up a local image, I am picking up the image from our ACR.

service.yml
apiVersion: v1
kind: Service
metadata:
  name: kube-weather-service
spec:
  selector:
    app: kube-weather-pod
  ports:
  - port: 9095
    targetPort: 80
  type: LoadBalancer
The next step is to deploy. I have navigated to my desktop from CLI as that's where I have my configuration files.
PS C:\Users\Jaliya\Desktop> kubectl apply -f .\deployment.yml
deployment.apps/kube-weather-deployment created
 
PS C:\Users\Jaliya\Desktop> kubectl apply -f .\service.yml
service/kube-weather-service created
 
PS C:\Users\Jaliya\Desktop> kubectl get services
NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP   PORT(S)          AGE
kube-weather-service   LoadBalancer   10.0.67.235   <pending>     9095:30943/TCP   12s
kubernetes             ClusterIP      10.0.0.1      <none>        443/TCP          74m
 
PS C:\Users\Jaliya\Desktop> kubectl get services
NAME                   TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)          AGE
kube-weather-service   LoadBalancer   10.0.67.235   40.81.10.239   9095:30943/TCP   17s
kubernetes             ClusterIP      10.0.0.1      <none>         443/TCP          74m
And the service is up. And when I browse to 40.81.10.239:9095 and it is running.
Running
Hope this helps.

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment