Веб-UI FastAPI, REST API v1, интерактивный setup без env.example
- Дашборд (Jinja2 + static), управление кластерами kind, задания и kubeconfig. - API: health, stats, clusters CRUD, versions, jobs; документация app/docs/api_routes.md. - Docker Compose: том app, uvicorn reload, KIND_K8S_PATCH_KUBECONFIG по умолчанию 1. - setup_env_interactive.py: список переменных в скрипте, удалён env.example. - Makefile: явный префикс docker/podman; прочие правки CLI и ядра кластеров.
This commit is contained in:
161
README.md
161
README.md
@@ -1,125 +1,144 @@
|
||||
# kind-k8s-develop — локальные кластеры Kubernetes (kind)
|
||||
|
||||
Образ **kind-k8s-tools** и **Makefile**: поднять kind на машине с **Docker** (или Podman + compose), сохранить **kubeconfig** в `clusters/<имя>/` на хосте. Python-скрипты и бинарники **kind/kubectl** лежат **внутри образа** — на хосте достаточно **Docker**, **make** и при необходимости **kubectl** для проверки API.
|
||||
Образ **kind-k8s-tools:local** и **Makefile** поднимают **веб-интерфейс** (FastAPI) на порту **6000** на хосте: через браузер создаёте и удаляете кластеры, смотрите статистику. **kubeconfig** сохраняется в `clusters/<имя>/`. На хосте достаточно **Docker** (или Podman) и **make**; **kind** и **kubectl** — внутри контейнера.
|
||||
|
||||
**Автор:** Сергей Антропов — [devops.org.ru](https://devops.org.ru)
|
||||
|
||||
## Зачем это нужно
|
||||
|
||||
- Быстро получить Kubernetes без облака (интеграционные тесты, проверка манифестов, обучение).
|
||||
- Версия кластера и число worker-нод задаются **интерактивно** при создании.
|
||||
- Артефакты на хосте: `clusters/<имя>/` в этом каталоге — удобно указать путь к `kubeconfig` в приложении или в `kubectl`.
|
||||
- Быстро получить Kubernetes без облака (интеграционные тесты, манифесты, обучение).
|
||||
- Версия кластера и число worker-нод задаются **в веб-UI** (или при необходимости скриптами/API).
|
||||
- Количество кластеров **не ограничено** кодом (ограничения — ресурсы хоста и Docker).
|
||||
- Артефакты на хосте: `clusters/<имя>/` — удобно указать путь к `kubeconfig` в приложении или в `kubectl`.
|
||||
|
||||
## Требования на хосте (основной сценарий)
|
||||
## Требования на хосте
|
||||
|
||||
| Компонент | Назначение |
|
||||
|-----------|------------|
|
||||
| **Docker** + **Compose v2** | Сборка образа и запуск (`docker compose`) |
|
||||
| **make** | Цели `create`, `delete`, `list`, … |
|
||||
| **kubectl** (опционально) | Проверка кластера с хоста после создания |
|
||||
| **Docker** + **Compose v2** (или **Podman** + compose) | Сборка образа и запуск веб-сервиса |
|
||||
| **make** | `make docker up` / `make podman up` и вспомогательные цели |
|
||||
| **kubectl** (опционально) | Проверка API с хоста: `kubectl --kubeconfig=clusters/<имя>/kubeconfig get nodes` |
|
||||
|
||||
**На хост не ставятся:** Python, kind, curl для kind — всё уже в образе `kind-k8s-tools`.
|
||||
**На хост не ставятся:** Python, kind — всё в образе.
|
||||
|
||||
Смонтированы только **сокет** Docker/Podman и каталог **`./clusters`** → в контейнере `/work/clusters`.
|
||||
Смонтированы **сокет** Docker/Podman и каталог **`./clusters`** → в контейнере `/work/clusters`.
|
||||
|
||||
После `make create` kubeconfig **патчится** на `https://127.0.0.1:<порт>` (apiserver с хоста), см. `kubeconfig_patch.py`.
|
||||
После создания кластера из UI kubeconfig **патчится** на `https://127.0.0.1:<порт>` для доступа с хоста, см. `kubeconfig_patch.py`.
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
```bash
|
||||
cd kind-k8s-develop
|
||||
make setup # опционально: интерактивно заполнить .env
|
||||
make check-docker # опционально: проверить docker compose
|
||||
make create # интерактивно: имя, версия образа нод, workers
|
||||
kubectl --kubeconfig="$(pwd)/clusters/<имя>/kubeconfig" get nodes # kubectl с хоста, если установлен
|
||||
make delete
|
||||
make setup # опционально: интерактивно .env (скрипт в scripts/; Enter — дефолты как в compose; нужен python3)
|
||||
make docker check-docker # или: make podman check-docker
|
||||
make docker up # или: make podman up
|
||||
# Браузер: http://127.0.0.1:6000 (порт: KIND_K8S_WEB_PORT в .env)
|
||||
```
|
||||
|
||||
Из родительского каталога: `make -C kind-k8s-develop create`.
|
||||
Из родительского каталога: `make -C kind-k8s-develop docker up`.
|
||||
|
||||
**Логи и остановка:** `make docker logs` / `make podman logs`, `make docker down` / `make podman down`.
|
||||
|
||||
Описание REST API и примеры JSON: **`app/docs/api_routes.md`**, интерактивно: **`/docs`** на том же порту.
|
||||
|
||||
### Разработка UI и API без пересборки образа
|
||||
|
||||
В **`docker-compose.yml`** каталог **`./app`** смонтирован в контейнер как **`/opt/kind-k8s/app`** — исправления в Python, шаблонах и `static/` на хосте сразу видны внутри сервиса.
|
||||
|
||||
По умолчанию (**`KIND_K8S_UVICORN_RELOAD=1`**) uvicorn запускается с **`--reload`** и перезапускает процесс при изменении `*.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 setup` | Интерактивно заполнить `.env` по `env.example` (`scripts/setup_env_interactive.py`, нужен `python3`) |
|
||||
| `make check-docker` | Проверить `docker` и `docker compose` |
|
||||
| `make compose-build` | Собрать образ `kind-k8s-tools` |
|
||||
| `make create` | Интерактивно создать кластер (**в контейнере**) |
|
||||
| `make delete` | Интерактивно удалить кластер и `clusters/<имя>/` |
|
||||
| `make list` | `kind get clusters` в контейнере |
|
||||
| `make status` | Статус узлов (`kubectl` в контейнере) |
|
||||
| `make status CLUSTER=имя` | Один кластер |
|
||||
| `make kubeconfig CLUSTER=имя` | Путь к `clusters/<имя>/kubeconfig` на хосте |
|
||||
| `make create-compose` / `make delete-compose` | То же, что `create` / `delete` (совместимость) |
|
||||
| `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` |
|
||||
| `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`, дефолты как в `docker-compose` |
|
||||
| `make clusters-dir` | Создать каталог `clusters/` |
|
||||
| `make docker …` / `make podman …` | Префикс **обязателен** для целей `up`, `down`, `logs`, `compose-build`, `check-docker` |
|
||||
|
||||
### Локальный запуск скриптов на хосте (без образа)
|
||||
|
||||
Если **kind**, **kubectl** и **Python** уже в PATH (kind: [установка](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)):
|
||||
|
||||
| Цель | Описание |
|
||||
|------|----------|
|
||||
| `make check-host` | Проверить docker, kind, kubectl, python3 |
|
||||
| `make create-host` | `app/create_cluster.py` на хосте |
|
||||
| `make delete-host` | `app/delete_cluster.py` на хосте |
|
||||
| `make status-host` | `app/cluster_status.py` на хосте |
|
||||
Цели `up`, `down`, `logs`, `compose-build` и `check-docker` **без** `docker`/`podman` в той же команде завершатся с подсказкой.
|
||||
|
||||
## Переменные окружения
|
||||
|
||||
Шаблон: **`env.example`**. Удобно выполнить **`make setup`** или скопировать в **`.env`** в корне этого каталога — Compose подхватывает `.env` при запуске отсюда.
|
||||
Файл **`.env`** в корне репозитория подхватывает Compose. Создать его можно командой **`make setup`** (опрос по списку в **`scripts/setup_env_interactive.py`**) или вручную.
|
||||
|
||||
| Переменная | Где используется | Назначение |
|
||||
|------------|------------------|------------|
|
||||
| **`KIND_VERSION`** | `docker-compose` (build-arg) | Версия бинарника kind в образе при `compose build` / `make compose-build`. |
|
||||
| **`CONTAINER_SOCKET`** | `docker-compose` (volume) | Сокет Docker/Podman на хосте (по умолчанию `/var/run/docker.sock`). |
|
||||
| **`KIND_K8S_PATCH_KUBECONFIG`** | контейнер (environment) | `1` / `true` — всегда патчить `server` в kubeconfig на `127.0.0.1:<порт>`. |
|
||||
| **`CONTAINER_CLI`** | контейнер (environment) | CLI к API контейнеров для `docker port` (по умолчанию `docker`). |
|
||||
| **`KIND_K8S_SKIP_VERSION_LIST`** | контейнер | `1` — не ходить в Docker Hub, версия только с клавиатуры. |
|
||||
| **`KIND_K8S_VERSION_LIST_DISPLAY`** | контейнер | Сколько строк списка версий показать (по умолчанию `50`, макс. `500`). |
|
||||
| **`KIND_K8S_HUB_TAGS_MAX_PAGES`** | контейнер | Лимит страниц API Hub при сборе тегов (по умолчанию `60`, макс. `200`). |
|
||||
| **`KIND_K8S_DEBUG`** | контейнер | `1` — уровень логов DEBUG для модулей kind-k8s. |
|
||||
| **`COMPOSE`** | только **Makefile** | Команда Compose, по умолчанию `docker compose`; Podman: `COMPOSE='podman compose'`. |
|
||||
| **`COMPOSE_BUILD_FLAGS`** | только **Makefile** | Аргументы к `compose build`, например `--platform linux/arm64` при `exec format error`. |
|
||||
| **`KIND_VERSION`** | build-arg | Версия бинарника kind при сборке образа |
|
||||
| **`KUBECTL_VERSION`** | build-arg | Версия kubectl в образе; в Dockerfile без build-arg — `stable.txt`; `make setup` предлагает закреплённый тег |
|
||||
| **`KIND_K8S_WEB_PORT`** | ports | Порт **на хосте** для веб-UI (в контейнере 6000) |
|
||||
| **`KIND_K8S_UVICORN_RELOAD`** | контейнер | `1` (по умолчанию) — hot-reload при правках в `./app`; `0` — без reload |
|
||||
| **`KIND_K8S_APP_TITLE`** | контейнер | Заголовок в OpenAPI и HTML |
|
||||
| **`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` |
|
||||
| **`KIND_K8S_SKIP_VERSION_LIST`** | контейнер | Не ходить в Docker Hub за тегами |
|
||||
| **`KIND_K8S_VERSION_LIST_DISPLAY`** | контейнер | Сколько тегов показывать в списке |
|
||||
| **`KIND_K8S_HUB_TAGS_MAX_PAGES`** | контейнер | Лимит страниц API Hub |
|
||||
| **`KIND_K8S_DEBUG`** | контейнер | Уровень DEBUG в логах |
|
||||
| **`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"
|
||||
COMPOSE='podman compose' make create
|
||||
make podman up
|
||||
```
|
||||
|
||||
## Файлы
|
||||
|
||||
| Путь | Назначение |
|
||||
|------|------------|
|
||||
| `Dockerfile` | Alpine, kind, kubectl, docker-cli; каталог `app/` копируется в `/opt/kind-k8s/app` |
|
||||
| `docker-compose.yml` | Том `./clusters`, сокет Docker/Podman |
|
||||
| `scripts/setup_env_interactive.py` | Интерактивное заполнение `.env` (цель `make setup`) |
|
||||
| `app/` | Все Python-модули и скрипты (`PYTHONPATH=/opt/kind-k8s/app` в образе) |
|
||||
| `app/kind_k8s_paths.py` | Корень данных: `KIND_K8S_WORKDIR` (в образе `/work`) или корень этого репозитория |
|
||||
| `app/create_cluster.py` | Диалог создания кластера |
|
||||
| `app/delete_cluster.py` | Удаление |
|
||||
| `app/cluster_status.py` | Узлы и meta |
|
||||
| `app/kubeconfig_patch.py` | Патч `server` в kubeconfig для доступа с хоста |
|
||||
| `app/kindest_node_tags.py` | Теги `kindest/node` (1.19+) с Docker Hub для выбора версии |
|
||||
| `Makefile` | Запуск веб-UI и вспомогательные цели |
|
||||
| `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/main.py` | FastAPI, дашборд |
|
||||
| `app/api/v1/` | REST API |
|
||||
| `app/core/` | Логика кластеров, задания, блокировки |
|
||||
| `app/docs/api_routes.md` | Описание маршрутов с примерами JSON |
|
||||
| `app/create_cluster.py`, `delete_cluster.py`, … | Используются веб-API и при ручном `compose run` |
|
||||
|
||||
При **`make create`** скрипт запрашивает версию Kubernetes: по умолчанию подгружается список тегов с Docker Hub (нужен интернет). Без сети или в air-gapped: **`KIND_K8S_SKIP_VERSION_LIST=1`** в **`.env`** — ввод версии только вручную.
|
||||
В UI и API список версий **kindest/node** по умолчанию тянется с Docker Hub (нужна сеть). В изолированной среде: **`KIND_K8S_SKIP_VERSION_LIST=1`** — версию вводят вручную.
|
||||
|
||||
## Где лежат данные на хосте
|
||||
|
||||
- `clusters/<имя>/kind-config.yaml`
|
||||
- `clusters/<имя>/kubeconfig`
|
||||
- `clusters/<имя>/meta.json` (в т.ч. `kubeconfig_patched_for_host`, `created_via_container`)
|
||||
- `clusters/<имя>/meta.json`
|
||||
|
||||
Содержимое `clusters/*/` не коммитится (см. `.gitignore`), каталог `clusters/` держит `.gitkeep`.
|
||||
|
||||
## Документация AppsTemplate (модуль Kubernetes)
|
||||
|
||||
Файл **`docs/k8s_runbook.md`** в этом репозитории — runbook эксплуатации модуля Kubernetes **веб-приложения** (кластеры в БД, health, RBAC, observability и т.д.). Раздел **§6.1** связывает локальный kind из этого каталога с импортом kubeconfig в приложение.
|
||||
Содержимое `clusters/*/` не коммитится; в репозитории есть `clusters/.gitkeep`.
|
||||
|
||||
## Ограничения
|
||||
|
||||
- Образ `kindest/node:v…` должен быть в реестре; опечатка версии → ошибка pull/kind.
|
||||
- На **Windows** без WSL удобнее WSL2 + Docker Desktop; пути ориентированы на Unix.
|
||||
- Для проверки с хоста нужен отдельно установленный **kubectl** (образ ставит kubectl только **внутри** контейнера).
|
||||
- Если при `make list` / `make create` в логе **`exec format error`** у `kind`, архитектура бинарника в образе не совпала с платформой контейнера. Пересоберите явно, например: `make compose-build COMPOSE_BUILD_FLAGS=--platform linux/arm64` или `linux/amd64` (как у вашего Docker).
|
||||
- Образ `kindest/node:v…` должен быть доступен для pull.
|
||||
- На **Windows** без WSL удобнее WSL2 + Docker Desktop.
|
||||
- Для проверки с хоста нужен отдельный **kubectl** (в образе kubectl только внутри контейнера).
|
||||
- При **`exec format error`** у kind пересоберите образ: `make docker compose-build COMPOSE_BUILD_FLAGS=--platform linux/arm64` (или `make podman …`, или `linux/amd64`).
|
||||
|
||||
Reference in New Issue
Block a user