Run Apps on Azure Kubernetes Service

Learn how to run apps on Azure Kubernetes Service in this practical Azure Tutorial lesson. Understand the core concept, follow a step-by-step hands-on exercise, and get troubleshooting tips for common edge cases. Ideal for developers progressing through the Azure learning path.

Focus: run apps on azure kubernetes service

Sponsored

You've built the containerized app, pushed it to Azure Container Registry, and verified it locally. But the moment you try to run it as a production service, you're thrown into a world of cluster nodes, pods, and networking. Every hour spent wrestling with deployment YAML instead of shipping features is an hour lost. This lesson on how to run apps on Azure Kubernetes Service (AKS) will take you from a frustrated developer to someone who can confidently deploy, scale, and update workloads in a managed Kubernetes cluster.

The problem this lesson solves

Running containers in production is not just about having a working Docker image. You need a system that restarts failed processes, balances traffic, scales with demand, and supports rolling updates without downtime. Building that system from scratch is a project, not a side task. AKS eliminates that complexity by providing a fully managed Kubernetes control plane — but managing your cluster and deploying your app still requires a solid understanding of how Kubernetes orchestrates resources.

Without this knowledge, developers often fall into these traps:

  • Deploying containers manually on a single VM, which creates a single point of failure.
  • Writing half-hearted Kubernetes manifests that never get the app noticed by the service mesh.
  • Watching your app run in a local Docker environment but failing in the cloud due to missing service discovery.

This lesson gives you a repeatable recipe to deploy a containerized app to AKS, expose it via a public load balancer, and scale it — with the confidence that comes from knowing why everything works.

Why now? You've already learned how to containerize and push an image in earlier lessons. AKS is the natural next step because it turns that image into a resilient, production-grade service. Skipping this step means relying on fragile, ad-hoc deployments that could fall over when you least expect it.

Core concept / mental model

Think of AKS as a smart apartment building for your containers. You don't worry about plumbing, electricity, or the building's steel frame — the provider handles that. Your job is to furnish and manage the apartments (your pods) and make sure guests (user traffic) get to the right unit.

In Kubernetes terms, that mental model maps to:

  • Cluster — the entire apartment building, consisting of one or more nodes (the floors).
  • Node — a VM (the physical space) that hosts your containers.
  • Pod — the smallest deployable unit; typically one or more containers that share storage, networking, and a specification (one furnished apartment).
  • Deployment — the blueprint that says how many apartments you need and which furniture (container image) should be in each.
  • Service — the concierge that routes guest requests to the right apartment, even if that apartment moves.
  • Ingress — the main entrance with rules that direct guests to specific wings based on the URL.

When you run an app on Azure Kubernetes Service, you're essentially telling the platform: "Here's my apartment blueprint (deployment), and here's the concierge (service). Please make sure the guests find the right apartments and that we have enough available."

The key insight: Kubernetes is declarative. You describe the desired state — "I want three replicas of this container" — and the system continuously works to make reality match that description. This is what gives you self-healing apps with zero downtime.

How it works step by step

1. Set up the backing infrastructure

Before you can run anything, you need an AKS cluster. When you create a cluster with the Azure CLI or anything else, Azure provisions a control plane (the brains) and a set of node pools (the arms). The control plane is fully managed and free — you only pay for the VM nodes that actually run your workload.

2. Package and push your application

Every app gets containerized into a Docker image and pushed to a registry (usually Azure Container Registry, or ACR). The image holds your code, runtime, and dependencies. This is what makes your app portable and reproducible.

3. Write the deployment manifest

The core of running an app on AKS is a YAML file that describes your Deployment. It tells Kubernetes which image to pull, how many replicas to maintain, and what ports the container listens on.

4. Expose the app with a Service

Pods are ephemeral — they get created, destroyed, and rescheduled. To make your app accessible, you create a Service that groups your pods (using labels) and provides a stable IP address or DNS name. For public internet access, you use type: LoadBalancer.

5. Scale and update

Once the deployment is running, you can scale it up or down, and perform rolling updates without downtime. Kubernetes manages the process automatically.

6. Verify and monitor

Finally, you check that the service is responding and use kubectl logs to troubleshoot. AKS integrates with Azure Monitor for deeper visibility.

