Commit Graph
1956 Commits
Author SHA1 Message Date
“Naeel” f5b57173f5 doc(audit): mark stuck-failed as CLOSED after 919e8439 (RunReconciler + error propagation)
Updated FORENSIC_ARCHITECTURE_AUDIT.md to reflect the fix from commit 919e8439:

Status table:
- 'Stuck-failed namespace без auto-recovery':  ОТКРЫТ →  ЗАКРЫТ (919e8439)
- 'No Explicit State Machine':  ОТКРЫТ → ⚠️ СМЯГЧЕНО (stuck-failed закрыт;
  явная state machine остаётся в backlog)

Sections updated:
- §1.4: полное описание что было (void-функции, мёртвый reconciler) и что
  сделано (error propagation chain, end-to-end flow retry)
- Fragile Components: Stuck Failed Phase — вычеркнуто как закрытое
- Risky Decisions table: No Explicit State Machine → частично закрыто
- Lifecycle Management: добавлено что auto-recovery работает через RunReconciler
- Operational Burden: убрано упоминание stuck-failed как активной проблемы
- Maintainability/Production-Grade: обновлены под текущее состояние
- §2 Stuck Failed Accumulation:  ЗАКРЫТ
- §3 P1 Reconcile-очередь:  ЗАКРЫТ
- §5 Sharded mutex вердикт: убрано упоминание stuck-failed
2026-05-18 11:32:13 +04:00
“Naeel” 919e84396c fix(reconciler): propagate SA/executor errors to NamespaceManager so failed NSes are retried
Problem
-------
The namespace reconciler (RunReconciler, added previously) retries namespaces
in NamespacePhaseFailed every 30s by calling DispatchResync. But the phase
could never actually reach NamespacePhaseFailed for the executor component
because the executor's NamespaceSubscriber always returned nil — swallowing
any SA-provisioning or informer-init errors. The reconciler was dead code for
the executor path.

Root cause chain
----------------
1. setupSAAndRoleBindings() — void, errors only logged internally.
2. EnsureNamespaceSA()      — void, just called setupSAAndRoleBindings.
3. registerNamespace()      — void, errors from both functions lost.
4. Executor AddFunc/ResyncFunc — always returned nil to dispatch().
5. dispatch() marks parts Active unconditionally   → NamespacePhaseFailed
   is never triggered for executor   → RunReconciler never fires for executor.

Consequence: if EnsureNamespaceSA failed (transient k8s 503, RBAC webhook
timeout, etc.) the namespace appeared Active in the manager but the fetcher
ServiceAccount was missing. Pool pods would CrashLoopBackOff on every call
to that namespace until a full process restart.

Changes
-------
pkg/utils/serviceaccount.go
  - setupSAAndRoleBindings: void → error. Returns the first k8s API error
    so callers can decide whether to retry.
  - runSACheck: ignores the error with _ = (same behaviour as before, it's
    a periodic background loop that already logs internally).
  - EnsureNamespaceSA: void → error, propagates setupSAAndRoleBindings.
    Updated godoc to explain the retry contract.

pkg/executor/multitenant/ns_watcher.go
  - registerNamespace: void → error.
    * EnsureNamespaceSA error → wrapped as 'EnsureNamespaceSA: ...' and returned.
    * registerExecutorTypes error → wrapped as 'registerExecutorTypes: ...' and returned.
    * Success log line only emitted when both succeed.
  - Added 'fmt' import for error wrapping.

pkg/executor/multitenant/namespace_subscriber.go
  - AddFunc:    return registerNamespace(...) instead of ignoring its error.
  - ResyncFunc: same — plus a comment explaining why it is safe to call
    registerNamespace again (SA creation is idempotent, executor-type
    AddNamespace guards against duplicate informer creation).

pkg/utils/namespace_manager.go
  - RunReconciler interface signature: added *zap.Logger parameter.
    Callers pass the component logger so retries are visible in prod logs.
  - RunReconciler implementation:
    * Accepts logger; falls back to zap.NewNop() if nil.
    * Skips the tick entirely when no failed namespaces are found (no log spam).
    * Logs 'retrying failed namespaces' with count + list when found.
    * Logs per-namespace 'dispatching resync'.
    * Logs 'resync succeeded' or 'resync still failing, will retry' with error.
  - RunManagedNamespaceWatcher: passes logger to RunReconciler.

