WSL2 + Kubernetes: налаштування, яке не перегріває ваш ноутбук

Було корисно?

Ви встановили Kubernetes локально, бо хотіли швидкості: швидко ітерації, тестувати чарти, налагоджувати контролери, можливо запускати невеликий стек платформи.
Потім вентилятори переходять у режим турбіни, SSD починає навантажуватися, і ваш «швидкий дев-кластер» перетворюється на причину, через яку Slack питає, чи ви онлайн.

WSL2 може бути чудовим місцем для запуску Kubernetes — якщо ставитися до нього як до реальної віртуальної машини з обмеженнями диска та пам’яті, а не як до чарівної папки Linux.
Це практичне налаштування, яке уникає класичних режимів відмов: неконтрольованого використання ОЗУ, повільного вводу/виводу, дивних проблем з DNS і «чому kubectl зависає?».

Що ви насправді будуєте (і чому це перегріває ноутбуки)

На Windows із WSL2 «запуск Kubernetes» рідко означає лише «запуск Kubernetes».
Це стек вкладених абстракцій, кожна з яких має власні уявлення про планування CPU, звільнення пам’яті, семантику файлової системи та мережу.
Коли будь-який шар помиляється, вашим ноутбуком розплачуються.

Типове налаштування Kubernetes на WSL2 виглядає так:

  • Операційна система Windows (хост)
  • VM WSL2 (легка Hyper-V VM з віртуальним диском)
  • Дистрибутив Linux userland (Ubuntu, Debian тощо)
  • Рuntime контейнерів (Docker Engine, containerd або стек nerdctl)
  • Дистрибуція Kubernetes (kind, k3d, minikube, microk8s або інтегрований кластер Docker Desktop)
  • Ваші робочі навантаження: бази даних, оператори, конвеєри збірки, ingress-контролери, service mesh — тобто «малий продакшн»

Перегрів зазвичай походить з одного з трьох місць:

  1. Пам’ять: WSL2 охоче кешує сторінки і не завжди швидко їх віддає. Kubernetes розподіляє поди, поки вузол «здається» нормальним, аж поки це перестає бути правдою.
  2. Зберігання: перетин кордону між Windows і Linux-файловими системами може перетворити нормальний I/O у повільний інцидент. Бази даних підсилюють проблему через fsync і дрібні випадкові записи.
  3. Мережа/DNS: kube-dns, Windows DNS, віртуальні мережеві інтерфейси WSL2 та клієнти VPN утворюють трикутник суму.

Мета — не «зробити блискавично швидко в бенчмарках». Мета — «зробити передбачувано достатньо швидко»,
і що важливіше, зробити режими відмов очевидними.
Надійність у деві важлива, бо дев — це місце, де ви вирішуєте, про що потім пошкодуєте у проді.

Кілька фактів і історичний контекст (щоб дивні речі були зрозумілі)

Це коротко з наголосом на потрібному. Це оновлення ментальної моделі, що заощаджує години пошуку примар.

  1. WSL1 був трансляцією системних викликів; WSL2 — справжнє ядро Linux у VM. Саме тому WSL2 може правильно запускати Kubernetes, але й поводиться як VM з власними дисковими й пам’ятними політиками.
  2. WSL2 за замовчуванням зберігає файли Linux у віртуальному диску (VHDX). Цей диск може швидко рости і не завжди зменшується, поки ви явно не компактнете його.
  3. Доступ до файлів Linux з Windows — не те саме, що доступ до Windows з Linux. Характеристики продуктивності дуже відрізняються, і повільний шлях вдарить по базах даних і збірках образів.
  4. Kubernetes не був створений для ноутбуків. Він про кластери, де «вузол — це корівна VM», і можна спалювати CPU на циклах реконциляції, не чутливо до вентиляторів.
  5. kind запускає Kubernetes у Docker-контейнерах. Це чудово для відтворюваності, але додає ще один шар, де зберігання і мережа можуть стати «креативними».
  6. k3s (і відповідно k3d) створено як легковаговий варіант. Він використовує SQLite за замовчуванням, що підходить локально, але все одно навантажує диск при великій кількості контролерів.
  7. cgroups v2 змінив поведінку ізоляції ресурсів. Багато розмов «чому ігнорується ліміт пам’яті?» насправді про режим cgroup.
  8. DNS — топова причина відмов у локальних кластерах. Не тому, що DNS складний, а тому, що корпоративні VPN і split-horizon DNS можуть непомітно все перекреслити.
  9. Збірка образів карає за метадані файлової системи. Різниця між швидкою файловою системою і «переправленою» стає очевидною при багатоступеневих збірках з тисячами дрібних файлів.

Виберіть локальний Kubernetes: kind vs k3d vs minikube (і що я рекомендую)

Моя стандартна рекомендація: kind у WSL2 з обмеженнями

Для більшості розробників і SRE, що працюють з платформою, kind дає відтворюваність, швидкість і чисте знищення середовища.
Кластер — «просто контейнери», і ви можете зафіксувати версію Kubernetes легко.
Ключ — обмежити ресурси WSL2 і тримати робочі навантаження на файловій системі Linux.