Hands-on walkthrough

Now, let's get practical. We'll deploy a simple Flask app to a new AKS cluster and expose it via a load balancer.

Prerequisites

  • An Azure subscription (if you don't have one, you can use the free tier)
  • Azure CLI installed and logged in (az login)
  • kubectl installed (or install it with az aks install-cli)

Create the cluster

First, set up a resource group and the cluster itself. Run these commands in your terminal:

# Create a resource group in a region close to you
group=aks-run-apps-demo
az group create --name $group --location eastus

# Create the AKS cluster with 2 nodes
az aks create \
  --resource-group $group \
  --name aks-demo-cluster \
  --node-count 2 \
  --enable-managed-identity \
  --generate-ssh-keys

# Get credentials so kubectl can talk to the cluster
az aks get-credentials --resource-group $group --name aks-demo-cluster

# Verify the cluster nodes are ready
kubectl get nodes

All timed out? Creating a cluster usually takes 5–10 minutes. It's normal. Use that period to prepare your deployment manifest.

Prepare your simple web app

If you don't have a container image yet, let's quickly build one. Create a folder with the following files:

app.py:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def home():
    return "Hello from AKS!"

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)

Dockerfile:

FROM python:3.10-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

requirements.txt:

Flask==2.3.3

Now push it to an Azure Container Registry. If you don't have an ACR instance, create one in the same resource group:

# Create an Azure Container Registry
az acr create --resource-group $group --name acrunique789 --sku Standard

# Login and push your image
az acr login --name acrunique789
docker build -t acrunique789.azurecr.io/hello-app:v1 .
docker push acrunique789.azurecr.io/hello-app:v1

Deploy the application to AKS

Now for the heart of the lesson. Create a file called deploy.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-app-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-app
  template:
    metadata:
      labels:
        app: hello-app
    spec:
      containers:
      - name: hello-app
        image: acrunique789.azurecr.io/hello-app:v1
        ports:
        - containerPort: 5000
---
apiVersion: v1
kind: Service
metadata:
  name: hello-app-service
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 5000
  selector:
    app: hello-app

Apply it:

kubectl apply -f deploy.yaml

Wait a minute, then check the status:

kubectl get pods
kubectl get service hello-app-service

The service will get an external IP. Wait for it to change from <pending> to an actual IP address:

kubectl wait --for=jsonpath='{.status.loadBalancer.ingress[0].ip}' service/hello-app-service --timeout=180s

Then curl the IP:

IP=$(kubectl get service hello-app-service -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl http://$IP

Expected output:

Hello from AKS!

Scale the application

To handle more traffic, scale up your deployment:

kubectl scale deployment hello-app-deployment --replicas=5

Verify the new pods:

kubectl get pods

You'll see 5 pods running across your nodes. This is horizontal scaling — a key reason to run apps on AKS.

Clean up

When you're done, delete the resource group to avoid incurring costs:

az group delete --name $group --yes --no-wait

Pro tip: Use az aks update --enable-cluster-autoscaler with node pools to let the cluster automatically grow and shrink based on load. That's when you really feel the power of Kubernetes.

Compare options / when to choose what

When you need to run apps on Azure Kubernetes Service, you have a few alternatives. The table below helps you decide based on your needs.

Option Control Complexity Best for
AKS Full Kubernetes control (kubectl everything) Moderate Teams needing portability, custom scaling rules, multi-container apps
Azure Container Apps (ACA) Managed abstraction, pay-per-run Low Microservices, serverless scaling, quick ramp-up
Azure App Service Highest abstraction, just push code Very low Web apps and APIs without container orchestration needs

When to choose AKS:

  • You need to orchestrate multiple interconnected services with service discovery.
  • You want to run stateful workloads with persistent volumes.
  • You have existing Kubernetes skill sets or need portability to any K8s cluster.
  • You need fine-grained control over networking, secrets, or autoscaling.

When to choose ACA instead:

  • Your app is event-driven and scales to zero.
  • You prefer not to manage clusters or nodes.
  • You want built-in service-to-service communication.

Your call: If a single Docker container is all you have, App Service or ACA might be overkill. But if you plan to grow into a microservices architecture, investing in AKS now pays off later.

Troubleshooting & edge cases

Pod stuck in ImagePullBackOff

Cause pattern: The image you referenced doesn't exist, or AKS can't authenticate to your private ACR registry.

Fix: Push the image, re-pull it locally to verify, and attach ACR to AKS:

az aks update --resource-group $group --name aks-demo-cluster --attach-acr acrunique789

Also check the image tag in the YAML — a typo like :v1 vs :latest will trip you up.

External IP stays <pending>

Cause: The pod is running, but the LoadBalancer can't allocate an IP — this often happens when the cluster doesn't have enough quota, or you're using a network policy that blocks it.

Fix: Wait a bit (it can take a few minutes), then check the service events:

kubectl describe service hello-app-service

If you see a quota error, request more IPs. If you see a network issue, your node pool may not have outbound access.

kubectl gets an “unauthorized” error

Cause: Your local kubeconfig is stale or points to the wrong cluster.

Fix: Fetch credentials again:

az aks get-credentials --resource-group $group --name aks-demo-cluster --overwrite-existing

Then test with kubectl get nodes.

Zero pods after scaling up

Cause: The cluster autoscaler isn't enabled, and your node pool doesn't have enough capacity for the new replicas.

Fix: Check the node status with kubectl describe nodes. If they're full, scale the node pool manually:

az aks scale --resource-group $group --name aks-demo-cluster --node-count 3

Deployment is running but the app returns 502 Bad Gateway

Cause: The container is listening on a different port than the one in targetPort.

Fix: Double-check the port your Flask app actually uses (often 5000, but you might have changed it). Update the service targetPort and re-apply.

What you learned & what's next

You've conquered the core of running apps on Azure Kubernetes Service. Here's what you can now do confidently:

  • Explain what AKS is and why it's the standard for production container orchestration on Azure.
  • Set up a cluster with Azure CLI and connect via kubectl.
  • Write a Deployment and Service manifest that actually works.
  • Expose your app publicly with a load balancer and access it.
  • Scale your app horizontally and troubleshoot common issues.

This is the bread and butter of day-to-day Kubernetes work. You're ready to move on to more advanced topics like persistent storage, ingress controllers, or monitoring with Azure Monitor.

Next lesson: The natural next step is Service Mesh and Ingress with AKS. You'll learn how to route traffic, add TLS, and handle internal service communication. That builds directly on the deployment patterns you just mastered.

Practice recap

Now take your favorite containerized app from the earlier lesson, deploy it to a new AKS cluster using the same pattern you just learned. Try changing the number of replicas to 4 and confirm via kubectl get pods. If you're ready for a challenge, add a second service and try communicating between pods using service discovery.

Common mistakes

  • Using targetPort: 5000 but your app listens on port 80, causing 503 errors on the load balancer.
  • Trying to access the service immediately after apply — it takes 1–3 minutes for the external IP to be provisioned.
  • Forgetting to attach your private ACR to AKS, leading to ImagePullBackOff errors on every pod.
  • Scaling up to many replicas but leaving the cluster autoscaler disabled, so your nodes run out of capacity.

Variations

  1. Use kubectl create with imperative commands instead of YAML files for quick tests.
  2. Expose your app using a NodePort service instead of LoadBalancer when you want internal access only.
  3. Deploy via an Azure DevOps pipeline to automate the build and deployment steps.

Real-world use cases

  • A SaaS platform deploys microservices with rolling updates, ensuring zero downtime for users during each release.
  • An e-commerce site scales the order-checkout service to handle holiday traffic spikes automatically using cluster autoscaler.
  • A data-processing company runs batch jobs in pods that process files from Blob storage, then scales back to zero between runs.

Key takeaways

  • AKS gives you a managed Kubernetes control plane, so you're responsible for your pods, services, and scaling, but not the masters.
  • Declarative YAML manifests (Deployment + Service) are the heart of running an app on AKS.
  • Always use a LoadBalancer service to expose your app publicly — it provisions a public IP automatically.
  • Horizontal scaling is as simple as kubectl scale — but enable cluster autoscaler for automatic node scaling.
  • Attach your ACR instance to the cluster to avoid ImagePullBackOff errors with private images.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.