End-to-end flow after this fix
-------------------------------
1. EnsureNamespaceSA fails (k8s 503).
2. registerNamespace returns error.
3. Executor AddFunc returns error.
4. dispatch() calls MarkPartFailed("executor") → deriveNamespacePhase →
   NamespacePhaseFailed.
5. RunReconciler tick (30s) finds the namespace → DispatchResync →
   registerNamespace called again → EnsureNamespaceSA (idempotent) →
   if API recovered: success → MarkPartActive → NamespacePhaseActive.
6. Log line 'namespace reconciler: resync succeeded' confirms recovery.

Backward compatibility
----------------------
- NamespaceManager interface: RunReconciler gained a *zap.Logger param.
  There is exactly one implementation (inMemoryNamespaceManager) and one
  call site (RunManagedNamespaceWatcher). No external mocks.
- EnsureNamespaceSA: callers outside this codebase (if any) that ignore
  the error will still compile (Go allows ignoring return values).
- All 26 affected tests pass: go test ./pkg/utils/... ./pkg/executor/...
  ./pkg/buildermgr/... ./pkg/router/...
2026-05-18 11:10:46 +04:00
“Naeel” 28c45e65aa doc: update forensic audit to reflect namespace lifecycle hardening (2026-05-18) 2026-05-18 09:13:35 +04:00
“Naeel” 695bfb74d4 doc: impl notes for namespace lifecycle hardening (2026-05-18) 2026-05-18 09:08:35 +04:00
“Naeel” 4eedf95f5c fix(namespace): executor/router/buildermgr RemoveNamespace + per-NS informer lifecycle
- Add RemoveNamespace(ctx, ns) to executortype.ExecutorType interface
- Implement RemoveNamespace in poolmgr, newdeploy, container executor types
- Add per-namespace context cancellation (nsCancels map) in all three types so
  informer factories are stopped when namespace is removed (fixes goroutine leak)
- Add PoolPodController.RemoveNamespace to clear envLister/podLister maps
- Add deregisterNamespace() in executor multitenant subscriber
- Switch executor/router/buildermgr watcher strategy from TrackOnly to DispatchRemove
  so RemoveFunc is called when fission.io/managed label is removed
- Add RemoveFunc to executor/router/buildermgr namespace subscribers
- Add RemoveNamespace to environmentWatcher and packageWatcher with per-NS cancel
- Add RemoveNamespace to HTTPTriggerSet: cancels informers, removes from maps, calls syncTriggers
- Fix ns_watcher_test.go fakeExecutorType to implement new RemoveNamespace method

Fixes:
- Executor dedup gap: re-added namespace was silently skipped (envLister/deplLister still present)
- Goroutine/FD leak: old informer factories ran forever after namespace removal
- Router stale routes: HTTPTriggers for removed namespace stayed in routing table
2026-05-18 09:04:13 +04:00
“Naeel” 3b93c5dc8b fix(namespace): harden lifecycle — RemoveNamespace, parallel dispatch, reconciler
- DefaultNSResolver.RemoveNamespace(): removes NS from global map on label removal
  so Snapshot() and idleObjectReaper stop iterating deleted namespaces.
  Fixes class of dirty-state bugs when NS name is reused by new tenant.

- HandleWatcherNamespaceRemoval: call RemoveNamespace on both TrackOnly and
  DispatchRemove strategies — global resolver cleanup is always required.

- dispatch(): parallel subscriber execution via goroutine per subscriber +
  sync.WaitGroup. Reduces onboarding latency from O(N_subscribers × API_latency)
  to O(max(API_latency)). Safe: MarkPart* are internally mutex-protected.

- inMemoryNamespaceManager.RunReconciler(): 30s ticker scans for
  NamespacePhaseFailed records and retries via DispatchResync. Started
  automatically by RunManagedNamespaceWatcher. Fixes permanent stuck-failed
  state caused by transient k8s API errors.