Коли віддати перевагу k3d (k3s у Docker)

Якщо ваша ціль — «запустити практичний дев-платформений стек з мінімальними накладними витратами», k3d відмінний вибір.
k3s обрізає зайве: менше компонентів, менше пам’яті. Він більш поблажливий на менших ноутбуках.
Також він ближчий до того, що часто використовують на edge-пристроях, що корисно, якщо ви деплоїте в обмежені середовища.

Коли використовувати minikube

minikube підходить, коли ви хочете «один інструмент для багатьох драйверів».
Але на WSL2 minikube може загнати вас у плутанину драйверів: Docker driver, KVM (зазвичай ні), Hyper-V (по стороні Windows),
і тоді ви почнете дебажити драйвер більше, ніж кластер.
Якщо ви вже комфортно користуєтеся Docker всередині WSL2, Docker driver minikube придатний.

Чого уникати (якщо немає вагомої причини)

  • Запускати важкі stateful навантаження на /mnt/c і потім звинувачувати Kubernetes у повільності. Це не Kubernetes; це межа файлових систем, яка просить припинити.
  • Перевиділяти CPU та RAM «бо це локально». WSL2 це прийме, Windows відповість, а ваш браузер програє.
  • Намагатися робити «як у проді» з усім увімкненим. Service mesh + розподілене трасування + три оператори + база даних + CI — це не дев-кластер; це хобі-центр обробки даних.

Короткий жарт, як обіцяно: Kubernetes схожий на кухню з 30 шефами — ніхто не готує швидше, але всі роблять звіт.

Базові положення WSL2: ліміти, ядро та речі, про які Windows не скаже

Встановіть обмеження WSL2 або прийміть хаос

За замовчуванням WSL2 буде масштабувати використання пам’яті до значної частини вашого системного ОЗП.
Це не злий намір. Це Linux робить свої Linux-справи — використовує пам’ять під кеш.
Проблема в тому, що Windows не завжди повертає цю пам’ять у спосіб, який відчувається ввічливо.

Покладіть файл .wslconfig у ваш профіль користувача Windows (на стороні Windows).
Потрібен верхній ліміт пам’яті та CPU, і бажано swap, який існує, але не замінює RAM.

cr0x@server:~$ cat /mnt/c/Users/$WINUSER/.wslconfig
[wsl2]
memory=8GB
processors=4
swap=4GB
localhostForwarding=true

Рішення: Якщо у вас 16GB RAM загалом, 8GB для WSL2 зазвичай розумно.
Якщо 32GB — можна 12–16GB. Більше зазвичай приховує витоки та погані межі подів.

Поведінка звільнення пам’яті WSL2: використайте наявні інструменти

У WSL2 поліпшили звільнення пам’яті, але іноді вона все ще прилипає після важких збірок або зміни кластерів.
Якщо потрібно швидко повернути пам’ять, вимкнення WSL — грубий, але дієвий інструмент.

cr0x@server:~$ wsl.exe --shutdown
...output...

Що означає вивід: Відсутність виводу — нормально. Це зупиняє всі дистрибутиви WSL і VM WSL2.
Рішення: Використовуйте це, коли Windows стискає пам’ять і потрібно повернути її негайно, а не під час налагодження проблем у кластері.

Використовуйте systemd у WSL2 (якщо доступно) і будьте явними

Сучасний WSL підтримує systemd. Це робить запуск Docker/containerd і інструментів Kubernetes менш незграбним.
Перевірте, чи увімкнено systemd.

cr0x@server:~$ ps -p 1 -o comm=
systemd

Що означає вивід: Якщо PID 1 — systemd, ви можете використовувати звичайне управління сервісами.
Якщо інше (наприклад, init), доведеться керувати демонами по-іншому.
Рішення: Віддавайте перевагу WSL з systemd для стабільності і менше «чому це не запустилося?» загадок.

Зберігання в WSL2: різниця між «працює» і «не ненавидить вас»

Правило №1: тримайте дані Kubernetes у файловій системі Linux

Розміщуйте стан кластера, образи контейнерів і дані персистентних томів у файловій системі дистрибутива Linux (наприклад, /home, /var).
Уникайте розміщення інтенсивних записів на /mnt/c.
Шар інтеграції може підходити для редагування коду, але це пастка для баз даних і всього, що інтенсивно викликає fsync.

Правило №2: зрозумійте, куди йдуть байти

Docker/containerd зберігає образи й writable-леєри десь під /var/lib.
kind і k3d додають власні шари.
Якщо ви багато будуєте образів або запускаєте CI-подібні навантаження, ваш VHDX ростиме. Він може не зменшуватись.
Це не моральний дефект; так працюють віртуальні диски.

Правило №3: вимірюйте I/O нудним способом

Вам не потрібні спеціальні інструменти зберігання, щоб помітити великі проблеми. Потрібні два порівняння:
продуктивність файлової системи Linux і продуктивність Windows-монту.
Якщо одна швидкість у 10 разів менша, не «налаштовуйте Kubernetes». Перенесіть навантаження.

