Files
KindClustersDashboard/README.md
Sergey Antropoff 02f4c655b9 UI: автообновление, прогресс, отмена; порт 8080; меню-пилюли и отдельные окна
- Порт хоста по умолчанию 8080 (Chrome ERR_UNSAFE_PORT на 6000); compose, setup, config, README.
- Дашборд: одна hero-карточка, прогресс создания, POST /jobs/{id}/cancel, JobView progress_*.
- job_store: отмена и прогресс (thread-safe); cluster_lifecycle этапы и откат.
- Навигация: стили nav-pill; Swagger/ReDoc/Health через window.open.
- main.py: TemplateResponse(request, …) для Starlette.
- Документация: README, app/docs (api_routes, README); Makefile ps; .gitignore clusters.
2026-04-04 05:58:11 +03:00

182 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# kind-k8s-develop — локальные кластеры 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](https://devops.org.ru)
## Документация
| Ресурс | Описание |
|--------|----------|
| **[app/docs/api_routes.md](app/docs/api_routes.md)** | Описание REST API `/api/v1/*` с примерами JSON (для фронтенда и интеграций) |
| **[app/docs/README.md](app/docs/README.md)** | Указатель по каталогу `app/docs/` |
| **`/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` в приложении или в `kubectl`.
## Веб-интерфейс
- Верхняя **единая карточка**: заголовок, краткое описание и строка **состояния среды** (`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`) |
| **kubectl** (опционально) | Проверка API с хоста: `kubectl --kubeconfig=clusters/<имя>/kubeconfig get nodes` |
**В образ не обязательно ставить на хост:** kind, Python приложения — они внутри контейнера.
Смонтированы **сокет** Docker/Podman и каталог **`./clusters`** → в контейнере **`/work/clusters`**. Каталог **`./app`** монтируется в **`/opt/kind-k8s/app`** для разработки без пересборки образа.
После создания кластера kubeconfig по умолчанию **патчится** на `https://127.0.0.1:<порт>` для доступа с хоста (`KIND_K8S_PATCH_KUBECONFIG`, см. `app/kubeconfig_patch.py`).
## Быстрый старт
```bash
cd kind-k8s-develop
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 kind-k8s-develop docker up`.
**Логи, статус и остановка:** `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`**.
По умолчанию (**`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, скрипты):
```bash
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`.
После успешного `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 compose-build` / `make podman compose-build` | Собрать образ `kind-k8s-tools:local` |
| `make docker check-docker` / `make podman check-docker` | Проверить выбранный CLI и `compose version` |
| `make setup` | Интерактивно создать `.env` (список переменных в `scripts/setup_env_interactive.py`) |
| `make clusters-dir` | Создать каталог `clusters/` |
| `make docker …` / `make podman …` | Префикс **обязателен** для целей `up`, `down`, `logs`, `ps`, `compose-build`, `check-docker` |
Цели `up`, `down`, `logs`, `ps`, `compose-build` и `check-docker` **без** `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_WORKDIR`** | локальный запуск | Корень данных на машине разработчика без compose |
| **`COMPOSE_BUILD_FLAGS`** | Makefile | Например `make docker compose-build COMPOSE_BUILD_FLAGS=--platform linux/arm64` |
## Podman (пример rootless)
```bash
export CONTAINER_SOCKET="$XDG_RUNTIME_DIR/podman/podman.sock"
make podman up
```
## Структура репозитория (основное)
| Путь | Назначение |
|------|------------|
| `Makefile` | Запуск веб-UI; префикс `docker` или `podman` обязателен для compose-целей |
| `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`, сокет |
| `app/main.py` | FastAPI: дашборд `/`, редирект `/ui`, монтирование `/static` |
| `app/api/v1/` | REST API: `router.py`, `endpoints/` (`health`, `versions`, `clusters`) |
| `app/core/` | Жизненный цикл кластеров, задания, настройки, блокировки (`kind_guard`), пути |
| `app/models/schemas.py` | Pydantic-схемы запросов/ответов API |
| `app/templates/` | Jinja2: `base.html`, `dashboard.html` |
| `app/static/` | `style.css`, `js/dashboard.js` |
| `app/docs/` | `api_routes.md`, `README.md` |
| `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** (в образе kubectl только внутри контейнера).
- История заданий создания в UI/API хранится в памяти (до **200** записей); после перезапуска контейнера очищается.
- При **`exec format error`** у kind пересоберите образ: `make docker compose-build COMPOSE_BUILD_FLAGS=--platform linux/arm64` (или `make podman …`, или `linux/amd64`).