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.