cr0x@server:~$ dd if=/dev/zero of=/home/cr0x/io-test.bin bs=1M count=512 conv=fdatasync
512+0 records in
512+0 records out
536870912 bytes (537 MB, 512 MiB) copied, 1.24 s, 433 MB/s

Що означає вивід: Це грубий послідовний запис з флашем. Сотні MB/s очікувані на SSD.
Рішення: Якщо це однозначні MB/s, ваша VM під I/O тиском або диск має проблеми. Виправляйте це перед Kubernetes.

cr0x@server:~$ dd if=/dev/zero of=/mnt/c/Users/$WINUSER/io-test.bin bs=1M count=256 conv=fdatasync
256+0 records in
256+0 records out
268435456 bytes (268 MB, 256 MiB) copied, 12.8 s, 21.0 MB/s

Що означає вивід: Якщо ви бачите таке падіння, це шлях інтеграції.
Рішення: Не розміщуйте /var/lib/docker, /var/lib/containerd або каталоги PV на /mnt/c.
Тримайте там код, якщо потрібно, але кеші збірки та бази даних — у Linux-просторі.

Зростання VHDX: компактування — це обслуговування, а не одноразовий фікс

Якщо ваш віртуальний диск WSL2 виріс через збірки образів і churn, ви можете його компактнути — але це не автоматично.
Спочатку очистіть всередині Linux: видаліть невикористані образи, prune томи, очистіть кеші.
Потім компактніть зі сторони Windows. Конкретні кроки відрізняються в залежності від збірки Windows і інструментів, але принцип постійний:
видаліть невикористані блоки в гості, потім скажіть хосту компактнути.

Суха правда: локальні кластери створюють дані. Вони рідко їх видаляють так агресивно, як ви думаєте.
Якщо ставитись до дев-середовища як до продакшену, треба планувати обслуговування як у проді. Ось така угода.

Мережа: NodePorts, ingress, DNS і пастка localhost

Localhost — це не філософія; це рішення маршрутизації

У WSL2 «localhost» може означати localhost Windows або localhost WSL залежно від того, як запущено процес.
З localhostForwarding=true WSL може форвардити порти на Windows, але це не магія для всіх шаблонів трафіку.

Якщо ви запускаєте kind у WSL2 і відкриваєте сервіс через NodePort, ви часто будете звертатися до нього з Windows через форвард порти
або звертаючись до IP VM WSL. Обидва способи можуть працювати. Важливо бути послідовним і документувати, який метод використовує ваша команда.

DNS: мовчазний вбивця kubectl

Багато скарг «Kubernetes повільний» насправді — це таймаути DNS.
kubectl виглядає так, ніби завис, але чекає на виклики API-сервера, які ніяк не розв’язуються.
VPN-клієнти ускладнюють це, впроваджуючи резолвери або змушуючи split DNS.

Ваше завдання — відокремити «API-сервер повільний» від «розв’язування імен повільне» менш ніж за п’ять хвилин.
Потім можна сперечатися з корпоративним VPN.

Практичні завдання (команди, виводи та рішення)

Це реальні задачі, які ви виконуватимете при налаштуванні та під час налагодження.
Кожна містить, що означає вивід і яке рішення з нього випливає.
Робіть їх по черзі при створенні нового середовища; вибірково — коли все горить.

Завдання 1: Підтвердіть, що ви на WSL2 (не WSL1)

cr0x@server:~$ wsl.exe -l -v
  NAME            STATE           VERSION
* Ubuntu-22.04    Running         2

Що означає вивід: VERSION 2 означає справжню Linux-VM. VERSION 1 — трансляцію системних викликів.
Рішення: Якщо у вас VERSION 1, зупиніться і конвертуйте. Kubernetes потребує реальної поведінки ядра.

Завдання 2: Перевірте ядро та режим cgroup

cr0x@server:~$ uname -r
5.15.146.1-microsoft-standard-WSL2
cr0x@server:~$ mount | grep cgroup2
cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime)

Що означає вивід: cgroup2 змонтований означає єдину ієрархію.
Рішення: Якщо ваше ПО очікує cgroup v1 (старі конфігурації Docker, деякі агенти моніторингу), готуйтеся до сюрпризів.

Завдання 3: Підтвердьте systemd і контроль сервісів

cr0x@server:~$ systemctl is-system-running
running

Що означає вивід: systemd активний і стабільний.
Рішення: Якщо ви бачите degraded, перевірте неуспішні одиниці перед тим, як звинувачувати Kubernetes у «випадкових» проблемах.

Завдання 4: Підтвердьте здоров’я runtime контейнерів (приклад Docker)

cr0x@server:~$ docker info --format '{{.ServerVersion}} {{.CgroupVersion}}'
24.0.7 2

Що означає вивід: Docker доступний і повідомляє версію cgroup.
Рішення: Якщо ця команда повільна або зависає, виправте Docker перед тим, як чіпати kind/k3d.

Завдання 5: Швидко виміряйте тиск пам’яті

cr0x@server:~$ free -h
               total        used        free      shared  buff/cache   available
