Files
KindClustersDashboard/README.md
Sergey Antropoff eb063aec20 Веб-интерфейс: страница /clusters, навигация и крошки для кластеров
- Выделена страница списка кластеров, панель упрощена; nav_active и крошки
  ведут в раздел Кластеры; theme.js синхронизирует активную пилюлю по URL.
- Доработки дашборда, аддонов, журнала, стилей и API-документации.
- Поддержка Podman: docker-compose.podman.yml, скрипты сокета; Makefile и env.
2026-04-04 13:42:21 +03:00

24 KiB
Raw Blame History

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; в начале — только выбор docker или podman, путь CONTAINER_SOCKET подставляется автоматически).

Зачем это нужно

  • Быстро получить 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 в сворачиваемом блоке).
  • Кластеры (/clusters): сводка ресурсов узлов (донаты), таблица кластеров — старт/стоп, скачивание kubeconfig, модалки узлов/подов, ссылка на страницу кластера; с панели (/) — быстрый переход по ссылке в карточке «Создать кластер».
  • Аддоны (/cluster-addons): выбор кластера и установка/удаление через Helm в контейнере — ingress-nginx, kube-prometheus-stack (логин/пароль Grafana), metrics-server, Istio + Kiali (логин/пароль Kiali); журнал операции на странице (прогресс + вывод как при создании кластера), история в clusters/<имя>/helm_addon_log.json. Нужна пересборка образа после обновления Dockerfile (бинарник helm). Таймаут операций: KIND_K8S_HELM_TIMEOUT_SEC (по умолчанию 900 с).
  • Последние задания: история в памяти процесса (до 200 записей; после перезапуска контейнера сбрасывается); кнопка «Очистить завершённые» вызывает DELETE /api/v1/jobs (из памяти удаляются только завершённые задания).
  • Автообновление таблиц и плашки среды каждые ~3,5 с (fetch к API без перезагрузки страницы).
  • При активном задании — прогресс-бар, журнал (в т.ч. скачивание образа; для docker при поддержке CLI — pull --progress=plain, см. KIND_K8S_DOCKER_PULL_PLAIN), опрос статуса чаще, чем общие таблицы; кнопка «Отменить» — прерывание с завершением текущей дочерней команды.
  • Уведомления (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.host (или скачивание из веб-UI) для kubectl на хосте: https://<KIND_K8S_KUBECONFIG_CLIENT_HOST или localhost>:<порт> — см. app/kubeconfig_patch.py. Переменная позволяет задать IP/имя хоста, если localhost недоступен с вашей машины.

Смонтированы сокет Docker/Podman и каталог ./clusters → в контейнере /work/clusters. Каталог ./app монтируется в /opt/kind-k8s/app для разработки без пересборки образа. Файл ./README.md монтируется в /opt/kind-k8s/README.md (страница «Документация» и GET /api/v1/docs/readme без пересборки образа).

После создания кластера при KIND_K8S_PATCH_KUBECONFIG дополнительно пишется kubeconfig.host; скачивание через API каждый раз пересобирает файл с актуальным портом и хостом из KIND_K8S_KUBECONFIG_CLIENT_HOST.

Быстрый старт

# Из корня клонированного репозитория 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 restart / make podman restart (перезапуск сервиса kind-k8s-web), 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 restart / make podman restart Перезапустить контейнер сервиса kind-k8s-web (compose restart)
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, restart, logs, ps, build, rebuild, check-docker, kubectl

Цели up, down, restart, 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 Путь к сокету на хосте; при make podman … перед compose пишется .env.podman.override.gitignore) с актуальным путём из scripts/detect_podman_socket.py, чтобы перекрыть .env: иначе старый docker-compose часто подставляет том из .env (в т.ч. неверный сокет /var/folders/…/podman-machine-default-api.sock) и падает с operation not supported
CONTAINER_SOCKET_MOUNT_TARGET volume Путь внутри контейнера: Docker — /var/run/docker.sock; Podman — /run/podman/podman.sock
KIND_K8S_REMOTE_SOCKET_URI контейнер DOCKER_HOST URI API (совпадает с точкой монтирования), например unix:///run/podman/podman.sock для Podman
KIND_K8S_PATCH_KUBECONFIG контейнер Патч server в kubeconfig для хоста; по умолчанию включено (1 в compose и в make setup)
CONTAINER_CLI контейнер CLI для docker port / podman port (docker или podman)
KIND_K8S_CONTAINER_UIDGID compose user uid:gid процесса в контейнере; для Docker обычно 0:0; для rootless Podman — $(id -u):$(id -g) (пишет make setup)
KIND_K8S_CONTAINER_HOME контейнер HOME Для не-root в образе без /home/<uid>: /tmp (Podman); для root — /root
KIND_K8S_SKIP_VERSION_LIST контейнер Не ходить в Docker Hub за тегами
KIND_K8S_VERSION_LIST_DISPLAY контейнер Сколько строк показывать в интерактивном CLI при выборе версии (веб-UI выводит полный список из API)
KIND_K8S_HUB_TAGS_MAX_PAGES контейнер Сколько страниц Docker Hub обходить при сборе тегов (старые 1.19.x часто на поздних страницах; в коде по умолчанию 120, максимум 500)
KIND_K8S_DEBUG контейнер 1/true/yes/да — уровень DEBUG в логах
KIND_K8S_JOB_LOG_MAX_LINES приложение Сколько строк журнала хранить в памяти на задание (старые вытесняются); по умолчанию 2500
KIND_K8S_JOB_API_LOG_MAX_LINES приложение Сколько строк отдавать в GET /api/v1/jobs/{id} (хвост); по умолчанию 5000, максимум 20000
KIND_K8S_JOBS_JSON приложение Путь к JSON с историей заданий; пусто — clusters/kind_k8s_jobs.json под KIND_K8S_WORKDIR
KIND_K8S_STREAM_PTY приложение 1 (по умолчанию) — для kind и podman pull псевдо-TTY; 0 — только pipe
KIND_K8S_DOCKER_PULL_PLAIN приложение 1 (по умолчанию) — если в выводе docker pull --help есть --progress, используется docker pull --progress=plain без PTY; иначе обычный pull. 0 — никогда не добавлять флаг
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

