Files
fission-console/doc/thinking/2026-04-25-plan.md
T

272 lines
11 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.
# План доработки 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-<hash(sub)>`
- 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-<hash>
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-<hash>
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-<hash>`
---
## Задача 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-<hash>
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, показывать статус:
- "Сборка..." → "Готово" / "Ошибка сборки: <text>"
**Файлы**: `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 моделей |