Mem:           7.7Gi       5.9Gi       310Mi       160Mi       1.5Gi       1.3Gi
Swap:          4.0Gi       1.2Gi       2.8Gi

Що означає вивід: available важливіший за free. Використання swap свідчить про тиск.
Рішення: Якщо available менше ~1Gi і swap росте, зменшіть кластер, знизьте ліміти або підвищте пам’ять WSL.

Завдання 6: Перевірте заповненість диска там, де це важливо

cr0x@server:~$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb       250G  180G   71G  72% /

Що означає вивід: Це файловa система вашого дистрибутива, підкріплена VHDX.
Рішення: Вище ~85% заповнення продуктивність і поведінка компактування погіршуються. Обріжте образи і старі PV.

Завдання 7: Встановіть і створіть кластер kind з розумними налаштуваннями

cr0x@server:~$ kind create cluster --name dev --image kindest/node:v1.29.2
Creating cluster "dev" ...
 ✓ Ensuring node image (kindest/node:v1.29.2) 🖼
 ✓ Preparing nodes 📦
 ✓ Writing configuration 📜
 ✓ Starting control-plane 🕹️
 ✓ Installing CNI 🔌
 ✓ Installing StorageClass 💾
Set kubectl context to "kind-dev"
You can now use your cluster with:

kubectl cluster-info --context kind-dev

Що означає вивід: Кластер створено, контекст встановлено. StorageClass інстальовано (зазвичай standard).
Рішення: Якщо встановлення CNI зависає, підозрюйте DNS/proxy/VPN або проблеми з підтягуванням образів — не повторюйте спроби бездумно.

Завдання 8: Перевірте живучість кластера та здоров’я компонентів

cr0x@server:~$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:40685
CoreDNS is running at https://127.0.0.1:40685/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
cr0x@server:~$ kubectl get nodes -o wide
NAME                STATUS   ROLES           AGE   VERSION   INTERNAL-IP   OS-IMAGE
dev-control-plane   Ready    control-plane   2m    v1.29.2   172.18.0.2    Debian GNU/Linux 12 (bookworm)

Що означає вивід: API-сервер доступний, вузол Ready, внутрішня IP-адреса призначена.
Рішення: Якщо вузол NotReady — одразу дивіться kubectl describe node і логи CNI — не перевстановлюйте все поки що.

Завдання 9: Знайдіть справжніх споживачів ресурсів (вузли + поди)

cr0x@server:~$ kubectl top nodes
NAME                CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
dev-control-plane   620m         15%    2240Mi          56%

Що означає вивід: metrics-server працює (kind часто включає його через addons або ви його встановили).
Рішення: Якщо пам’ять висока в режимі простою — перевірте нав’язливі контролери, витоки dev-зборок або завислий лог-шифтер.

Завдання 10: Перевірка DNS у кластері (дешевий smoke test)

cr0x@server:~$ kubectl run -it --rm dns-test --image=busybox:1.36 --restart=Never -- nslookup kubernetes.default.svc.cluster.local
Server:    10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes.default.svc.cluster.local
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local
pod "dns-test" deleted

Що означає вивід: CoreDNS відповідає, service discovery працює.
Рішення: Якщо це таймаутиться, виправте DNS перед тим, як налагоджувати додаток. Додаток невинний, поки не доведено інше.

Завдання 11: Підтвердіть, чи повільний kubectl через мережу або API-латентність

cr0x@server:~$ time kubectl get pods -A
NAMESPACE     NAME                                        READY   STATUS    RESTARTS   AGE
kube-system   coredns-76f75df574-2lq9r                    1/1     Running   0          4m
kube-system   coredns-76f75df574-9x2ns                    1/1     Running   0          4m
kube-system   etcd-dev-control-plane                      1/1     Running   0          4m
kube-system   kindnet-4cdbf                               1/1     Running   0          4m
kube-system   kube-apiserver-dev-control-plane            1/1     Running   0          4m
kube-system   kube-controller-manager-dev-control-plane   1/1     Running   0          4m
kube-system   kube-proxy-4xw26                            1/1     Running   0          4m
kube-system   kube-scheduler-dev-control-plane            1/1     Running   0          4m

real    0m0.312s
user    0m0.127s
sys     0m0.046s

Що означає вивід: 300ms — нормально для локального. Кілька секунд підозрілі — DNS, плутанина контекстів kubeconfig або проблеми API-сервера.
Рішення: Якщо це повільно, запустіть kubectl get --raw /readyz?verbose далі.

Завдання 12: Перевірте готовність API-сервера для реального блокера

cr0x@server:~$ kubectl get --raw='/readyz?verbose'
[+]ping ok
[+]log ok
[+]etcd ok
[+]informer-sync ok
[+]poststarthook/start-apiserver-admission-initializer ok
[+]poststarthook/start-apiextensions-informers ok
[+]poststarthook/start-apiextensions-controllers ok
readyz check passed

Що означає вивід: Якщо etcd або informer sync повільні/відмовляють, контрольна площина — вузьке місце.
Рішення: Повільний etcd часто означає затримку зберігання. Це натяк перевірити диск і уникати крос-файлової I/O.

