- README: веб-UI, структура static/templates, нет env.example, make setup, KIND_K8S_WEB_HOST, jobs в памяти, .gitignore, ссылки на /docs и ReDoc. - api_routes: сводная таблица маршрутов, UI/статика, поведение jobs (лимит 200), уточнение stats, коды 400 для kubeconfig/workloads/delete. - app/docs/README.md: навигация по документации приложения.
9.9 KiB
Описание REST API веб-интерфейса kind-k8s-develop
Базовый префикс: /api/v1
Автор: Сергей Антропов — devops.org.ru
Как смотреть документацию
| Способ | URL / путь |
|---|---|
| Swagger UI (OpenAPI) | http://127.0.0.1:<порт>/docs (порт по умолчанию 6000, см. KIND_K8S_WEB_PORT) |
| ReDoc | http://127.0.0.1:<порт>/redoc |
| Этот файл | app/docs/api_routes.md в репозитории |
Веб-интерфейс и статика (не JSON)
| Маршрут | Описание |
|---|---|
GET / |
HTML-панель: статус среды (kind, kubectl, Docker/Podman), статистика, форма создания кластера, таблицы кластеров и заданий, модальное окно «узлы / поды», ссылки на API. |
GET /ui |
Редирект 307 на / (удобный ярлык). |
GET /static/… |
CSS (style.css), скрипт панели (js/dashboard.js); базовый URL API задаётся атрибутом data-api-base на <body> (по умолчанию /api/v1). |
Шаблоны: app/templates/base.html (шапка, навигация), app/templates/dashboard.html (контент панели).
Сводка маршрутов API
| Метод | Путь | Кратко |
|---|---|---|
| GET | /api/v1/health |
Среда: kind, kubectl, движок контейнеров |
| GET | /api/v1/versions |
Теги kindest/node (Docker Hub) или пусто при KIND_K8S_SKIP_VERSION_LIST |
| GET | /api/v1/stats |
Сводка для дашборда |
| GET | /api/v1/clusters |
Список кластеров |
| POST | /api/v1/clusters |
Создание в фоне (202 + job_id) |
| GET | /api/v1/clusters/{name} |
Детали + kubectl get nodes при наличии kubeconfig |
| GET | /api/v1/clusters/{name}/kubeconfig |
Скачать файл kubeconfig |
| GET | /api/v1/clusters/{name}/workloads |
Узлы и поды (kubectl) |
| DELETE | /api/v1/clusters/{name} |
Удалить кластер и данные в clusters/ |
| GET | /api/v1/jobs |
Последние задания создания |
| GET | /api/v1/jobs/{job_id} |
Статус одного задания |
Фоновые задания (jobs)
- Хранятся только в памяти процесса uvicorn; после перезапуска контейнера история обнуляется.
- В памяти держится не более 200 записей; при превышении старые задания вытесняются (
app/core/job_store.py). - Создание кластера:
POST /api/v1/clusters→ опросGET /api/v1/jobs/{job_id}(как в веб-UI).
GET /api/v1/health
Проверка: kind/kubectl в PATH и ответ движка контейнеров (docker info / podman info по CONTAINER_CLI).
status: ok — всё готово к созданию кластеров; degraded — чего-то не хватает (см. поля ниже).
Пример ответа 200 (JSON):
{
"status": "ok",
"kind_in_path": true,
"kubectl_in_path": true,
"container_cli": "docker",
"container_engine_ok": true,
"container_engine_detail": null
}
Если сокет Docker недоступен:
{
"status": "degraded",
"kind_in_path": true,
"kubectl_in_path": true,
"container_cli": "docker",
"container_engine_ok": false,
"container_engine_detail": "Cannot connect to the Docker daemon..."
}
GET /api/v1/versions
Список стабильных тегов kindest/node с Docker Hub (для выпадающего списка в UI).
При KIND_K8S_SKIP_VERSION_LIST=1 список пустой.
Пример ответа 200:
{
"tags": ["v1.32.0", "v1.31.4"],
"skipped": false
}
Пример при пропуске загрузки:
{
"tags": [],
"skipped": true,
"reason": "KIND_K8S_SKIP_VERSION_LIST"
}
GET /api/v1/stats
Сводная статистика для дашборда.
Пример ответа 200:
{
"kind_clusters_count": 2,
"local_cluster_dirs_count": 2,
"total_workers_from_meta": 4,
"jobs_total": 5,
"jobs_recent_failed": 1
}
total_workers_from_metaможет бытьnull, если ни в одномmeta.jsonнетworker_nodes.jobs_total— число заданий в текущей памяти процесса (не более 200).jobs_recent_failed— сколько заданий в этом хранилище сейчас в статусеfailed(не «последние N», а счётчик по всему снимку).
GET /api/v1/clusters
Список: объединение kind get clusters и подкаталогов clusters/* (без дубликатов).
Пример ответа 200 (массив):
[
{
"name": "dev",
"registered_in_kind": true,
"has_local_kubeconfig": true,
"meta": {
"cluster_name": "dev",
"kubernetes_version_tag": "v1.29.4",
"node_image": "kindest/node:v1.29.4",
"worker_nodes": 2,
"kubeconfig_patched_for_host": true
}
}
]
GET /api/v1/jobs
Список последних фоновых заданий (создание кластера), от новых к старым.
Query: limit (1–200, по умолчанию 30).
Пример ответа 200 (массив JobView):
[
{
"job_id": "abc123",
"kind": "create_cluster",
"status": "success",
"cluster_name": "dev",
"created_at_utc": "2026-04-04T12:00:00+00:00",
"message": "Кластер создан",
"result": { "cluster_name": "dev", "kubernetes_version_tag": "v1.29.4" }
}
]
GET /api/v1/clusters/{name}/kubeconfig
Скачать файл kubeconfig (ответ — тело файла, Content-Disposition с именем kubeconfig-{name}.yaml).
Ошибка 404: файла нет в clusters/{name}/.
Ошибка 400: некорректное имя кластера.
GET /api/v1/clusters/{name}/workloads
kubectl get nodes -o wide и kubectl get pods -A по сохранённому kubeconfig.
Пример ответа 200:
{
"cluster_name": "dev",
"nodes_rc": 0,
"nodes_output": "NAME STATUS ROLES ...",
"pods_rc": 0,
"pods_output": "NAMESPACE NAME READY STATUS ...",
"error": null
}
Если kubeconfig нет: error — строка вида Нет сохранённого kubeconfig в clusters/<имя>/, поля вывода kubectl могут быть null.
Ошибка 400: некорректное имя кластера.
GET /api/v1/clusters/{name}
Детали и попытка kubectl get nodes -o wide с сохранённого clusters/{name}/kubeconfig (если файл есть).
Пример ответа 200:
{
"name": "dev",
"registered_in_kind": true,
"has_local_kubeconfig": true,
"kubeconfig_path": "/work/clusters/dev/kubeconfig",
"meta": { "worker_nodes": 2 },
"kubectl_get_nodes_rc": 0,
"kubectl_get_nodes": "NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME\n..."
}
POST /api/v1/clusters
Создание кластера в фоне (ответ 202).
Тело запроса (JSON):
{
"name": "dev",
"kubernetes_version": "1.29.4",
"workers": 2
}
Пример ответа 202:
{
"job_id": "a1b2c3d4e5f6...",
"status": "queued",
"message": "Создание кластера выполняется в фоне; опросите GET /api/v1/jobs/{job_id}"
}
Ошибка 400: невалидное имя кластера или тело не проходит валидацию Pydantic.
Ошибка 409 (кластер уже есть в kind):
{
"detail": "Кластер с таким именем уже есть в kind"
}
GET /api/v1/jobs/{job_id}
Статус фонового задания создания.
В процессе (пример 200):
{
"job_id": "a1b2...",
"kind": "create_cluster",
"status": "running",
"cluster_name": "dev",
"created_at_utc": "2026-04-04T12:00:00+00:00",
"message": null,
"result": null
}
Успех (пример 200):
{
"job_id": "a1b2...",
"kind": "create_cluster",
"status": "success",
"cluster_name": "dev",
"created_at_utc": "2026-04-04T12:00:00+00:00",
"message": "Кластер создан",
"result": {
"cluster_name": "dev",
"kubernetes_version_tag": "v1.29.4",
"node_image": "kindest/node:v1.29.4",
"workers": 2,
"kubeconfig_path": "/work/clusters/dev/kubeconfig",
"kubeconfig_patched_for_host": true,
"nodes_ready": true,
"nodes_ready_message": "..."
}
}
Ошибка 404:
{
"detail": "Задание не найдено"
}
DELETE /api/v1/clusters/{name}
kind delete cluster и удаление каталога clusters/{name}/.
Пример ответа 200:
{
"name": "dev",
"kind_delete_ok": true,
"summary": "kind delete: OK; удалена папка /work/clusters/dev"
}
Ошибка 400: некорректное имя кластера.
Ошибка 500: логическая ошибка удаления (тело с detail).
GET /
HTML-дашборд (не JSON): см. раздел «Веб-интерфейс и статика» выше.