Windows workers
Overview#
k0smotron supports Windows worker nodes as an experimental feature, allowing you to run Linux and Windows workloads in the same Kubernetes cluster. This capability is particularly useful for organizations maintaining both modern Linux services and Windows applications.
Requirements#
- At least one Linux worker node for CoreDNS
- Windows nodes with appropriate PowerShell remoting capabilities
- Calico CNI for networking
Limitations#
- Windows worker support is experimental
- Control plane must run on Linux
- Requires Linux worker for cluster DNS services
Architecture#
The control plane runs on Linux nodes only. Both Linux and Windows worker nodes can join the same cluster:
┌─────────────────────────────────────┐
│ k0s Control Plane │
│ (Linux - API Server, etcd, etc.) │
└─────────────────────────────────────┘
│
┌─────────────────────────┐
▼ ▼
┌─────────────────────┐ ┌─────────────────────┐
│ Linux Worker │ │ Windows Worker │
└─────────────────────┘ └─────────────────────┘
│ - CNI (Calico) │ │ - CNI (Calico) │
│ - CoreDNS │ │ - Windows Workloads │
│ - Linux Workloads │ │ (.NET, IIS, SQL) │
│ (NGINX, Node.js) │ └─────────────────────┘
└─────────────────────┘
Networking#
k0s has native Calico support that provides networking for both Linux and Windows nodes
DNS#
CoreDNS runs on Linux workers and serves the entire cluster, including Windows pods. At least one Linux worker node is required in the cluster.
Configuration#
K0sWorkerConfig#
Windows worker nodes are configured using the platform field in K0sWorkerConfig:
apiVersion: k0smotron.io/v1beta1
kind: K0sWorkerConfig
metadata:
name: windows-worker
spec:
version: v1.34.2+k0s.0
provisioner:
platform: windows # Specify Windows platform (default is linux)
type: powershell # Specify provisioning format
Provisioning#
Default cloud-init provisioning type is supported for Windows, as well as two Windows-specific formats available:
- cloud-init - e.g. for RemoteMachine provider
- powershell - Standard PowerShell script
- powershell-xml - PowerShell wrapped in XML (AWS user data compatible)
Provisioner types by provider:
| Provider | Provisioner Type |
|---|---|
| AWS | powershell-xml |
| k0smotron RemoteMachine | cloud-init |
| … | … |
Use Cases#
Windows worker support enables:
- Hybrid clusters: Run Linux and Windows nodes in the same cluster
- Gradual migration: Containerize Windows applications incrementally
- Unified operations: Single control plane, API, and operational model
- Legacy application support: Run Windows-only workloads alongside modern services
Full Example with AWS#
apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
name: aws-test-cluster
namespace: default
spec:
clusterNetwork:
pods:
cidrBlocks:
- 192.168.0.0/16
serviceDomain: cluster.local
services:
cidrBlocks:
- 10.128.0.0/12
controlPlaneRef:
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: K0sControlPlane
name: aws-test
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSCluster
name: k0s-aws-test
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSMachineTemplate
metadata:
name: k0s-aws-test-mt-cp
namespace: default
spec:
template:
spec:
uncompressedUserData: false
ami:
# Replace with your AMI ID
id: ami-0fa91bc90632c73c9 # Ubuntu in eu-north-1
instanceType: t3.large
iamInstanceProfile: nodes.cluster-api-provider-aws.sigs.k8s.io # Instance Profile created by `clusterawsadm bootstrap iam create-cloudformation-stack`
cloudInit:
# Makes CAPA use k0s bootstrap cloud-init directly and not via SSM
# Simplifies the VPC setup as we do not need custom SSM endpoints etc.
insecureSkipSecretsManager: true
sshKeyName: <your-ssh-key-name>
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSMachineTemplate
metadata:
name: k0s-aws-test-mt-worker
namespace: default
spec:
template:
spec:
publicIP: true
ami:
# Replace with your AMI ID
id: ami-010e40c6557403885 # Windows in eu-north-1
instanceType: t3.medium
iamInstanceProfile: nodes.cluster-api-provider-aws.sigs.k8s.io # Instance Profile created by `clusterawsadm bootstrap iam create-cloudformation-stack`
cloudInit:
# Makes CAPA use k0s bootstrap cloud-init directly and not via SSM
# Simplifies the VPC setup as we do not need custom SSM endpoints etc.
insecureSkipSecretsManager: true
---
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: K0sControlPlane
metadata:
name: aws-test
spec:
replicas: 1
version: v1.34.2+k0s.0
updateStrategy: Recreate
k0sConfigSpec:
args:
- --enable-worker
k0s:
apiVersion: k0s.k0sproject.io/v1beta1
kind: ClusterConfig
metadata:
name: k0s
spec:
api:
extraArgs:
anonymous-auth: "true"
telemetry:
enabled: false
network:
provider: calico # Enable Calico networking
machineTemplate:
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSMachineTemplate
name: k0s-aws-test-mt-cp
namespace: default
---
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSCluster
metadata:
name: k0s-aws-test
namespace: default
spec:
region: eu-north-1
sshKeyName: <your-ssh-key-name>
controlPlaneLoadBalancer:
healthCheckProtocol: TCP
network:
additionalControlPlaneIngressRules:
- description: "k0s controller join API"
protocol: tcp
fromPort: 9443
toPort: 9443
---
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
name: k0s-aws-test-md
namespace: default
spec:
clusterName: aws-test-cluster
replicas: 1
selector:
matchLabels:
cluster.x-k8s.io/cluster-name: aws-test-cluster
pool: worker-pool-1
template:
metadata:
labels:
cluster.x-k8s.io/cluster-name: aws-test-cluster
pool: worker-pool-1
spec:
clusterName: aws-test-cluster
bootstrap:
configRef:
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: K0sWorkerConfigTemplate
name: k0s-aws-test-machine-config
infrastructureRef:
apiVersion: infrastructure.cluster.x-k8s.io/v1beta2
kind: AWSMachineTemplate
name: k0s-aws-test-mt-worker
---
apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: K0sWorkerConfigTemplate
metadata:
name: k0s-aws-test-machine-config
spec:
template:
spec:
version: v1.34.2+k0s.0
provisioner:
platform: windows
type: powershell-xml