Завдання 13: Знайдіть под, що «спалює» ваш ноутбук (CPU/пам’ять)

cr0x@server:~$ kubectl top pods -A --sort-by=memory | tail -n 10
default       api-7b7c7d8f6c-9bq5m             1/1     980Mi
observability prometheus-0                      2/2     1210Mi
observability loki-0                            1/1     1530Mi

Що означає вивід: Ви бачите топ-споживачів.
Рішення: Якщо ваш дев-кластер включає Prometheus/Loki за замовчуванням, ви щойно знайшли причину «чому гаряче?».
Зменшіть масштаб, скоротіть ретенцію або використайте легші інструменти локально.

Завдання 14: Перевірте використання диска runtime контейнерів (Docker)

cr0x@server:~$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          42        12        18.4GB    12.1GB (65%)
Containers      19        6         1.2GB     720MB (60%)
Local Volumes   27        9         9.8GB     6.3GB (64%)
Build Cache     124       0         22.6GB    22.6GB

Що означає вивід: Build cache часто — мовчазний пожирач диска.
Рішення: Якщо reclaimable велике, чистіть свідомо. Не чекайте, поки VHDX досягне 95% і все сповільниться.

Завдання 15: Працюйте з prune обережно (і прийміть компроміс)

cr0x@server:~$ docker builder prune --all --force
Deleted build cache objects:
v8m3q8qgk7yq4o0l5u3f7s1m2
...
Total reclaimed space: 22.6GB

Що означає вивід: Ви звільнили простір, за ціною повторної збірки шарів пізніше.
Рішення: У деві диск і стабільність важливіші, ніж зекономлені 90 секунд на наступній збірці.

Завдання 16: Перевірте, чи випадково не запускаєте навантаження на /mnt/c

cr0x@server:~$ kubectl get pv -A -o wide
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                      STORAGECLASS   REASON   AGE   VOLUMEMODE
pvc-1d2c7f7e-2f5d-4c0d-9a3a-2c6f9d8b1a7c   10Gi       RWO            Delete           Bound    default/db-data           standard                8m    Filesystem

Що означає вивід: Це не показує шлях хоста. У kind провайдер local-path і поведінка provisioning відрізняються.
Рішення: Розгляньте storage class і поведінку provisioner; якщо воно прив’язується до hostPath на Windows-монту, виправте негайно.

Завдання 17: Діагностика kubelet/container через логи вузла (контейнер kind node)

cr0x@server:~$ docker ps --format 'table {{.Names}}\t{{.Status}}' | grep dev-control-plane
dev-control-plane   Up 6 minutes
cr0x@server:~$ docker logs dev-control-plane | tail -n 20
I0205 09:10:12.123456       1 server.go:472] "Kubelet version" kubeletVersion="v1.29.2"
I0205 09:10:15.234567       1 kubelet.go:2050] "Skipping pod synchronization" error="PLEG is not healthy"
...

Що означає вивід: Якщо PLEG нездоровий, kubelet бореться — часто через I/O диска або повільний runtime контейнерів.
Рішення: Перевірте затримки диска, здоров’я runtime і кількість логів.

Завдання 18: Швидка перевірка «штормів логів» (вони можуть бути найгарячішим навантаженням)

cr0x@server:~$ kubectl logs -n kube-system deploy/coredns --tail=20
.:53
[INFO] plugin/reload: Running configuration SHA512 = 7a9b...
[INFO] 10.244.0.1:52044 - 46483 "A IN kubernetes.default.svc.cluster.local. udp 62 false 512" NOERROR qr,aa,rd 114 0.000131268s

Що означає вивід: Деякі DNS-логи — нормальні. Тисячі на секунду — ні.
Рішення: Якщо логи «гарячі», знизьте рівень логування, виправте цикл повторних спроб клієнта або ви заплатите CPU і дисковими записами.

Три корпоративні міні-історії з поля бою

Міні-історія 1: Інцидент через неправильне припущення

Команда, з якою я працював, стандартизувала WSL2 для дев-кластерів, бо це «майже Linux».
Вони тримали репозиторій на файловій системі Windows для зручності IDE, а потім монтували його в контейнери для збірок і тестів.
Здавалося, усе було добре для невеликих сервісів. Потім платформа додала локальний Postgres, контролер і тестовий набір, що запускав міграції при кожному запуску.

Симптом був дивний: міграції іноді займали 30 секунд, іноді 10 хвилин.
Люди звинувачували «накладні витрати Kubernetes» і «той оператор».
Один інженер намагався виправити це, підвищивши ліміти CPU. Стало гірше — більше CPU тільки прискорило досягнення дискового вузького місця.

Неправильне припущення було простим: вони вважали /mnt/c «ще однією файловою системою».
Це не так. Це межа з іншою поведінкою кешування, іншою продуктивністю метаданих і іншою семантикою скидання.
Їхній том бази даних і кеші збірки були на повільному шляху.

