Introduction

Kubernetes on Windows Server 2022 allows you to run Windows containerized workloads alongside Linux containers in a mixed-OS cluster. Since Kubernetes control plane components (API server, scheduler, controller manager, etcd) only run on Linux, a Windows Server 2022 node always joins an existing cluster as a worker node — it cannot act as a control plane node. k3s, a lightweight Kubernetes distribution from Rancher Labs, simplifies cluster setup significantly and supports Windows worker nodes as of k3s v1.28+. This guide covers the architecture of a Linux + Windows mixed cluster, Windows worker node requirements, installing containerd and kubelet, joining a Windows node to a k3s cluster, deploying Windows workloads with node selectors, and Windows container networking with Flannel and Calico.

Windows on Kubernetes: Architecture Overview

A mixed Linux/Windows Kubernetes cluster has two tiers of nodes:

Linux nodes run the Kubernetes control plane (in the case of k3s, the server node runs all control plane components plus a worker) and schedule both Linux and Windows workloads depending on pod affinity rules.

Windows nodes run only Windows containers. The Kubernetes node agent (kubelet), container runtime (containerd), and CNI plugin (Flannel or Calico) run as Windows services. Windows nodes support process isolation and Hyper-V isolation for pods.

The control plane communicates with Windows nodes via the Kubernetes API exactly as it does with Linux nodes. Windows nodes report Windows-specific labels such as kubernetes.io/os=windows and kubernetes.io/arch=amd64 that pod specs use to target specific node types.

Windows Worker Node Requirements

Before setting up a Windows worker node, verify the following requirements are met on the Windows Server 2022 machine:

The Windows Containers feature must be installed:

Install-WindowsFeature -Name Containers -Restart

If you plan to use Hyper-V isolation for pods, install the Hyper-V feature as well:

Install-WindowsFeature -Name Hyper-V -IncludeManagementTools -Restart

Ensure the node has at least 4 GB of RAM (8 GB recommended for production), 2 vCPUs, and network connectivity to the Linux k3s server node. Windows Defender real-time protection should be configured to exclude Kubernetes directories to avoid performance and file-lock issues:

Add-MpPreference -ExclusionPath "C:varlibrancher","C:runflannel","C:optcni"

Setting Up the Linux k3s Server Node

On a Linux machine (Ubuntu 22.04 or RHEL 9 recommended), install k3s as the server node. Specify the Flannel backend as host-gw for Windows compatibility (vxlan works but host-gw has better Windows support in many configurations):

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --flannel-backend=host-gw --cluster-cidr=10.244.0.0/16" sh -

After k3s starts, retrieve the node token that Windows nodes will use to join the cluster:

cat /var/lib/rancher/k3s/server/node-token

Also note the server’s IP address, which Windows nodes need to connect to the API server. Verify the Linux node is ready:

kubectl get nodes

Installing containerd on the Windows Node

containerd is the container runtime for Windows nodes in Kubernetes. Download and install the official containerd release for Windows. Open PowerShell as Administrator on the Windows Server 2022 node:

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$containerdVersion = "1.7.13"
Invoke-WebRequest -Uri "https://github.com/containerd/containerd/releases/download/v${containerdVersion}/containerd-${containerdVersion}-windows-amd64.tar.gz" -OutFile C:containerd.tar.gz
mkdir -Force C:Program Filescontainerd
tar.exe -xvf C:containerd.tar.gz -C "C:Program Filescontainerd"

Register containerd as a Windows service:

& "C:Program Filescontainerdbincontainerd.exe" config default | Out-File "C:Program Filescontainerdconfig.toml" -Encoding ascii
& "C:Program Filescontainerdbincontainerd.exe" --register-service
Start-Service containerd
Set-Service -Name containerd -StartupType Automatic

Verify containerd is running:

Get-Service containerd

Installing kubelet and kube-proxy on the Windows Node

Rancher provides a Windows agent installer script for k3s that automates kubelet and kube-proxy setup. Run this on the Windows node, substituting the Linux server IP and node token retrieved earlier:

$K3S_TOKEN = "K10abc123yourtokenhere"
$K3S_URL = "https://192.168.1.100:6443"
Invoke-WebRequest -Uri https://github.com/k3s-io/k3s/releases/latest/download/k3s-windows-amd64.exe -OutFile C:k3sk3s.exe
C:k3sk3s.exe agent --server $K3S_URL --token $K3S_TOKEN

For a service-based installation that starts automatically on boot, Rancher provides a dedicated Windows agent installer:

Invoke-WebRequest -Uri "https://raw.githubusercontent.com/k3s-io/k3s/master/contrib/util/win-agent-install.ps1" -OutFile C:win-agent-install.ps1
.win-agent-install.ps1 -Token $K3S_TOKEN -ServerUrl $K3S_URL

