- Документация: хлебные крошки; секции H2 в одной карточке; заголовок вкладки от H1 - Навигация: активна только текущая пилюля (Панель без постоянного home-стиля) - GET /api/v1/stats: cluster_resources (docker stats CPU/RAM/I/O по узлам kind) - Панель: блок ресурсов в карточке статистики; убраны строки подвала про api_routes/clusters - Удалён app/docs/README.md; крошки app/docs → api_routes.md; README корня обновлён
Kind Clusters Dashboard — локальные кластеры Kubernetes (kind)
Образ kind-k8s-tools:local и Makefile поднимают веб-интерфейс (FastAPI) на порту 8080 на хосте по умолчанию (или KIND_K8S_WEB_PORT в .env; внутри контейнера приложение слушает 6000). Порт 6000 на хосте не используем по умолчанию: Chrome и другие браузеры на Chromium отдают ERR_UNSAFE_PORT. Через браузер создаёте и удаляете кластеры, смотрите статистику и вывод kubectl. kubeconfig сохраняется в clusters/<имя>/. На хосте достаточно Docker (или Podman) и make; kind и kubectl — внутри контейнера.
Автор: Сергей Антропов — devops.org.ru
Документация
| Ресурс | Описание |
|---|---|
| app/docs/api_routes.md | Описание REST API /api/v1/* с примерами JSON (для фронтенда и интеграций) |
/docs (Swagger), /redoc, /api/v1/health |
На панели открываются в отдельном окне браузера (window.open); прямой URL — тот же порт, что и UI (по умолчанию 8080) |
Шаблона env.example в репозитории нет: переменные для .env задаются интерактивно скриптом scripts/setup_env_interactive.py (make setup).
Зачем это нужно
- Быстро получить Kubernetes без облака (интеграционные тесты, манифесты, обучение).
- Версия кластера и число worker-нод задаются в веб-UI (или через REST API / скрипты в контейнере).
- Количество кластеров не ограничено кодом (ограничения — ресурсы хоста и Docker).
- Артефакты на хосте:
clusters/<имя>/— том дляkubeconfig(доступен в контейнере как/work/clusters/<имя>/).
Веб-интерфейс
- Верхняя единая карточка: заголовок, краткое описание и строка состояния среды (
kind/kubectl/ Docker или Podman API). - Статистика: число кластеров в kind, локальных каталогов, сумма workers из
meta.json, счётчики фоновых заданий. - Создание кластера: форма с подсказкой тегов
kindest/node(GET /api/v1/versions), фоновое задание и опрос статуса (JSON в сворачиваемом блоке). - Таблица кластеров: признаки регистрации в kind и наличия kubeconfig, скачивание kubeconfig, просмотр узлов/подов в модальном окне, удаление.
- Последние задания создания (данные в памяти процесса; после перезапуска контейнера история сбрасывается).
- Автообновление таблиц и плашки среды каждые ~3,5 с (fetch к API без перезагрузки страницы).
- При создании кластера — прогресс-бар и текст текущего этапа; кнопка «Отменить создание» (между этапами; шаг
kind createдо конца не прерывается). - Уведомления (toast) при успехе/ошибке; в подвале — копирайт и ссылка на devops.org.ru.
Шапка: навигация в виде пилюль (стили .nav-pill); пункты Swagger, ReDoc и Health открывают страницу в отдельном именованном окне (~1240×840), чтобы не уходить с панели (см. скрипт в base.html).
Структура фронтенда: app/templates/base.html (шапка и меню), app/templates/dashboard.html, app/static/style.css, app/static/js/dashboard.js (префикс API: data-api-base на <body>, по умолчанию /api/v1).
Требования на хосте
| Компонент | Назначение |
|---|---|
| Docker + Compose v2 (или Podman + compose) | Сборка образа и запуск веб-сервиса |
| make | make docker up / make podman up и вспомогательные цели |
| python3 | Только для make setup (создание .env) |
На хост не нужны: kind, kubectl, Python приложения — всё это в образе kind-k8s-tools:local и выполняется в контейнере kind-k8s-web. Проверка API и узлов: веб-интерфейс (кластер → узлы/поды) или make docker kubectl CLUSTER=<имя> / make podman kubectl … (см. ниже) — kubectl вызывается через docker compose exec / podman compose exec внутри уже запущенного сервиса.
Файл clusters/<имя>/kubeconfig на хосте можно использовать опционально, если у вас локально установлен kubectl (например IDE или отладка) — после патча apiserver обычно указывает на 127.0.0.1:<порт>.
Смонтированы сокет Docker/Podman и каталог ./clusters → в контейнере /work/clusters. Каталог ./app монтируется в /opt/kind-k8s/app для разработки без пересборки образа. Файл ./README.md монтируется в /opt/kind-k8s/README.md (страница «Документация» и GET /api/v1/docs/readme без пересборки образа).
После создания кластера kubeconfig по умолчанию патчится на https://127.0.0.1:<порт> для доступа с хоста (KIND_K8S_PATCH_KUBECONFIG, см. app/kubeconfig_patch.py).
Быстрый старт
# Из корня клонированного репозитория Kind Clusters Dashboard (рядом с Makefile):
make setup # опционально: интерактивно создать .env (Enter — дефолты из скрипта)
make docker check-docker # или: make podman check-docker
make docker up # или: make podman up
# Браузер: http://127.0.0.1:8080 (порт: KIND_K8S_WEB_PORT в .env; не 6000 на хосте — Chrome ERR_UNSAFE_PORT)
Из родительского каталога: make -C <каталог-корня-репозитория> docker up (подставьте путь к каталогу с Makefile).
Логи, статус и остановка: make docker logs / make podman logs (follow), make docker ps / make podman ps, make docker down / make podman down.
Разработка UI и API без пересборки образа
В docker-compose.yml смонтированы ./app → /opt/kind-k8s/app и ./README.md → /opt/kind-k8s/README.md (только чтение).
По умолчанию (KIND_K8S_UVICORN_RELOAD=1) uvicorn запускается с --reload (см. scripts/run_uvicorn.sh) и перезапускает процесс при изменении *.py, *.html, *.css, *.js в app/. Пересобирать образ нужно после изменений Dockerfile, requirements.txt или scripts/run_uvicorn.sh.
Отключить reload: в .env задать KIND_K8S_UVICORN_RELOAD=0.
Дополнительно: CLI в одноразовом контейнере
Если нужен сценарий без UI (CI, скрипты):
docker compose run --rm --entrypoint python3 kind-k8s-web \
/opt/kind-k8s/app/create_cluster.py --non-interactive --name dev --kubernetes-version 1.29.4 --workers 2
docker compose run --rm --entrypoint python3 kind-k8s-web \
/opt/kind-k8s/app/delete_cluster.py --non-interactive --name dev --yes
Рабочий каталог сервиса в образе — /opt/kind-k8s/app; том clusters/ и сокет те же, что у docker compose up.
kubectl без установки на хост
Пока запущен веб-сервис (make docker up или make podman up), kubectl из образа:
# По умолчанию: get nodes (kubeconfig: /work/clusters/<имя>/kubeconfig внутри контейнера)
make docker kubectl CLUSTER=<имя_кластера>
# или: make podman kubectl CLUSTER=<имя_кластера>
make docker kubectl CLUSTER=<имя> KUBECTL_ARGS="get pods -A"
make docker kubectl CLUSTER=<имя> KUBECTL_ARGS="config view --minify"
Эквивалент вручную (из корня репозитория, Docker):
docker compose exec kind-k8s-web kubectl --kubeconfig=/work/clusters/<имя>/kubeconfig get nodes
После успешного kind create по умолчанию выполняется kubectl wait готовности нод (KIND_K8S_WAIT_NODES, KIND_K8S_WAIT_NODES_TIMEOUT_SEC в .env) — тоже внутри контейнера приложения.
Команды Makefile
| Цель | Описание |
|---|---|
make help |
Краткая справка |
make docker up / make podman up |
Поднять веб-UI (kind-k8s-web) |
make docker down / make podman down |
Остановить compose в каталоге репозитория |
make docker logs / make podman logs |
Логи kind-k8s-web (stream, -f) |
make docker ps / make podman ps |
Статус контейнеров текущего compose-проекта |
make docker build / make podman build |
Собрать образ kind-k8s-tools:local |
make docker rebuild / make podman rebuild |
Пересборка образа без кэша (build --no-cache) и пересоздание контейнера (up -d --force-recreate) |
make docker check-docker / make podman check-docker |
Проверить выбранный CLI и compose version |
make docker kubectl CLUSTER=… / make podman kubectl CLUSTER=… |
kubectl в контейнере kind-k8s-web (опционально KUBECTL_ARGS="…"; по умолчанию get nodes). Сервис должен быть up. |
make setup |
Интерактивно создать .env (список переменных в scripts/setup_env_interactive.py) |
make clusters-dir |
Создать каталог clusters/ |
make docker … / make podman … |
Префикс обязателен для целей up, down, logs, ps, build, rebuild, check-docker, kubectl |
Цели up, down, logs, ps, build, rebuild, check-docker и kubectl без docker/podman в той же команде завершатся с подсказкой.
Переменные окружения
Файл .env в корне репозитория подхватывает Compose. Создать его: make setup или вручную по списку в scripts/setup_env_interactive.py. Файл .env в git не коммитится (см. .gitignore).
Переменные DOCKER_HOST, KIND_K8S_IN_CONTAINER, KIND_K8S_WORKDIR в контейнере задаются литералами в docker-compose.yml, а не из .env.
| Переменная | Где используется | Назначение |
|---|---|---|
KIND_VERSION |
build-arg | Версия бинарника kind при сборке образа |
KUBECTL_VERSION |
build-arg | Версия kubectl в образе; пусто в compose → в Dockerfile подставляется stable.txt при сборке; make setup предлагает закреплённый тег |
KIND_K8S_WEB_PORT |
ports | Порт на хосте для веб-UI (по умолчанию 8080; в контейнере публикация идёт на процесс на 6000) |
KIND_K8S_WEB_HOST |
локальный uvicorn / Settings | Хост привязки при запуске вне compose (в контейнере задаётся entrypoint) |
KIND_K8S_UVICORN_RELOAD |
контейнер | 1 (по умолчанию) — hot-reload при правках в ./app; 0 — без reload |
KIND_K8S_APP_TITLE |
контейнер / Settings | Заголовок OpenAPI и HTML; пустое значение из compose не ломает приложение (env_ignore_empty, fallback) |
KIND_K8S_WAIT_NODES |
контейнер | 0 — не ждать Ready нод после create |
KIND_K8S_WAIT_NODES_TIMEOUT_SEC |
контейнер | Таймаут kubectl wait (секунды) |
CONTAINER_SOCKET |
volume | Сокет Docker/Podman на хосте |
KIND_K8S_PATCH_KUBECONFIG |
контейнер | Патч server в kubeconfig для хоста; по умолчанию включено (1 в compose и в make setup) |
CONTAINER_CLI |
контейнер | CLI для docker port / podman port (docker или podman) |
KIND_K8S_SKIP_VERSION_LIST |
контейнер | Не ходить в Docker Hub за тегами |
KIND_K8S_VERSION_LIST_DISPLAY |
контейнер | Сколько тегов отдавать в API/UI |
KIND_K8S_HUB_TAGS_MAX_PAGES |
контейнер | Лимит страниц API Hub |
KIND_K8S_DEBUG |
контейнер | 1/true/yes/да — уровень DEBUG в логах |
KIND_K8S_JOB_LOG_MAX_LINES |
приложение | Размер буфера строк журнала фонового задания (kind create) для поля progress_log в API/UI; по умолчанию 500 (задаётся в коде, при необходимости передайте в compose) |
KIND_K8S_README_PATH |
контейнер / приложение | Абсолютный путь к README.md для страницы /documentation; если пусто — используется README.md рядом с каталогом app/ (в образе: /opt/kind-k8s/README.md) |
KIND_K8S_WORKDIR |
локальный запуск | Корень данных на машине разработчика без compose |
COMPOSE_BUILD_FLAGS |
Makefile | Например make docker build COMPOSE_BUILD_FLAGS=--platform linux/arm64 (то же для make docker rebuild) |
Podman (пример rootless)
export CONTAINER_SOCKET="$XDG_RUNTIME_DIR/podman/podman.sock"
make podman up
Структура репозитория (основное)
| Путь | Назначение |
|---|---|
Makefile |
Запуск веб-UI; префикс docker или podman обязателен; цели up, rebuild, build и др. |
scripts/setup_env_interactive.py |
Интерактивное создание .env (все ключи и дефолты внутри скрипта) |
scripts/run_uvicorn.sh |
Точка входа контейнера: uvicorn с опциональным --reload |
Dockerfile |
Образ: kind, kubectl, docker-cli, FastAPI |
requirements.txt |
pip-зависимости веб-приложения |
docker-compose.yml |
Сервис kind-k8s-web, тома ./clusters, ./app, ./README.md, сокет |
app/main.py |
FastAPI: дашборд /, /documentation, редирект /ui, монтирование /static |
app/api/v1/ |
REST API: router.py, endpoints/ (health, versions, docs_readme, clusters) |
app/core/ |
Жизненный цикл кластеров, задания, настройки, блокировки (kind_guard), пути |
app/models/schemas.py |
Pydantic-схемы запросов/ответов API |
app/templates/ |
Jinja2: base.html, dashboard.html, documentation.html |
app/static/ |
style.css, js/dashboard.js, js/documentation.js, js/vendor/ (marked, DOMPurify для README в UI) |
app/docs/ |
api_routes.md (описание REST API) |
app/create_cluster.py, delete_cluster.py, cluster_status.py |
CLI и переиспользование из API / compose run |
В UI и API список версий kindest/node по умолчанию тянется с Docker Hub (нужна сеть). В изолированной среде: KIND_K8S_SKIP_VERSION_LIST=1 — версию вводят вручную.
Где лежат данные на хосте
clusters/<имя>/kind-config.yamlclusters/<имя>/kubeconfigclusters/<имя>/meta.json
Содержимое clusters/*/ не коммитится; в репозитории есть clusters/.gitkeep.
Git и артефакты
В .gitignore: .env, каталоги в clusters/ (кроме .gitkeep), __pycache__/ и *.pyc, .DS_Store.
Ограничения
- Образ
kindest/node:v…должен быть доступен для pull. - На Windows без WSL удобнее WSL2 + Docker Desktop.
- kubectl на хосте не обязателен: используйте веб-UI или
make docker kubectl/make podman kubectl(см. выше). - История заданий создания в UI/API хранится в памяти (до 200 записей); после перезапуска контейнера очищается.
- При
exec format errorу kind пересоберите образ:make docker rebuild COMPOSE_BUILD_FLAGS=--platform linux/arm64(илиmake podman …, илиmake docker buildбез--no-cache, илиlinux/amd64).