Виправлення було непривабливим: перемістити базу даних і кеші збірки у файлову систему Linux, і тримати вихідний код на Windows лише якщо потрібно.
Вони також додали preflight-скрипт, що відмовлявся запускати стек, якщо виявляв PV, спрямовані на /mnt/c.
Продуктивність стабілізувалась миттєво. Ніхто не святкував — отже, це було правильне рішення.

Міні-історія 2: Оптимізація, що обернулася проти

Інша компанія хотіла «швидші локальні кластери», тому заздалегідь підвантажила все: стек спостереження, ingress, cert-manager і кілька операторів.
Ідея була благородна: скоротити час онбордингу, гарантувати однакову базу для всіх, уникнути «працює на моєму ноутбуці».
Вони навіть створили внутрішній скрипт, що створював кластер і встановлював усі чарти за один раз.

Потім почалися тікети. Ноутбуки нагрівалися на нарадах. Тривалість роботи акумулятора впала.
kubectl іноді лагав на кілька секунд. Розробники почали відключати компоненти «тимчасово», що перетворилося на постійний дріфт.
Команда платформи відповіла, підвищивши дефолтні ліміти ресурсів і кількість реплік, бо «парність з продом».

Зворотний ефект виник через фонову роботу контролерів і їхню активність.
Prometheus scraping, Loki ingest, cert-manager reconciliation і цикли операторів — це не безкоштовно.
У реальному кластері цю вартість амортизує кілька серверів. На ноутбуку ви відчуваєте це щоразу, коли вентилятор розкручується.

Виправлення — визначити два профілі: core (ingress + DNS + storage + metrics-server) і full (важкий стек).
Core — за замовчуванням; full — за бажанням для налагодження.
Вони також знизили інтервали скрейпу і ретенцію в локальному режимі. Іронія: онбординг прискорився, бо люди перестали боротись із середовищем.

Міні-історія 3: Нудна, але правильна практика, що врятувала

Регульована підприємницька організація (та, що любить таблиці) мала дивно гладкий досвід WSL2 Kubernetes.
Секрет не в досконалому стеку інструментів. Секрет — дисципліна: фіксація версій, відтворюване створення кластера і агресивне прибирання.
Кожен розробник мав той самий образ kind node, ті самі версії чартів і однакові дефолтні ліміти ресурсів.

Вони також мали тижневу рутинну процедуру: prune невикористані образи, видаляти невживані неймспейси і компактувати дев-середовище при потребі.
Це було заплановано, задокументовано і нудно.
Розробники спочатку скаржилися — ніхто не любить «день обслуговування» для ноутбука.

Потім стався день, коли оновлення Windows змінило щось тонке в мережі.
Піворганізації почали отримувати переривчасті DNS-збої.
Команди з різними середовищами мали хаос: різні версії CNI, випадкові kubeconfig, непослідовні локальні DNS-переопреділення.
Дисципліновані команди швидко відтворили проблему і порівняли «яблука з яблуками».

Вони локалізували проблему до поведінки резолвера під VPN, накотили стандартизоване рішення і повернулися до роботи.
Нудна практика врятувала день: послідовні версії і базові налаштування роблять відлагодження кінцевим.

Швидкий план діагностики: що перевіряти спочатку, потім, далі

Коли ваш ноутбук плавиться або кластер «повільний», часу милуватися архітектурою немає.
Потрібен детермінований шлях до вузького місця.

Перш за все: чи зазнає хост (Windows + WSL2) навантаження по ресурсам?

  1. Перевірте використання пам’яті і swap WSL2: free -h. Якщо available низький і swap росте — ви обмежені пам’яттю.
  2. Перевірте заповненість диска: df -h /. Якщо майже повний — усе стає повільнішим і вразливішим.
  3. Швидка перевірка I/O: dd ... conv=fdatasync на Linux FS vs /mnt/c. Якщо Linux FS теж повільний — проблема на рівні системи.

Друге: чи здорова контрольна площина Kubernetes або вона застрягла?

  1. API readyz: kubectl get --raw='/readyz?verbose'. Якщо перевірки etcd повільні — підозрюйте затримку зберігання.
  2. Стан вузлів: kubectl get nodes і kubectl describe node. Якщо NotReady — дивіться CNI і симптоми kubelet.
  3. Smoke test CoreDNS: запустіть busybox nslookup. Якщо DNS зламаний — зупиніть притягування додатка у відповідальність.

Третє: яке навантаження справді «спалює» CPU/пам’ять/I/O?

  1. Топ-споживачі: kubectl top pods -A --sort-by=memory і --sort-by=cpu.
  2. Шторми логів: перевірте логи підозрюваних подів. Висока швидкість запису = тиск на I/O = загальне уповільнення.
  3. Частота збірок/образів: docker system df і при потребі prune build cache, якщо він роздувся.

Парафраз ідеї Вернера Фогельса: «Усе ламається, постійно». Будуйте локальне середовище так, щоб відмова була швидко діагностованою, а не загадковою.

Поширені помилки: симптом → корінна причина → виправлення

1) Симптом: вентилятори ноутбука спрацьовують, коли кластер «в режимі простою»

Корінна причина: фонові контролери (стек спостереження, оператори) постійно роблять реконциляцію; або под у crash loop записує логи.

