🟦 Application Deployment in Azure Kubernetes Service (AKS)

What is AKS (Azure Kubernetes Service)?

Azure Kubernetes Service (AKS) is a managed container orchestration service provided by Microsoft Azure. It allows you to deploy, manage, and scale containerized applications using Kubernetes without needing to manage the underlying infrastructure.

Prerequisites:

  • Install Azure Cli

To install Azure CLI using Winget, run the following command in Command Prompt:

winget install Microsoft.AzureCLI
  • After installation, log into Azure to see if it's functioning by running below command:
az login

This will redirect to Microsoft Login page you will need to login to your Azure account.

Then run below command to Install kubectl using Azure CLI:

az aks install-cli

Creating AKS Cluster:

  • Go to https://portal.azure.com and sign in to your Azure account.

  • Navigate to Services > Kubernetes Services.

    Azure Kubernetes

  • Click Create > Kubernetes Cluster.

    Azure Kubernetes

  • On the creation page:

    • Select the desired Resource Group.

    • Choose a Cluster Preset Configuration (click Compare presets to evaluate options).

    • Set the Cluster name (e.g., leasetool, SCMWebAPP) and Region (e.g., South India).

    Azure Kubernetes

Node Pool Configuration

  • On the Node Pools page:

    • Either add a new node pool or update the existing agentpool.

    • Click the node name to update.

    Azure Kubernetes

    • Adjust Node Size by clicking on "Choose a size" based on the requirement and set Minimum Node Count and Maximum Node Count (e.g., 1 to 2).

    • Click Update.

    Azure Kubernetes

Networking Configuration

  • On the Networking page:

    • Choose Azure CNI Overlay.

    • If using AGIC (Application Gateway Ingress Controller) for SSL/Firewall, select Azure CNI with Node Subnet.

    Azure Kubernetes

    • Review and click Create. The process may take 5–10 minutes.

    Azure Kubernetes

Deployment Process:

  • Once AKS is created, perform the following steps in Command Prompt: Login to ACR(Here using Docker, can be replaced with respective container runtime to pull image):
docker login planvisage.azurecr.io --username <User Name> --password <Password>

Run this command to check the available containers in ACR:

az acr repository list --name <UserName> --output table

Login to Azure and set the subscription

az login
az account set --subscription <YourSubscriptionName>

(To get subscriptions: az account list --output table)

Get AKS credentials:

az aks get-credentials --resource-group <YourResourceGroup> --name <YourAksCluster>

• Create a Kubernetes Image Pull Secret:

First create a namespace under kubectl

kubectl create namespace pvtest

Now create Secret:

In Azure Kubernetes Service (AKS), a Secret is an object used to securely store sensitive data

kubectl create secret docker-registry acr-secret ^
--namespace=pvtest ^
--docker-server=planvisage.azurecr.io ^
--docker-username=<ACR UserName> ^
--docker-password=<ACR Password> ^
--docker-email=<Your Email>

• Create a folder and inside it create two YAML files one for deployment and another for services named as below:

deployment.yaml and service.yaml

• Create service.yaml file:

Sample service.yaml file

    apiVersion: v1  # Uses the core Kubernetes API. 
    kind: Service   # Defines a Service, which enables communication between components inside the cluster. 
    metadata:
      name: leasetool-service  # The name of the service.
      namespace: pvtest   # Add this if your deployment is in 'pvtest'
    spec:
      type: LoadBalancer     # The service is accesible Public/ For AGIC and Private need to use: ClusterIP
      selector:              # Matches pods with the Label app: leasetool
        app: leasetool       # Any pods with this Label will be part of the service.
      ports:
      - port: 80              # The port on the service that other component will use.
        targetPort: 8080      # The port on the pod where traffic is directed.

🔹 Optional: Using Application Gateway with AKS (Internal / Intranet Setup)

This section is optional and should be followed only if the application needs to be accessed internally (intranet) or requires centralized traffic control.

By default, the Service created in AKS exposes the application using a public Azure Load Balancer. If you want the application to be accessible only within a private network, or if you plan to use Application Gateway for routing, SSL termination, or firewall (WAF), Application Gateway can be integrated with AKS.

Important prerequisites for Application Gateway integration

  • AKS and Application Gateway must be deployed in the same Virtual Network (VNET) (They should be in different subnets, but within the same VNET)

  • Application Gateway will act as the entry point for user traffic

  • The AKS service should be internal, not public.

When using Application Gateway, update the service.yaml as shown below:

apiVersion: v1
kind: Service
metadata:
  name: leasetool-service
  namespace: pvtest
  annotations:
    service.beta.kubernetes.io/azure-load-balancer-internal: "true"
spec:
  type: LoadBalancer
  selector:
    app: leasetool
  ports:
    - port: 80 
      targetPort: 8080

🔹 This annotation ensures that the service is exposed internally within the VNET, allowing Application Gateway to route traffic to it.

• Now create deployment.yaml file:

Sample deployment.yaml file