Доступ к сокету (permission denied на /var/run/docker.sock внутри контейнера): у rootless Podman сокет обычно принадлежит вашему пользователю, а не «root» из контейнера. В .env для Podman нужны KIND_K8S_CONTAINER_UIDGID=$(id -u):$(id -g) и KIND_K8S_CONTAINER_HOME=/tmp — при make setup с выбором Podman скрипт записывает их сам. Команды make podman … подмешивают docker-compose.podman.yml (userns_mode: keep-id) и дублируют uid/gid в окружении: без keep-id rootless Podman часто даёт permission denied на смонтированный сокет даже при верном user:. Вручную: podman compose -f docker-compose.yml -f docker-compose.podman.yml up -d и те же переменные в .env или в shell. На системах с SELinux при отказе доступа к сокету попробуйте CONTAINER_SOCKET_VOLUME_OPTS=:Z в .env.

Структура репозитория (основное)

Путь Назначение
Makefile Запуск веб-UI; префикс docker или podman обязателен; цели up, down, restart, logs, rebuild, build и др. Для Podman: --env-file .env.podman.override (нужен compose с поддержкой --env-file, обычно ≥ 1.28).
.env.podman.override Создаётся целью make podman …: CONTAINER_SOCKET, KIND_K8S_* для сокета; перекрывает устаревшие значения в .env.
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, сокет
docker-compose.podman.yml Только для Podman: userns_mode: keep-id (подмешивается в make podman …)
app/main.py FastAPI: главная /, создание кластера /cluster-create, /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.yaml
  • clusters/<имя>/kubeconfig
  • clusters/<имя>/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 записей); после перезапуска контейнера очищается. Завершённые записи можно удалить из памяти кнопкой на панели или DELETE /api/v1/jobs.
  • При exec format error у kind пересоберите образ: make docker rebuild COMPOSE_BUILD_FLAGS=--platform linux/arm64 (или make podman …, или make docker build без --no-cache, или linux/amd64).