# План доработки Fission Console — 2026-04-25 > Для нового чата. Масштаб: ~20 одновременных пользователей. > Текущая версия: `naeel/fission-console:v0.8.8` > Ветка: `feat/namespace-isolation` --- ## Контекст (кратко) - Go-бэкенд `console/main.go` + embedded UI `console/ui/index.html` - Каждый пользователь → отдельный K8s namespace `fission-` - Fission core один на кластер, namespace регистрируется через NSReconciler - Terraform provider: низкоуровневый (Environment + Package + Function + HTTPTrigger) - API: `https://fission.kube5s.ru/console/api`, тест: `X-Test-Sub: livetest@test.local` - SSH: `ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213` - sshfs: `/home/naeel/remote_dev/fission/` = `~/terra/fission/` на VM --- ## Задача 1: ResourceQuota + LimitRange на user namespace (ПРИОРИТЕТ 1) **Зачем**: без квот одна функция может съесть весь CPU/RAM кластера. **Где делать**: `console/main.go`, функция `ensureUserNamespace`. **Что добавить**: при создании namespace применять два объекта: ```yaml # ResourceQuota apiVersion: v1 kind: ResourceQuota metadata: name: user-quota namespace: fission- spec: hard: requests.cpu: "2" requests.memory: "2Gi" limits.cpu: "4" limits.memory: "4Gi" pods: "20" count/functions.fission.io: "20" count/packages.fission.io: "40" ``` ```yaml # LimitRange apiVersion: v1 kind: LimitRange metadata: name: user-limits namespace: fission- spec: limits: - type: Container default: cpu: "500m" memory: "256Mi" defaultRequest: cpu: "100m" memory: "64Mi" max: cpu: "2" memory: "1Gi" ``` **Детали реализации**: - Применять через `k8s dynamic client` или `core client` (уже есть в main.go) - Idempotent: если уже есть — не ошибаться, просто пропустить (patch или get+create) - Значения вынести в константы (или env vars) для удобной настройки **Файлы**: `console/main.go` **Тест**: создать нового пользователя, проверить `kubectl get resourcequota,limitrange -n fission-` --- ## Задача 2: NetworkPolicy на user namespace (ПРИОРИТЕТ 2) **Зачем**: без NetworkPolicy функции разных юзеров могут напрямую обращаться друг к другу по cluster IP. **Где делать**: `console/main.go`, функция `ensureUserNamespace` (вместе с задачей 1). **Что создать**: два правила: ```yaml # Deny all ingress from other namespaces (кроме fission core) apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-cross-tenant namespace: fission- spec: podSelector: {} policyTypes: - Ingress ingress: - from: - namespaceSelector: matchLabels: kubernetes.io/metadata.name: fission # fission core может - podSelector: {} # внутри namespace — OK ``` **Осторожно**: проверить что fission router/executor/fetcher namespace правильно лейблован. Если нет — добавить лейбл на namespace `fission` через kubectl. **Тест**: поднять функцию в namespace A, попробовать curl из пода namespace B — должен fail. --- ## Задача 3: fission_simple_function Terraform ресурс (ПРИОРИТЕТ 3) **Зачем**: сейчас юзер пишет 4 ресурса вместо одного. Это неудобно и error-prone. **Ветка**: `feat/simple-function-resource` (создана, код не написан) **Файл**: `terraform/provider/internal/resources/simple_function_resource.go` **Целевой синтаксис для пользователя:** ```hcl resource "fission_simple_function" "health" { name = "health" runtime = "nodejs" code_dir = "./code/health" url = "/ecom/health" methods = ["GET"] } ``` **Что провайдер делает внутри:** 1. Ищет существующий `fission_environment` для runtime → переиспользует или создаёт 2. Zip-архивирует `code_dir` → создаёт `fission_package` (с ESM wrap для nodejs) 3. Создаёт `fission_function` 4. Создаёт `fission_http_trigger` (если указан `url`) **Атрибуты ресурса:** ``` name string — имя функции runtime string — nodejs / python / go / ruby / perl / php code_dir string — путь к директории с кодом url string — HTTP route (опционально) methods []string — ["GET","POST"] (опционально, default GET) entrypoint string — имя точки входа (опционально, default "Handler") min_scale int — минимальный масштаб (опционально, default 0) max_scale int — максимальный масштаб (опционально, default 1) ttl int — TTL в секундах (опционально) ``` **Computed атрибуты:** ``` invoke_url string — полный URL для вызова status string — статус package (building / succeeded / failed) ``` **Особенности реализации:** - nodejs: ESM wrapper (`export default { Handler }`) — проверить формат как в Console - Go: нужен archive package (zip), не literal. BuildStatus polling. - Идемпотентность: Read → если уже есть все 3 ресурса, не пересоздавать - Delete: удалить trigger + function + package. Environment — только если unused. **Регистрация**: добавить в `terraform/provider/internal/provider/provider.go` в `Resources()` **Примеры**: обновить `examples/big-suite/` после реализации **Тест**: `terraform apply` → `terraform plan` должен показать "no changes" --- ## Задача 4: Улучшение поверхности ошибок (ПРИОРИТЕТ 4) **Зачем**: сейчас при провале specialization пользователь видит "timeout after 20s: function specialization likely failed" — не информативно. **Что делать:** ### 4.1 Package build status в API response При создании функции и при GET `/console/api/functions/:name` — тянуть и возвращать: ```json { "name": "myfunc", "status": "building", // или "ready" / "failed" "buildError": "compilation failed: undefined reference to..." } ``` `buildError` брать из `package.status.info` (Fission заполняет это поле). ### 4.2 Specialization error в invoke response Сейчас invoke возвращает timeout. Надо после timeout: 1. Проверить статус package → если `failed`, вернуть buildError 2. Проверить поды namespace → если CrashLoopBackOff, вернуть причину 3. Иначе — вернуть "specialization timeout, function pod not ready" ### 4.3 UI polling для build status После создания Go-функции (или любой с builder) — polling `/console/api/functions/:name` каждые 3s, показывать статус: - "Сборка..." → "Готово" / "Ошибка сборки: " **Файлы**: `console/main.go` (API), `console/ui/index.html` (UI polling) --- ## Задача 5: Cleanup и housekeeping (ПРИОРИТЕТ 5) **Что сделать:** ### 5.1 Reaper для пустых namespace Если namespace не имеет ни одной функции и не обращался больше N дней → удалить namespace + все ресурсы. Параметр: `NAMESPACE_TTL_DAYS` (env var, default 30). ### 5.2 Orphan package cleanup При удалении функции — проверить все packages namespace, удалить те, на которые нет ни одной функции. Сейчас `cleanupEnvironmentIfUnused` есть, нужен аналог для packages. ### 5.3 Soft limit на функции на пользователя `MAX_FUNCTIONS_PER_USER` (env var). При превышении → HTTP 429 с сообщением. Защита от случайного создания 1000 функций в loop. --- ## Порядок выполнения (рекомендованный) ``` 1. Задача 1 (ResourceQuota + LimitRange) — ~2-3 часа, высокий риск если не сделать 2. Задача 2 (NetworkPolicy) — ~1-2 часа, вместе с задачей 1 3. Задача 3 (fission_simple_function) — ~1-2 дня, основная фича 4. Задача 4 (ошибки) — ~4-6 часов, UX improvement 5. Задача 5 (cleanup) — ~3-4 часа, housekeeping ``` --- ## Команды для нового чата ```bash # Текущий образ naeel/fission-console:v0.8.8 # Сборка нового образа (ОБЯЗАТЕЛЬНО сначала поменять тег в deploy/console.yaml!) ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 \ 'cd ~/terra/fission && docker build -t naeel/fission-console:v0.8.9 -f console/Dockerfile console/ && docker push naeel/fission-console:v0.8.9' # Deploy ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 \ 'kubectl set image deployment/fission-console fission-console=naeel/fission-console:v0.8.9 -n fission' # Тест после деплоя ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 \ 'bash ~/terra/fission/tests_v2.sh 2>&1 | tail -5' # Проверка quota (после задачи 1) ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 \ 'kubectl get resourcequota,limitrange -n fission-c3fce59430e41b0f' ``` --- ## Файлы проекта (ключевые) | Файл | Назначение | |------|-----------| | `console/main.go` | Основная логика бэкенда | | `console/ui/index.html` | Embedded UI | | `console/deploy/console.yaml` | K8s deployment (тег образа) | | `console/deploy/rbac/console-ns-manager.yaml` | RBAC для fission-console SA | | `terraform/provider/internal/resources/` | Terraform ресурсы | | `terraform/provider/internal/provider/provider.go` | Регистрация ресурсов | | `tests_v2.sh` | Регресс-тесты (73 блока, все PASS) | | `doc/thinking/2026-04-25-ai-opinions.md` | Мнения AI моделей |