apiVersion: apps/v1
kind: Deployment
metadata:
  name: leasetool   #This is the name of the Deployment, can replace with the required ApplicationName (eg: SCMWebApp..)
  namespace: pvtest
spec:
  replicas: 1       #This speocifies that one pod should be running at all times
  selector:
    matchLabels:
      app: leasetool #This is the name of the Application, can be replaced the required ApplicationName (eg: SCMWebApp..)
  template:          #This template defines how the pod should be created.
    metadata:
      labels:         #Each pod will have labelapp: leasetool so that deployment can be manage it.
        app: leasetool #This is the name of the Application, can be replaced with the required ApplicationName (eg: SCMWebApp..)
    spec:              #Pod specification
      imagePullSecrets: 
      - name: acr-secret  # ImagePullSecret: Secret Name: acr-secret, which is used to pull the images from ACR
      # 🔐 POD-LEVEL SECURITY (applies to all containers)
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000


      containers:
      - name: leasetool  #The container is named leasetool, can be replaced the required ApplicationName (eg: SCMWebApp..)
        image: planvisage.azurecr.io/leasetool:latest  #It pulls the latest Leasetool images. Need to replace with respective Image Path.
        imagePullPolicy: Always

        ports:
        - containerPort: 8080  # Exposes port 8080 inside container.
        # 🔐 CONTAINER-LEVEL SECURITY
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000
          capabilities:
            drop:
              - ALL

        env:                   # Setting Environment Variables
        - name: TIME_ZONE
          value: "Asia/Kolkata"
        - name: DB_CONNECTSTR
          value: ""
        - name: DB_TYPE
          value: ""
        - name: BLOB_CONNECTSTR
          value: ""
        - name: BLOB_CONTAINER_NAME
          value: ""
        - name: LOG_TARGET
          value: "FILE"
        - name: SECURE_COOKIE 
          value: "False"  # False since we have not set SSL for the testing, this can be set to True when SSL is setup.

        # 📦 VOLUME MOUNTS
        # REQUIRED when readOnlyRootFilesystem = true
        volumeMounts:
        # Writable temp directory (required for read-only root FS)
        - name: tmp
          mountPath: /tmp
        # Writable directory for application logs
        - name: applogs
          mountPath: /app/wwwroot/log
        - name: appconfig
          mountPath: /app/wwwroot/xml
        - name: appdata
          mountPath: /app/wwwroot/data
        - name: appdesign
          mountPath: /app/wwwroot/design



      # 📦 VOLUMES
      volumes:
       # Logs volume
      - name: applogs
        emptyDir: {}
      # congif volume
      - name: appconfig
        emptyDir: {}
      # data volume
      - name: appdata
        emptyDir: {}
      # design volume
      - name: appdesign
        emptyDir: {}
      # Temp directory
      - name: tmp
        emptyDir: {}

The environment variables used in the above deployment.yaml (such as database connection strings, blob storage configuration, logging, and security settings) are explained in detail in the document below.

Refer to: Application Environmental Variables

🔹 Optional: Using Azure Key Vault for Sensitive Configuration

This section is optional and should be followed if you wish to setup keyvault to fetch sensitive configuration values such as database connection strings, storage keys, or secrets.

In the basic deployment, sensitive values (e.g., database connection strings) are defined directly in the deployment.yaml file. This approach is not recommended for production environments.

Azure Key Vault provides a secure way to:

  • Store secrets centrally

  • Control access using Managed Identity

  • Avoid hardcoding sensitive data in YAML files

Refer to: How to setup Azure KeyVault for AKS

• In Command Prompt, navigate to the folder containing the YAML files and run:

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml 
kubectl rollout status deployment <kuberneteappname> -n <namespace>

KuberneteAppName refers to the name of the Deployment defined in the deployment.yaml file. In this case, it is set to "leasetool", and the corresponding namespace is "pvtest".

• Check if the pods are running:

kubectl get pods -n <namespace>

EX:

C:\AKSTest>kubectl get pods -n pvtest
NAME                         READY   STATUS    RESTARTS   AGE
leasetool-7585f58f68-xz5n4   1/1     Running   0          39s

• Check if the service is running:

kubectl get svc <Service Name> -n <Namespace>

EX:

C:\AKSTest>kubectl get svc leasetool-service -n pvtest
NAME                TYPE           CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
leasetool-service   LoadBalancer   10.0.149.4   4.247.24.42   80:31417/TCP   15s

Copy the External IP displayed by the kubectl get svc command.

  • If the service is configured without a private network, open a browser and access the application using:

http://<External-IP>

Ex: http://4.247.24.42/

  • If the service is configured for a private network using Application Gateway, the application will not be accessible publicly. In this case, the application can be accessed only from within the same VNET. (To test we can create a VM (Lynux/Windows) in the same VNET and access the app through the externalIP.)

To enable private access using Application Gateway, follow the steps in the section below.

Refer to: How to setup Azure Application Gateway for AKS