Виправлення: kubectl top pods -A, знайдіть хижака; зменшіть масштаб; скоротіть ретенцію/інтервали скрейпу; виправте crash loop; встановіть розумні requests/limits.

2) Симптом: kubectl іноді виконується 5–30 секунд

Корінна причина: таймаути DNS або втручання VPN-резолвера; іноді kubeconfig вказує на мертвий контекст.

Виправлення: запустіть time kubectl get pods -A, потім kubectl get --raw='/readyz?verbose'. Якщо readyz у порядку, перевірте DNS у кластері. Якщо DNS ламається — вирішіть resolv.conf/policy split DNS або працюйте без VPN для локальних задач.

3) Симптом: Postgres/MySQL у кластері надто повільні

Корінна причина: PV або bind mounts на /mnt/c або іншому повільному кордоні; fsync-інтенсивні навантаження підсилюють це.

Виправлення: тримайте дані PV у файловій системі Linux; використовуйте local-path provisioner, що пише в /var всередині WSL, а не на Windows-монти.

4) Симптом: WSL2 поглинає RAM і ніколи не віддає

Корінна причина: кеш сторінок Linux + поведінка звільнення WSL2; великі збірки і pull образів заповнюють кеш; не задано ліміт пам’яті.

Виправлення: встановіть обмеження у .wslconfig; перезапускайте WSL через wsl.exe --shutdown коли потрібно; зменшіть відбиток кластера і уникайте запуску всього одночасно.

5) Симптом: диск «таємниче» заповнюється

Корінна причина: шари образів контейнерів, build cache, залишкові PV дані і логи; VHDX росте; prune не виконувалися.

Виправлення: docker system df і docker builder prune --all; видаліть невикористані неймспейси/PV; слідкуйте за df -h.

6) Симптом: вузол стає NotReady; поди зависають у ContainerCreating

Корінна причина: CNI зламаний або kubelet/runtime контейнерів страждають через I/O; контейнер kind node нездоровий.

Виправлення: перевірте логи контейнера kind node; перевірте CNI-поди в kube-system; виправте дисковий тиск; відновіть кластер, якщо образ вузла пошкоджено.

7) Симптом: ingress працює з WSL, але не з Windows

Корінна причина: неправильні очікування форвардингу портів; брандмауер Windows/VPN; плутанина між IP WSL і localhost Windows.

Виправлення: оберіть один метод доступу (форвардинг localhost або IP WSL); задокументуйте його; відкрийте ingress з передбачуваним відображенням; перевірте curl з обох сторін.

8) Симптом: збірки всередині контейнерів повільніші за збірки на Windows

Корінна причина: дерево сорсів на Windows-монті; інтенсивні операції з метаданими через межу; антивірус Windows сканує шлях.

Виправлення: тримайте вихідник у файловій системі Linux для збірок; користуйтеся IDE через інтеграцію WSL; виключіть каталоги збірки з AV, якщо політика дозволяє.

Другий і останній короткий жарт: Якщо ваш дев-кластер потребує runbook — вітаю, ви побудували малий продакшен з гіршим фінансуванням.

Контрольні списки / покроковий план

План налаштування (зробіть це одного разу на ноутбук)

  1. Встановіть ліміти WSL2 у .wslconfig: обмежте пам’ять і CPU; увімкніть розумний swap.
  2. Увімкніть systemd у WSL (якщо підтримується) і стандартизуйте це в команді.
  3. Виберіть один runtime: Docker Engine у WSL2 підходить; уникайте змішування Docker Desktop + WSL Docker, якщо вам не до вподоби невизначеність.
  4. Виберіть один інструмент Kubernetes: kind (рекомендовано) або k3d. Виберіть і стандартизируйте скрипти створення кластера.
  5. Тримайте дані кластера в Linux FS: переконайтеся, що зберігання runtime і PV не на /mnt/c.
  6. Визначте профілі: «core» за замовчуванням; «full» — опційно. Ноутбук — не staging.
  7. Зафіксуйте версії: image версії kind node, версії чартів і критичних аддонів.

Щоденний робочий список (залишайтесь швидкими і адекватними)

  1. Перед важкою роботою: free -h і df -h /. Якщо низько — зробіть prune перш ніж починати.
  2. Після важкого дня збірок: docker system df. Якщо build cache величезний — prune.
  3. Коли щось здається повільним: спочатку тест DNS і перевірки /readyz, перш ніж щось міняти.
  4. Тримайте репозиторій там, де інструменти найшвидші: якщо збірки у Linux — робочу копію тримайте у Linux.

Щотижневий чеклист обслуговування (нудно, але дієво)

  1. Prune build cache: docker builder prune --all.
  2. Prune невикористані образи і контейнери: docker system prune (обережно: зрозумійте, що видаляється).
  3. Видаліть невикористані неймспейси і PV у дев-кластері.
  4. Пересоздайте кластер, якщо накопичився дріфт. Розрив і пересоздання — це функція.
  5. Поверніть пам’ять, якщо Windows прижимає: wsl.exe --shutdown.

Питання й відповіді