Analysis source: FORENSIC_ARCHITECTURE_AUDIT.md §Deep Risk Analysis
2026-05-18 08:45:31 +04:00
“Naeel” 4c82285863 doc: add console integration section to porting guide 2026-05-15 08:04:46 +04:00
“Naeel” 728cc351b5 doc: add multitenant porting guide for upstream upgrade 2026-05-15 07:49:47 +04:00
“Naeel” 5d52c9ba94 test: add integration test for NSWatcher with fake Kubernetes client
TestStartManagedNamespaceWatcherIntegration проверяет полный маршрут
горячей регистрации namespace без real cluster:

1. RunManagedNamespaceWatcher запускается с k8sfake.NewSimpleClientset()
2. В fake client создаётся Namespace с label fission.io/managed=true
3. Kubernetes informer детектирует событие (без polling, через Watch)
4. SubscriberFuncs.OnNamespaceAdd вызывается
5. NamespaceManager содержит запись со статусом Active

Тест доказывает, что вся цепочка
  fake k8s event → informer → AddFunc → subscriber → manager
работает корректно без rolling restart процесса.

Также добавлен import metav1 в test file (требовался для CreateOptions).
2026-05-15 07:11:48 +04:00
“Naeel” 5f0ab79f00 doc: add multitenant architecture summary (2026-05-15)
Единый сводный документ, описывающий полную архитектуру мультитенантного Fission.
Заменяет необходимость читать 50+ пошаговых thinking-файлов.

Содержит:
- Причина и концепция решения
- Архитектурная карта изменений (ASCII diagram)
- Таблица ключевых файлов с ролями
- Инженерные решения: Snapshot API, NamespaceManager event bus,
  EnsureNamespaceSA, buildermgr dedup bug, router nil guard
- RBAC: что и почему (включая нетривиальные events:create и LSAR)
- Backward compatibility guarantees
- Описание test scenario (Layer 1, PASS=5)
- Порядок деплоя нового форка
- Направления дальнейшей работы
2026-05-15 07:08:32 +04:00
“Naeel” 4addf254cb chore: remove superseded executor-ns-watcher-rbac.yaml
Файл deploy/executor-ns-watcher-rbac.yaml был создан на раннем этапе работы
над мультитенантностью. Он содержал только partial RBAC (только executor,
без router и без SA-provisioner прав).

Файл полностью покрыт deploy/multitenant/rbac.yaml который содержит:
- fission-executor-ns-watcher: list/watch namespaces
- fission-router-ns-watcher: list/watch namespaces
- fission-executor-sa-provisioner: create SA/Role/RoleBinding в user NS

Старый файл нигде не referenced — ни в charts, ни в коде.
2026-05-15 07:06:58 +04:00
“Naeel” b5f8a9bf0e doc: add multi-tenant quick reference card
Краткий справочник команд и концепций мультитенантного Fission.
Содержит: жизненный цикл namespace, CLI команды, схему RBAC,
структуру URL функций, типичные сценарии использования.
2026-05-15 06:59:19 +04:00
“Naeel” b2efefd75a doc: add multi-tenant Fission Console API guide
Полное руководство по REST API мультитенантного Fission Console.
Описывает все эндпоинты: создание namespace (tenant), деплой функций,
управление environment, триггеры, пакеты.
Актуально для нашего форка с мультитенантностью.
2026-05-15 06:59:14 +04:00
“Naeel” 5988ced1e2 chore: add GitHub Copilot project rules
Добавлены файлы правил для GitHub Copilot:
- .github/copilot-instructions.md — краткие правила поведения ИИ в проекте:
  отвечать кратко, не трогать рабочий код без явного указания, rsync на ВМ
  после каждого изменения, git только локально.
- .github/pravila.md — расширенные правила проекта: порядок работы с SSH,
  запреты на групповое удаление, правила docker build и деплоя.
