Skip to content

GKE Windows Node Pool Creation & Mental Model

Vì Sao Quan Trọng

Windows Server containers trên GKE là niche nhưng không thể tránh với enterprise chạy .NET Framework legacy hoặc dependency Windows-only (COM, IIS, MSMQ). GKE cho phép mix Linux và Windows worker nodes trong cùng một cluster, nhưng đây không phải "thêm một node pool bình thường" — có những constraint kiến trúc riêng biệt mà nếu bỏ qua sẽ dẫn tới cluster không schedule được pod, hoặc image không pull được.

Mental model cốt lõi cần nắm:

  • Control plane luôn luôn là Linux. GKE không có "Windows control plane". API server, etcd, scheduler — tất cả chạy trên Linux VM do Google quản lý. Windows chỉ tồn tại ở worker node layer.
  • Windows node pool là một resource riêng biệt, tách khỏi Linux node pool, với image type, machine type, và disk size constraint khác.
  • Một cluster có thể có nhiều OS song song — Linux node pool cho phần lớn workload, Windows node pool cho phần cần Windows API surface.

Kiến Trúc: Mixed-OS Cluster

GKE Cluster
├── Control Plane (Linux, Google-managed) — luôn luôn

├── Node Pool "linux-default" (Linux, containerd)
│   ├── Node 1 (Ubuntu/COS)
│   └── Node 2 (Ubuntu/COS)

└── Node Pool "windows-workers" (Windows Server, containerd)
    ├── Node 1 (Windows Server 2022 LTSC Core)
    └── Node 2 (Windows Server 2022 LTSC Core)

Điểm quan trọng: kubelet, kube-proxy, và container runtime chạy native trên Windows ở Windows node — không phải chạy trong VM lồng Linux. GKE build image Windows Server riêng (LTSC hoặc SAC channel) có sẵn containerd, kubelet.exe, và các Windows-specific component đã đóng gói.

LTSC vs SAC: Lựa Chọn Channel

ChannelChu kỳ releaseSupport lifecycleKhi nào dùng
LTSC (Long-Term Servicing Channel)~3 năm/versionDài hạn (nhiều năm)Production, stability ưu tiên
SAC (Semi-Annual Channel)2 lần/nămNgắn (18 tháng)Cần feature mới nhất, container-optimized workload

Quan trọng: channel của node image phải tương thích với channel của base image container app dùng — mismatch giữa host OS build và container base image build là nguồn lỗi phổ biến nhất (chi tiết ở bài image registry).

Constraint Khi Tạo Windows Node Pool

1. Container Runtime: Containerd Bắt Buộc

Windows node pool trên GKE hiện tại chỉ hỗ trợ containerd làm runtime — image type dạng Docker-based (legacy) đã bị deprecate. Điều này quan trọng vì:

  • containerd trên Windows dùng HCS (Host Compute Service) shim khác biệt so với Linux runc shim
  • Một số Docker-specific behavior (ví dụ: certain networking flag) không map 1:1 sang containerd

2. VPC-Native Cluster Là Yêu Cầu

Windows node pool yêu cầu cluster dùng VPC-native (alias IP ranges), không hỗ trợ routes-based (legacy) networking. Lý do: Windows CNI plugin (win-bridge/win-overlay) cần alias IP range để assign Pod IP trực tiếp từ VPC subnet, tương tự cách Linux node hoạt động với Dataplane V1 VPC-native mode.

3. Machine Type & Resource Floor

Windows Server có baseline resource overhead cao hơn Linux đáng kể (OS services, .NET runtime nếu dùng, GUI-less nhưng vẫn nhiều subsystem chạy nền). Vì vậy:

  • Không nên dùng machine type nhỏ (ví dụ e2-small) cho Windows node — OS overhead sẽ chiếm phần lớn resource, để lại rất ít cho pod
  • Khuyến nghị bắt đầu từ machine type tương đương 4 vCPU / 16GB trở lên cho production workload thực tế (chi tiết sizing ở bài resource requests)

4. Boot Disk Size

Windows Server image (kể cả bản Server Core, không GUI) nặng hơn Linux image (COS/Ubuntu) rất nhiều — thường gấp 5-10 lần. Boot disk quá nhỏ dẫn tới:

  • Node fail để pull node image ban đầu
  • Không đủ disk space để cache container image layers, gây ImagePullBackOff dù network hoạt động tốt

Nguyên tắc: luôn set boot disk size rộng rãi hơn mức bạn nghĩ cần — image OS + vài container image lớn (servercore-based) có thể dễ dàng chiếm hàng chục GB.

OS Labels, NodeSelector, và Taints

GKE tự động gắn label phân biệt OS lên mọi node — đây là built-in Kubernetes label, không phải GKE-specific:

yaml
# Labels tự động trên Windows node
kubernetes.io/os: windows
kubernetes.io/arch: amd64
node.kubernetes.io/windows-build: "10.0.20348"  # build number cụ thể

Vấn đề cần hiểu: nếu không có cơ chế nào ngăn chặn, scheduler có thể cố schedule pod Linux lên node Windows (và ngược lại) — dẫn tới pod stuck ở Pending hoặc crash ngay khi container runtime cố chạy binary sai OS.

Pattern Bắt Buộc: nodeSelector + Toleration

Mọi Pod spec chạy trên Windows phải khai báo nodeSelector rõ ràng:

yaml
apiVersion: v1
kind: Pod
spec:
  nodeSelector:
    kubernetes.io/os: windows
  tolerations:
  - key: "os"
    operator: "Equal"
    value: "windows"
    effect: "NoSchedule"
  containers:
  - name: my-windows-app
    image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022

Nhiều tổ chức tự thêm custom taint lên Windows node pool khi provision (ví dụ os=windows:NoSchedule) để bảo đảm double-safety — không chỉ dựa vào nodeSelector từ phía application team (dễ bị quên).

Nguyên tắc thiết kế: treat Windows node pool như một "khu vực đặc biệt" — mọi Deployment/DaemonSet target Windows phải qua review để đảm bảo nodeSelector + toleration được khai báo đúng, tránh việc pod Linux vô tình lọt vào node pool đắt đỏ và khan hiếm này.

Version Skew & Lifecycle

Windows node pool trên GKE có xu hướng theo sau Linux về việc hỗ trợ phiên bản Kubernetes mới nhất — features GA trên Linux có thể ở trạng thái preview hoặc chưa available trên Windows trong vài minor version. Khi lập kế hoạch nâng cấp cluster:

  • Kiểm tra release notes GKE riêng cho phần Windows trước khi nâng cấp minor version
  • Windows node pool upgrade (surge upgrade) thường chậm hơn Linux đáng kể vì thời gian boot + pull image lớn hơn — cần tính vào maintenance window

Những Gì Không Thể Làm

  • Không thể chạy Windows container trên Linux node hoặc ngược lại — không có cross-OS emulation ở container runtime level
  • Không thể dùng Hyper-V isolation trên GKE — chỉ hỗ trợ process isolation, nghĩa là container OS build phải tương thích chặt với host OS build (xem bài image registry)
  • Không thể giảm control plane xuống Windows — architecture này không tồn tại trên GKE (và thực tế không tồn tại trên bất kỳ managed Kubernetes nào hiện nay)

Tham Khảo