How to Set Up Windows Server 2019 Azure Kubernetes Service

Azure Kubernetes Service (AKS) on Windows Server 2019 refers to running AKS worker nodes on Windows Server 2019, enabling containerized Windows applications to run in a Kubernetes cluster alongside Linux workloads. Windows nodes in AKS are fully supported and can run Windows Server containers, IIS applications, and .NET Framework workloads. This guide covers the prerequisites, deployment, and configuration of Windows nodes in an AKS cluster using Windows Server 2019 as the node OS.

Prerequisites

To deploy AKS with Windows Server 2019 nodes, you need an Azure subscription, the Azure CLI installed and configured, and sufficient quota for the VM SKUs you plan to use. Install the Azure CLI on a management workstation:

Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .AzureCLI.msi
Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'
az version

Log in to Azure and set the target subscription:

az login
az account set --subscription "My Production Subscription"
az account show

Creating an AKS Cluster with Windows Node Support

AKS clusters must be created with a Windows-specific configuration. Create a resource group and then the AKS cluster with a Linux system node pool and a Windows user node pool. The cluster must use Azure CNI networking for Windows node support:

az group create --name rg-aks-windows --location eastus

az aks create `
    --resource-group rg-aks-windows `
    --name aks-ws2019-cluster `
    --node-count 2 `
    --node-vm-size Standard_DS2_v2 `
    --network-plugin azure `
    --generate-ssh-keys `
    --windows-admin-username winsvcadmin `
    --windows-admin-password "W1nd0ws@dmin2019!" `
    --vm-set-type VirtualMachineScaleSets `
    --enable-cluster-autoscaler `
    --min-count 1 `
    --max-count 5

Adding a Windows Server 2019 Node Pool

After creating the cluster, add a Windows node pool specifying the Windows Server 2019 OS SKU. Windows node pools must be of type User:

az aks nodepool add `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --os-type Windows `
    --os-sku Windows2019 `
    --name winnp2019 `
    --node-count 2 `
    --node-vm-size Standard_D4s_v3 `
    --node-taints "os=windows:NoSchedule"

Verify the node pool was added and nodes are in Ready state:

az aks nodepool list `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --output table

Configuring kubectl Access

Download the AKS cluster credentials to configure kubectl on your workstation:

az aks get-credentials `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --overwrite-existing

kubectl get nodes -o wide

Verify that both Linux and Windows nodes appear and are in the Ready state:

kubectl get nodes --show-labels | grep -E "kubernetes.io/os"
kubectl describe node 

Deploying a Windows Application

Windows workloads must be scheduled on Windows nodes using node selectors or tolerations. Create a deployment YAML for an IIS-based Windows container application:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: iis-windows
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: iis-windows
  template:
    metadata:
      labels:
        app: iis-windows
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      tolerations:
      - key: "os"
        operator: "Equal"
        value: "windows"
        effect: "NoSchedule"
      containers:
      - name: iis
        image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019
        resources:
          limits:
            cpu: "1"
            memory: "1Gi"
          requests:
            cpu: "500m"
            memory: "512Mi"
        ports:
        - containerPort: 80

Apply the deployment:

kubectl apply -f iis-windows-deployment.yaml
kubectl get pods -o wide --watch

Exposing Windows Applications

Create a LoadBalancer service to expose the IIS application externally:

apiVersion: v1
kind: Service
metadata:
  name: iis-windows-svc
spec:
  type: LoadBalancer
  selector:
    app: iis-windows
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80
kubectl apply -f iis-service.yaml
kubectl get service iis-windows-svc --watch

Scaling Windows Node Pools

Manually scale the Windows node pool when additional capacity is needed:

az aks nodepool scale `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --name winnp2019 `
    --node-count 4

Enable or update the autoscaler settings for the Windows node pool:

az aks nodepool update `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --name winnp2019 `
    --enable-cluster-autoscaler `
    --min-count 2 `
    --max-count 10

Upgrading Windows Node Pools

List available Kubernetes upgrade versions:

az aks get-upgrades `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --output table

Upgrade the control plane first, then node pools:

az aks upgrade `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --kubernetes-version 1.28.3 `
    --control-plane-only

az aks nodepool upgrade `
    --resource-group rg-aks-windows `
    --cluster-name aks-ws2019-cluster `
    --name winnp2019 `
    --kubernetes-version 1.28.3

Windows Server 2019 nodes in AKS provide a powerful platform for running Windows workloads in Kubernetes. The combination of Azure CNI networking, autoscaling, and the ability to mix Linux and Windows workloads in the same cluster makes AKS the recommended approach for organizations adopting Kubernetes while still running Windows-dependent applications.