kind: кластер из контейнеров
Как kind поднимает Kubernetes внутри Docker, как сделать multi-node, пробросить порты наружу и получить работающий Ingress.
kind расшифровывается как Kubernetes IN Docker. Идея простая: то, что в обычном кластере является отдельной машиной, здесь становится обычным контейнером. Один контейнер - одна нода. Внутри контейнера крутится containerd, kubelet и всё остальное, что положено ноде.
Из этого следует главное свойство инструмента. Кластер поднимается за десятки секунд и удаляется одной командой, потому что удалить контейнер дёшево. Ничего не остаётся на диске, кроме образа ноды.
Проект родился как тестовый стенд для самого Kubernetes, и это до сих пор видно по темпу релизов: v0.31.0 в декабре 2025, v0.32.0 в июне 2026, v0.33.0 в августе 2026.
Версии и образы нод
Актуальная версия kind - v0.33.0 от 26 августа 2026. По умолчанию она
создаёт кластер на Kubernetes 1.37.0, образ kindest/node:v1.37.0.
Под v0.33.0 собраны образы для четырёх версий Kubernetes:
kindest/node:v1.37.0kindest/node:v1.36.4kindest/node:v1.35.8kindest/node:v1.34.11
Есть требование, о которое спотыкаются на Apple Silicon: платформа образа ноды обязана совпадать с платформой хоста. На arm64-машине нужен arm64-образ. Эмуляция здесь не спасает.
Рантайм по умолчанию - Docker версии 20.10 и выше. Podman от 3.0 и nerdctl от 1.7 тоже подходят, выбор переключается переменной окружения:
KIND_EXPERIMENTAL_PROVIDER=podman kind create cluster
У Podman лимит pids по умолчанию 4096. Для кластера этого мало: процессы
упираются в лимит, и поды перестают подниматься.
Значения переменной: docker, podman, nerdctl. Отдельно стоит сказать
про память. В документации встречаются 6-8 GB RAM, но это требование к
сборке собственных образов ноды. Обычная работа с готовым образом столько
не просит.
Установка
brew install kind # macOS
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.33.0/kind-linux-amd64 # Linux
chmod +x ./kind && sudo mv ./kind /usr/local/bin/kind
winget install Kubernetes.kind # Windows
Жизненный цикл кластера
kind create cluster
kind create cluster --name lab --image kindest/node:v1.35.8
kind delete cluster --name lab
kind get clusters
Без флагов кластер получает имя kind, контекст в kubeconfig прописывается
автоматически. --image задаёт версию Kubernetes, kind get clusters
показывает, что сейчас живёт на машине.
Несколько нод
Одна нода закрывает большинство сценариев, но планировщик на ней изучать неудобно. Чтобы получить несколько нод, нужен конфиг-файл:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
Запуск с этим файлом:
kind create cluster --config kind-multi.yaml
Каждая запись в nodes превращается в отдельный контейнер.
Порты наружу
Кластер живёт в контейнерах, а контейнеры по умолчанию не отдают свои порты
хосту. На macOS и Windows это обязательный шаг, без него до сервисов не
достучаться. Пробрасывают порты через extraPortMappings в конфиге:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 80
hostPort: 80
listenAddress: "127.0.0.1"
protocol: TCP
Отдельный случай - NodePort. Тут есть тонкость, на которой теряют время:
containerPort в конфиге kind и nodePort в Service должны совпадать.
Проброс делается один раз при создании кластера, а Service появляется позже,
и подогнать придётся именно Service под уже открытый порт.
LoadBalancer и Ingress
Service типа LoadBalancer в kind сам по себе повиснет без внешнего адреса: раздавать адреса некому. Эту роль берёт отдельный бинарь cloud-provider-kind, текущая версия v0.11.1 от 26 июня 2026.
Начиная с v0.9.0 (28 октября 2025) он умеет обслуживать не только
LoadBalancer, но и Ingress. Документация kind после этого была переписана и
теперь прямо говорит: «No third-party ingress controllers are required by
default». Отдельный ingress-контроллер ставить не нужно. Gateway API там
тоже включён, канал выбирается флагом --gateway-channel со значениями
standard, experimental или disabled.
brew install cloud-provider-kind
kind create cluster
cloud-provider-kind # держать запущенным
kubectl get ingress # ADDRESS заполнится
Процесс cloud-provider-kind должен работать всё время, пока нужен внешний
адрес. Закрыли терминал - адреса перестали выдаваться.
Полный пример из документации kind:
kind create cluster
kubectl apply -f https://kind.sigs.k8s.io/examples/ingress/usage.yaml
INGRESS_IP=$(kubectl get ingress example-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl ${INGRESS_IP}/foo
Одна деталь про однонодовый кластер. По умолчанию в kind поды садятся на control-plane, а балансировщик такие ноды исключает. Метку нужно снять:
kubectl label node kind-control-plane node.kubernetes.io/exclude-from-external-load-balancers-
Дефис в конце имени метки - это синтаксис удаления, не опечатка.
На macOS и Windows ноды kind недостижимы с хоста напрямую, поэтому
cloud-provider-kind включает режим --enable-lb-port-mapping. Он поднимает
вспомогательный контейнер с именем вида kindccm-… и вешает на него
эфемерный порт хоста. Ходить нужно на localhost:<этот порт>, а не на
адрес, который показывает kubectl get svc.
Хранилище
StorageClass в kind есть из коробки: standard, помеченный как дефолтный.
PersistentVolumeClaim без указания класса подхватит именно его.
Что обычно ломается
Не хватает inotify. Симптом расплывчатый: поды не поднимаются, в логах компонентов мелькают ошибки про слежение за файлами. Лечится на хосте:
fs.inotify.max_user_watches=524288
fs.inotify.max_user_instances=512
Rootless-режим. Требует cgroup v2 и делегирования cpu-контроллера. С systemd версии 252 и выше делегирование включается само, на более старых системах его надо настраивать руками.
Не загружены модули ядра. В rootless-конфигурациях часто не подгружены
ip_tables и iptable_nat. Сеть кластера при этом ломается целиком, а
сообщение об ошибке на причину не указывает.
WSL2 и xt_recent. В ядре WSL2 нет модуля xt_recent. Из-за этого не
работает sessionAffinity: ClientIP, и ломается не только сам Service с
этой настройкой, но и Service, созданные после него.
Коротко
- kind запускает ноды Kubernetes как контейнеры Docker, Podman или nerdctl.
- v0.33.0 по умолчанию даёт Kubernetes 1.37.0; доступны образы 1.37.0, 1.36.4, 1.35.8, 1.34.11.
- Платформа образа ноды должна совпадать с платформой хоста.
- Multi-node описывается конфиг-файлом со списком
nodes. - Порты наружу открываются только через
extraPortMappings, и для NodePortcontainerPortобязан совпадать сnodePortв Service. - LoadBalancer и Ingress даёт cloud-provider-kind; с v0.9.0 сторонний ingress-контроллер не нужен.
- StorageClass
standardдоступен сразу и является дефолтным.
Прошли материал до конца? Отметьте урок пройденным.
Прогресс сохранён в этом браузере
Почистишь историю или откроешь с телефона, и отметки пропадут. Оставь почту, они переедут в аккаунт. Пароль придумывать не нужно.
Готово. теперь в аккаунте: прогресс виден с любого устройства. Мой прогресс