After the agent starts, switch back to the Linux server and verify the Windows node appears:

kubectl get nodes -o wide

The Windows node should show Ready status with kubernetes.io/os=windows in its labels.

kubectl on Windows

You can install kubectl directly on the Windows node or on a management machine to interact with the k3s cluster. Download kubectl for Windows:

$kubectlVersion = "v1.30.0"
Invoke-WebRequest -Uri "https://dl.k8s.io/release/${kubectlVersion}/bin/windows/amd64/kubectl.exe" -OutFile C:kubectlkubectl.exe

Add C:kubectl to the PATH:

[System.Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:kubectl", [System.EnvironmentVariableTarget]::Machine)

Copy the kubeconfig from the Linux server to the Windows machine:

# On the Linux server:
cat /etc/rancher/k3s/k3s.yaml

Paste the content into C:UsersAdministrator.kubeconfig on the Windows machine, and replace 127.0.0.1 in the server field with the Linux server’s actual IP address. Then test connectivity:

kubectl get nodes
kubectl cluster-info

Deploying Windows Workloads with nodeSelector

Windows containers can only run on Windows nodes. Use a nodeSelector in your pod spec to ensure Windows pods are scheduled on Windows nodes:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: iis-deployment
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: iis
  template:
    metadata:
      labels:
        app: iis
    spec:
      nodeSelector:
        kubernetes.io/os: windows
      containers:
      - name: iis
        image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"

Apply the deployment:

kubectl apply -f iis-deployment.yaml

Verify the pods are running on the Windows node:

kubectl get pods -o wide

The NODE column should show the Windows Server 2022 node name. To expose the IIS deployment as a service:

kubectl expose deployment iis-deployment --type=NodePort --port=80

Windows Container Networking: Flannel and Calico

Container networking on Windows nodes requires a CNI plugin that supports Windows. The two most common choices are Flannel (with the host-gw or overlay backend) and Calico (with VXLAN or BGP).

Flannel with host-gw is the simplest option for small clusters where all nodes are on the same L2 network segment. k3s deploys Flannel automatically on Linux nodes; the Windows Flannel configuration is applied via a DaemonSet that installs the Flannel CNI plugin files on Windows nodes:

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

The Flannel DaemonSet includes a nodeSelector for Linux (kubernetes.io/os: linux) for the Linux flanneld pod and a separate Windows DaemonSet for Windows nodes.

Calico on Windows supports BGP and VXLAN modes and provides network policy enforcement. Install the Calico operator and configure the Windows node IPPool:

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/tigera-operator.yaml

Then apply the installation manifest that includes a WindowsNode configuration section targeting Windows Server 2022 nodes with VXLAN networking.

Mixed Linux/Windows Cluster Considerations

In a mixed cluster, Linux pods must also have a nodeSelector or toleration to prevent them from accidentally scheduling on Windows nodes, since Linux container images cannot run on Windows. Add a nodeSelector to Linux deployments:

nodeSelector:
  kubernetes.io/os: linux

System pods (kube-proxy, CoreDNS, metrics-server) deployed by k3s are already configured with Linux node selectors. Custom workloads require explicit node targeting.

Monitoring Windows Nodes

The Kubernetes Metrics Server collects resource usage from all nodes. Install it on the Linux control plane:

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Once running, check resource usage on Windows nodes:

kubectl top node
kubectl top pods --all-namespaces

For more detailed monitoring, deploy the Prometheus Windows Exporter as a DaemonSet on Windows nodes. It exposes Windows performance counters (CPU, memory, disk, network) in Prometheus format:

kubectl apply -f https://raw.githubusercontent.com/prometheus-community/windows_exporter/master/kubernetes/windows-exporter-daemonset.yaml

Label Windows nodes to target the DaemonSet correctly:

kubectl label node win-node-01 node.kubernetes.io/windows-build=10.0.20348

Troubleshooting Windows Node Issues

Check the kubelet service status on the Windows node:

Get-Service k3s-agent

View kubelet logs to diagnose pod scheduling or networking problems:

Get-EventLog -LogName Application -Source k3s -Newest 50

Check containerd logs:

Get-EventLog -LogName Application -Source containerd -Newest 50

Describe a problematic pod to see scheduling and startup events:

kubectl describe pod iis-deployment-abc123

Conclusion

Running Kubernetes workloads on Windows Server 2022 with k3s provides a lightweight path to managing Windows containers at scale alongside Linux containers. By configuring a Linux k3s server node, installing containerd and the k3s agent on Windows Server 2022 worker nodes, and using nodeSelector to target Windows pods, you can build a functional mixed-OS cluster. Combined with Flannel or Calico for networking and kubectl for management, k3s on Windows Server 2022 delivers a production-capable container orchestration platform for Windows-native workloads.