2026-05-15 06:59:07 +04:00
“Naeel” e3928e1d4d chore: ignore *.token files
Token files (mgmt.token и подобные) не должны попадать в репозиторий.
Добавлено правило *.token в .gitignore.
2026-05-15 06:59:00 +04:00
Naeel 63ce6ea135 layer1: close namespace manager step1 2026-04-26 16:27:53 +03:00
Naeel 7b6ff84188 layer1: harden namespace watcher logging path 2026-04-26 16:27:20 +03:00
Naeel 55d0b5a9e7 layer1: log namespace watcher startup summary 2026-04-26 16:24:29 +03:00
Naeel 813617ffd1 layer1: log watcher namespace transitions 2026-04-26 11:52:06 +03:00
Naeel 7d7fe561a8 layer1: log namespace summary active flag 2026-04-26 11:51:03 +03:00
Naeel fed69da335 layer1: add namespace summary active helper 2026-04-26 11:46:47 +03:00
Naeel 9f0e911b9d layer1: stabilize namespace summary contract 2026-04-26 11:46:15 +03:00
Naeel f4a3bffc6b layer1: test namespace manager summary logging 2026-04-26 11:45:13 +03:00
Naeel 90924cdec7 layer1: checkpoint namespace manager runtime series 2026-04-26 11:44:36 +03:00
Naeel 6e037a506d layer1: add default watcher config helper 2026-04-26 11:03:39 +03:00
Naeel d24605a8b8 layer1: fix managed watcher config wiring 2026-04-26 11:02:54 +03:00
Naeel d2ff55f9e0 layer1: add managed watcher config 2026-04-26 11:02:09 +03:00
Naeel b9236698f3 layer1: run managed namespace watchers 2026-04-26 11:01:05 +03:00
Naeel 073f2c1504 layer1: add live namespace counts 2026-04-26 10:59:39 +03:00
Naeel b93e720e12 layer1: add namespace source counts 2026-04-26 10:59:01 +03:00
Naeel f16aa030db layer1: log namespace manager summary 2026-04-26 10:57:29 +03:00
Naeel 5c481b7293 layer1: add namespace manager summary 2026-04-26 10:55:56 +03:00
Naeel 67db8d71f1 layer1: fix watcher preparation imports 2026-04-26 10:54:51 +03:00
Naeel 2bbed95c2a layer1: prepare managed namespace watchers 2026-04-26 10:54:24 +03:00
Naeel a1517ba4b2 layer1: share managed namespace watcher startup 2026-04-26 10:51:31 +03:00
Naeel 49be1db3a0 layer1: share namespace watcher event handlers 2026-04-26 10:50:28 +03:00
Naeel c3b161da83 layer1: share update removal policy 2026-04-26 10:49:26 +03:00
Naeel 0755319fac layer1: formalize namespace removal strategy 2026-04-26 10:48:42 +03:00
Naeel 340b9cae84 layer1: centralize namespace watcher handlers 2026-04-26 10:47:12 +03:00
Naeel 4cd4bc9507 layer1: share namespace watcher lifecycle helpers 2026-04-26 10:45:03 +03:00
Naeel 0e08664ef6 layer1: share watcher namespace manager bootstrap 2026-04-26 10:41:14 +03:00
Naeel d7497dcd34 layer1: remove old namespace watcher helpers 2026-04-26 10:40:36 +03:00
Naeel 447133d5b2 layer1: track namespace removals in manager 2026-04-26 10:39:59 +03:00
Naeel b6f3640bbe layer1: add namespace tombstone helper step 34 2026-04-26 10:39:11 +03:00
Naeel d09bee3431 layer1: add namespace remove dispatch step 33 2026-04-26 10:36:48 +03:00
Naeel 488157963a layer1: bootstrap executor namespace manager 2026-04-26 10:35:50 +03:00
Naeel 804bc533db layer1: bootstrap router namespace manager 2026-04-26 10:35:29 +03:00
Naeel 65837610a1 layer1: bootstrap builder namespace manager 2026-04-26 10:35:09 +03:00
Naeel dd7470922c layer1: hook executor watcher to namespace manager 2026-04-26 10:34:34 +03:00
Naeel 0135a93a30 layer1: hook router watcher to namespace manager 2026-04-26 10:34:04 +03:00