Files
fission-src/doc/thinking/2026-04-26-layer1-pass-detailed.md
T

10 KiB
Raw Blame History

2026-04-26 - Layer1 multi-tenant NSWatcher: полный разбор до 5/5 PASS

Цель

Довести test_layer1.sh до PASS=5 FAIL=0 для сценария:

  1. создаётся новый namespace
  2. namespace получает label fission.io/managed=true
  3. Fission без рестарта подхватывает namespace
  4. в namespace создаются Environment, Function, HTTPTrigger
  5. функция успешно вызывается через router

Ключевое требование: всё должно происходить без rolling restart Fission-компонентов.

Исходный симптом

Первый устойчивый симптом был таким:

  • test_layer1.sh стабильно доходил до 4/5
  • шаг вызова функции падал
  • в user namespace наблюдалось:
    • FailedCreate
    • serviceaccount "fission-fetcher" not found

Это означало, что poolmgr deployment для environment уже создаётся, но pod не может стартовать без fission-fetcher ServiceAccount.

Что уже было исправлено до RBAC-этапа

Кодовая часть hot-registration была уже внедрена ранее:

  • pkg/utils/serviceaccount.go
    • добавлена EnsureNamespaceSA(...)
  • pkg/executor/multitenant/ns_watcher.go
    • при регистрации нового namespace вызывается EnsureNamespaceSA(...)
  • образ naeel/fission-bundle:v1.22.0-multi-ns-8 уже был собран и задеплоен

То есть логика в коде уже существовала; сбой был не в отсутствии вызова, а в невозможности выполнить его успешно в кластере.

Диагностика 1: executor не может создать ServiceAccount/Role/RoleBinding

Была проведена проверка прав service account fission-executor.

Подтверждено:

  • код EnsureNamespaceSA вызывается
  • ns_watcher регистрирует namespace
  • executor не имеет достаточных RBAC-прав для provisioning ресурсов в новом namespace

Первый явный пробел:

  • отсутствовали права на:
    • serviceaccounts
    • roles
    • rolebindings

После начального RBAC fix было видно, что ServiceAccount/fission-fetcher уже создаётся, но этого оказалось недостаточно.

Диагностика 2: initial RBAC fix оказался неполным

После расширения прав на serviceaccounts/roles/rolebindings тест перестал падать на отсутствии SA, но при детальной диагностике выяснилось, что EnsureNamespaceSA всё ещё не может полностью создать Role для fetcher.

Ключевой лог executor:

error while creating role for sa fission-fetcher in namespace diag-ns-82702
... is attempting to grant RBAC permissions not currently held:
{APIGroups:[""], Resources:["events"], Verbs:["create"]}

И дополнительный лог перед этим:

localsubjectaccessreviews.authorization.k8s.io is forbidden

Что это означает

Функция setupSAAndRoleBindings() делает две важные вещи:

  1. пытается проверить уже существующие права через LocalSubjectAccessReview
  2. если прав нет, создаёт Role с нужными permission-ами

Следовательно executor должен иметь не только право создавать Role/RoleBinding, но и:

  • authorization.k8s.io/localsubjectaccessreviews:create
  • все permission-ы, которые он пытается делегировать через создаваемую Role

В нашем случае fetcher получает право:

  • events:create

По правилам Kubernetes нельзя создать Role, выдающую право, которого нет у самого вызывающего субъекта. Поэтому executor должен был сам иметь events:create.

Реальный root cause на этом этапе

fission-executor не имел:

  • events.create
  • localsubjectaccessreviews.create

Из-за этого:

  • ServiceAccount создавался
  • но Role и RoleBinding создавались не полностью или не создавались вовсе
  • downstream specialization ломалась

Исправление 1: полный executor RBAC для dynamic SA provisioning

В deploy/multitenant/rbac.yaml был добавлен и затем расширен ClusterRole:

  • fission-executor-sa-provisioner

