Containers and Kubernetes have traditionally been the area of Linux-based workloads. However, things have changed. Windows has supported Docker containers for a while now, and since Kubernetes 1.14, Windows support has been generally available in Kubernetes as well.
In this blog post, we’ll explore how you can add Windows nodes to a Kubernetes cluster running on Azure. After we’ve set up the cluster, we’ll have a look at how actual Windows containers can be created on the cluster.
Setting up the cluster
To run Windows containers on AKS, we’ll need the following:
- An AKS cluster
- (at least) 1 Linux Nodepool. This is used for running system components such as CoreDNS.
- A Windows Nodepool
Let’s create all of this using the Azure CLI:
# Create a resource group az group create -n win-aks -l westus2 # Create the cluster, with the default linux nodepool az aks create -g win-aks -n win-aks \ --node-count 2 --ssh-key-value ~/.ssh/id_rsa.pub \ --windows-admin-username nilfranadmin \ --windows-admin-password superSecret123! \ --network-plugin azure # Create a second nodepool using Windows az aks nodepool add -g win-aks \ --cluster-name win-aks \ --os-type Windows --name winnp \ --node-count 2
The second command will take some time to run (about 15 minutes), but after a while, we will be able to go ahead and schedule Windows containers. While you’re waiting for the node pool to be added, let’s explore how we need to tell Kubernetes to schedule a Windows workload on Windows nodes.
A little info about labels and nodeSelectors
Once you have a cluster with both Linux and Windows nodes, you should be able to run
kubectl get nodes -o wide and see you now have nodes with a Windows operating system:
What’s more, these nodes are also labeled with their OS information. To see those labels, run a
kubectl describe node <windows-node-name>:
To schedule pods on a Windows node (or a Linux node for that matter) you’ll have to set a
nodeSelector in the pod definition. In the node selector, you define which labels on the nodes need to be met to schedule pods on certain nodes. In case of the operating system, we’ll set the
kubernetes.io/os label to Windows in the
What’s important to note here: if you run in a mixed cluster (with both Linux and Windows nodes and workloads), you need to include the
nodeSelector for both Windows and Linux workloads. Otherwise, Kubernetes might schedule Linux pods on Windows nodes (or vice-versa), and that will lead to issues.
Let’s have a look at how to do that:
How to schedule pods on Windows nodes
As mentioned in the previous section, to schedule a pod on a Windows node, you need to include a
nodeSelector in your workload definition. An example of that below (code is also available on GitHub):
apiVersion: apps/v1 kind: Deployment metadata: labels: app: win-webserver name: win-webserver spec: replicas: 2 selector: matchLabels: app: win-webserver template: metadata: labels: app: win-webserver name: win-webserver spec: containers: - name: windowswebserver ports: - containerPort: 80 name: http protocol: TCP - containerPort: 443 name: https image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2019 nodeSelector: kubernetes.io/os: windows
This will create a deployment, containing 2 IIS web servers. To verify that things work well, let’s also include a service to route traffic to these IIS servers. Note how the service definition isn’t any different for Windows vs Linux workloads.
apiVersion: v1 kind: Service metadata: name: win-webserver labels: app: win-webserver spec: selector: app: win-webserver ports: - port: 80 targetPort: 80 type: LoadBalancer
We can deploy both using:
kubectl create -f . .
It will take a while for the pods to spin up since Windows images are generally a bit bigger than Linux images. But after a couple of minutes, you should see your Windows pods running, which you can confirm using
kubectl get pods -o wide:
And we can now also browse to the service. To get its public IP, use
kubectl get svc:
And if we browse to that IP, you can see a glorious IIS web server running on Kubernetes:
And that’s how you run Windows containers on AKS.
In this blog post, we looked into how to run Windows containers on the Azure Kubernetes Service (AKS). We created a new AKS cluster, and we added a Windows nodepool. After that, we scheduled an actual workload on the nodes in that pool. To do this, we used the
nodeSelector in the pod definition.
If you’re interested to take this one step further and also run Windows pods on ACI instances using the virtual kubelet, check out this blog post.