1) Чи використовувати Docker Desktop чи Docker Engine у WSL2?

Якщо ви хочете найпростішу інтеграцію з Windows і в компанії стандартизовано Docker Desktop — це нормально.
Якщо хочете менше рухомих частин і більш передбачувану поведінку Linux — використовуйте Docker Engine у WSL2.
Виберіть одне і дотримуйтеся; змішані налаштування породжують фольклор дебагу.

2) Чому зберігання даних на /mnt/c таке проблемне?

Тому що ви перетинаєте віртуалізаційний/інтероперабельний кордон з різним кешуванням і семантикою метаданих.
Бази даних роблять багато дрібних записів і викликів fsync. Цей шлях карає їх.
Тримайте інтенсивні I/O в Linux-файловій системі і сприймайте /mnt/c як «добре для документів, не для гарячих даних».

3) kind чи k3d: що менше «розплавить» мій ноутбук?

k3d часто вимагає менше пам’яті за замовчуванням, бо k3s компактніший.
kind надзвичайно передбачуваний і легко фіксувати версії. Обидва можуть бути безпечними для ноутбука, якщо навантаження помірне і встановлено ліміти WSL2.
Моя уподобання: kind для роботи з платформою та імітації мультивузловості; k3d для «просто запустити стек».

4) Скільки RAM виділити WSL2?

На 16GB всього: 6–8GB як верхня межа — хороший вибір.
На 32GB: 12–16GB підходить.
Якщо виділити занадто багато, ви заховаєте погані ліміти подів і тонко голодуватимете Windows-додатки.

5) Чому WSL2 тримає пам’ять після зупинки навантажень?

Linux агресивно використовує пам’ять під файловий кеш. Це зазвичай добре.
Звільнення пам’яті WSL2 назад у Windows може бути повільнішим, ніж хочеться.
Якщо треба RAM негайно — вимкніть WSL; якщо хочете довготривалу нормальність — обмежте пам’ять і зменшіть фоновий шум.

6) Чому kubectl повільний лише коли увімкнений VPN?

VPN-клієнти часто впроваджують DNS-резолвери і правила маршрутизації.
Kubernetes залежить від DNS внутрішньо, а kubectl — від надійного з’єднання з API.
Діагностуйте за допомогою тесту DNS і readyz; потім вирішіть, чи split-tunnel, налаштування резолверів або робота з локальним кластером без VPN.

7) Як відкрити сервіси в Windows з кластера у WSL2?

Визначте, чи використовуєте ви форвардинг localhost або IP VM WSL.
Для передбачуваного UX багато команд роблять порт-форвард (kubectl port-forward) або запускають ingress, який відображається на відомих портах.
Задокументуйте метод, щоб команда не дебагала «localhost» заради розваги.

8) Чи можна запускати stateful навантаження (Postgres, Kafka) локально у WSL2 Kubernetes?

Так, але будьте реалістичні. Postgres підходить для деву, якщо дані живуть у файловій системі Linux і ви не запускаєте ще п’ять важких стеків.
Kafka можлива, але часто локальна «парність» перетворюється на «локальне покарання». Розгляньте легші замінники, якщо не дебажите специфічну поведінку Kafka.

9) Як часто пересоздавати локальний кластер?

Якщо ви працюєте з платформою та багатьма CRD і контролерами, пересоздавання щотижня або раз на два тижні — нормально.
Якщо кластер стабільний і лаконічний, можна тримати його довше.
Пересоздавайте одразу, коли підозрюєте дріфт: дивний DNS, застряглі вебхуки або таємничі admission-помилки.

10) Яка найпоширеніша корінна причина «все повільно»?

Зберігання. Або навантаження на неправильному шляху файлової системи, або диск майже повний, або система пише логи ніби за рядок платять.
Пам’ять — друга. DNS — третя. Kubernetes рідко перший винуватець; він просто сцена, на якій проблема виступає.

Наступні кроки, які можна зробити сьогодні

  1. Встановіть ліміти WSL2 (пам’ять, CPU, swap). Якщо робити лише одну річ — зробіть це.
  2. Перемістіть гарячі дані з /mnt/c: storage runtime, PV, бази даних, кеші збірки — тримайте їх у файловій системі Linux.
  3. Оберіть лаконічний профіль кластера: kind або k3d з лише основними addon-ами. Зробіть «повний стек» опційним.
  4. Прийміть швидкий план діагностики: перевірка тиску хоста, потім здоров’я контрольної площини, потім топ-споживачі. Хватить гадати.
  5. Заплануйте нудне обслуговування: prune кеші, видаляйте невикористані неймспейси і пересоздавайте кластер, коли з’являється дріфт.

Кінцева ідея не в тому, щоб побудувати найефектніший локальний кластер. Мета — побудувати такий, що веде себе передбачувано під навантаженням.
Передбачуваність — це те, що тримає ваш ноутбук прохолодним — і вашу голову теж.

← Попередня
ІТ‑індустрія: брехня «переписати з нуля» — чому це провалюється і що працює
Наступна →
Шурхіт аудіо в Windows 11: виправте затримки без покупки нового обладнання

Залишити коментар