Итоговый набор прав для него:

  • core:
    • serviceaccounts: get, list, watch, create, update, patch
    • events: create
  • authorization.k8s.io:
    • localsubjectaccessreviews: create
  • rbac.authorization.k8s.io:
    • roles: get, list, watch, create, update, patch
    • rolebindings: get, list, watch, create, update, patch

После применения этого манифеста было подтверждено:

  • kubectl auth can-i create events --as=system:serviceaccount:fission:fission-executor -> yes
  • kubectl auth can-i create localsubjectaccessreviews.authorization.k8s.io --as=system:serviceaccount:fission:fission-executor -> yes

И в новом test namespace автоматически появлялись:

  • ServiceAccount/fission-fetcher
  • Role/fission-fetcher-role-*
  • RoleBinding/fission-fetcher-rolebinding-*

Изменение симптома после executor-fix

После полного executor RBAC fix шаг 5 перестал падать с 500 timeout от executor.

Новый симптом:

  • постоянный HTTP 404
  • router не видел route/function в новом namespace

Это был важный индикатор того, что executor-path уже работает лучше, а оставшаяся проблема находится в router-path.

Диагностика 3: router NSWatcher не мог watch/list namespaces

Лог router показал прямую ошибку:

failed to list *v1.Namespace: namespaces is forbidden:
User "system:serviceaccount:fission:fission-router" cannot list resource
"namespaces" at the cluster scope

При этом код router уже содержал dynamic namespace watcher:

  • pkg/router/ns_watcher.go

То есть логика была, но RBAC для fission-router отсутствовал.

Реальный root cause на этом этапе

fission-router не имел cluster-scope прав:

  • namespaces:list
  • namespaces:watch

Из-за этого:

  • router не подхватывал новые labeled namespaces
  • HTTPTriggerSet.AddNamespace(...) не вызывался
  • HTTP trigger не попадал в router runtime map
  • вызов функции возвращал 404

Исправление 2: router RBAC для NSWatcher

В тот же deploy/multitenant/rbac.yaml добавлены:

  • ClusterRole/fission-router-ns-watcher
  • ClusterRoleBinding/fission-router-ns-watcher

С правами:

  • core namespaces: list, watch

После применения подтверждено:

  • kubectl auth can-i list namespaces --as=system:serviceaccount:fission:fission-router -> yes
  • kubectl auth can-i watch namespaces --as=system:serviceaccount:fission:fission-router -> yes

Финальная проверка

После обоих RBAC fixes повторный запуск test_layer1.sh дал:

ИТОГ: PASS=5  FAIL=0

На шаге 5 функция успешно ответила:

HTTP 200 - hello from layer1

Что именно оказалось правдой по итогу

Итоговая проблема состояла из двух последовательных RBAC-дырок:

  1. executor не мог полностью provision-ить fission-fetcher в динамическом namespace
  2. router не мог подхватить новый namespace из-за отсутствия namespace watch/list

То есть код hot-registration в целом был правильный, но runtime contract в Kubernetes RBAC был реализован не полностью.

Итоговые изменения

Код и манифесты

  • deploy/multitenant/rbac.yaml
    • executor namespace watch
    • executor SA provisioning RBAC
    • router namespace watch RBAC

Документация

  • doc/progress.md
  • doc/thinking/2026-04-26-rbac-fix.md
  • doc/thinking/2026-04-26-layer1-pass-detailed.md

Коммиты по ходу исправления

  • 161de70 - multi-tenant: EnsureNamespaceSA + ns_watcher SA provisioning (v8)
  • 8ccc9fb - первый RBAC commit
  • f617913 - полный executor RBAC fix для fetcher role provisioning
  • 7faaa9d - router namespace watch RBAC

Практический вывод

Для hot namespace onboarding в Fission недостаточно просто добавить informer-ы в коде.

Нужно обеспечить весь runtime contract:

  • executor видит namespace
  • executor может provision-ить service accounts и RBAC в tenant namespace
  • executor может делегировать все требуемые permission-ы
  • router видит namespace и подписывается на triggers/functions в нём

Если хотя бы одно из этих звеньев отсутствует, поведение выглядит как "код вроде есть, но dynamic namespace не работает".