docs: lifecycle test — 44/44 PASS; 2 бага оператора задокументированы в errors/log.md + progress.md
Баги: 1. memory_mb через PUT не обновляет k8s Deployment Resources → controllers/service_controller.go:~241 2. нет self-healing при ручном удалении Deployment → нет RequeueAfter / cross-namespace watch
This commit is contained in:
@@ -4,6 +4,85 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 2026-03-21 — БАГ: memory_mb через PUT не применяется в k8s Deployment (НЕ ИСПРАВЛЕН)
|
||||||
|
|
||||||
|
### Симптом
|
||||||
|
|
||||||
|
```
|
||||||
|
PUT /v1/namespaces/sless-xxx/services/my-svc
|
||||||
|
{ "memory_mb": 256, ... }
|
||||||
|
→ HTTP 200 OK
|
||||||
|
|
||||||
|
kubectl get deployment my-svc -n sless-fn-xxx
|
||||||
|
containers[0].resources.limits.memory: 128Mi ← было 128, осталось 128
|
||||||
|
```
|
||||||
|
|
||||||
|
### Причина
|
||||||
|
|
||||||
|
`controllers/service_controller.go:ensureServiceDeployment` при UPDATE существующего Deployment обновляет только два поля:
|
||||||
|
```go
|
||||||
|
existing.Spec.Template.Spec.Containers[0].Image = svc.Status.ImageRef
|
||||||
|
existing.Spec.Template.Spec.Containers[0].Env = desired.Spec.Template.Spec.Containers[0].Env
|
||||||
|
// Resources (memory limit) НЕ обновляется!
|
||||||
|
```
|
||||||
|
`desired` Deployment строится с правильным `memory_mb`, но в `existing` он не копируется.
|
||||||
|
|
||||||
|
### Фикс (не применён)
|
||||||
|
|
||||||
|
```go
|
||||||
|
// В ensureServiceDeployment, блок else (UPDATE):
|
||||||
|
existing.Spec.Template.Spec.Containers[0].Image = svc.Status.ImageRef
|
||||||
|
existing.Spec.Template.Spec.Containers[0].Env = desired.Spec.Template.Spec.Containers[0].Env
|
||||||
|
existing.Spec.Template.Spec.Containers[0].Resources = desired.Spec.Template.Spec.Containers[0].Resources // ← ДОБАВИТЬ
|
||||||
|
existing.Spec.Template.Spec.ImagePullSecrets = desired.Spec.Template.Spec.ImagePullSecrets
|
||||||
|
```
|
||||||
|
|
||||||
|
### Файл
|
||||||
|
|
||||||
|
`controllers/service_controller.go` ~ строка 241
|
||||||
|
|
||||||
|
### Обнаружен
|
||||||
|
|
||||||
|
`operator_lifecycle_test.sh`, тест 2.13
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2026-03-21 — БАГ: нет self-healing — ручное удаление Deployment не восстанавливается (НЕ ИСПРАВЛЕН)
|
||||||
|
|
||||||
|
### Симптом
|
||||||
|
|
||||||
|
```
|
||||||
|
kubectl delete deployment my-svc -n sless-fn-sless-xxx
|
||||||
|
# Deployment исчез.
|
||||||
|
# Ждём 90s — контроллер не пересоздаёт.
|
||||||
|
# GET /fn/sless-xxx/my-svc → 502 (pod отсутствует, CRD=Ready)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Причина
|
||||||
|
|
||||||
|
`ServiceReconciler` реагирует только на изменения объектов типа `Service` (sless CRD) в namespace `sless`.
|
||||||
|
Deployment живёт в `sless-fn-sless-xxx` — другой namespace. controller-runtime не допускает `Owns()` для cross-namespace ресурсов.
|
||||||
|
`ensureServiceDeployment` вызывается только когда `phase=Ready` И пришёл reconcile event (=изменение CRD). Просто удалённый Deployment event не генерирует.
|
||||||
|
|
||||||
|
### Фикс (вариант)
|
||||||
|
|
||||||
|
Добавить `RequeueAfter: 60s` в `ensureServiceDeployment` — тогда контроллер будет периодически проверять и пересоздавать:
|
||||||
|
```go
|
||||||
|
// В конце ensureServiceDeployment:
|
||||||
|
return ctrl.Result{RequeueAfter: 60 * time.Second}, nil
|
||||||
|
```
|
||||||
|
Или использовать `Watches()` с cross-namespace mapper (сложнее).
|
||||||
|
|
||||||
|
### Файл
|
||||||
|
|
||||||
|
`controllers/service_controller.go` ~ строка 340
|
||||||
|
|
||||||
|
### Обнаружен
|
||||||
|
|
||||||
|
`operator_lifecycle_test.sh`, тест 3.2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 2026-03-21 — Баг: DELETE несуществующего ресурса → HTTP 204 вместо 404
|
## 2026-03-21 — Баг: DELETE несуществующего ресурса → HTTP 204 вместо 404
|
||||||
|
|
||||||
### Симптом
|
### Симптом
|
||||||
|
|||||||
+40
-3
@@ -1,6 +1,43 @@
|
|||||||
# Прогресс разработки
|
# Прогресс разработки
|
||||||
|
|
||||||
Последнее обновление: 2026-03-21 (operator v0.1.48 — timeout_sec: 0 = нет лимита; валидация 1–900; Terraform state = null при отсутствии лимита)
|
Последнее обновление: 2026-03-21 (operator_lifecycle_test.sh — 44/44 PASS; 2 бага оператора найдены)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2026-03-21 — Сессия 5: lifecycle-тест оператора — 44/44 PASS; 2 бага
|
||||||
|
|
||||||
|
### Что сделано
|
||||||
|
|
||||||
|
| # | Компонент | Результат |
|
||||||
|
|---|-----------|-----------|
|
||||||
|
| 1 | `operator_lifecycle_test.sh` — 44 теста жизненного цикла | ✅ 44/44 PASS |
|
||||||
|
| 2 | Найден БАГ 1: `memory_mb` через PUT не применяется в k8s | ⚠️ зафиксировано |
|
||||||
|
| 3 | Найден БАГ 2: нет self-healing при ручном удалении Deployment | ⚠️ зафиксировано |
|
||||||
|
|
||||||
|
### Структура теста (operator_lifecycle_test.sh)
|
||||||
|
|
||||||
|
| Группа | Что тестируется | Тестов |
|
||||||
|
|--------|----------------|--------|
|
||||||
|
| 1 (API validation) | `memory_mb=0/5000` → 400; `timeout_sec=-1/901` → 400; без runtime → 400; GET/PUT/DELETE несущ. → 404 | 8 |
|
||||||
|
| 2 (Full lifecycle solo) | create→upload→build→ready→invoke→env update→k8s verify→memory update→timeout→delete→k8s cleanup | 18 |
|
||||||
|
| 3 (Edge cases) | DELETE while Building (kaniko убит, Deployment не создан); Reconcile (self-healing) | 10 |
|
||||||
|
| 4 (Multi parallel) | 3 функции параллельно; delete одной в Building; 2 дошли до Ready; 40 parallel invoke | 8 |
|
||||||
|
|
||||||
|
### Найденные баги оператора
|
||||||
|
|
||||||
|
| # | Баг | Место | Суть |
|
||||||
|
|---|-----|-------|------|
|
||||||
|
| 1 | `memory_mb` через PUT не применяется | `controllers/service_controller.go:ensureServiceDeployment` | При UPDATE обновляются только `Image` и `Env`. `Resources` (memory limit) не трогается — k8s Deployment хранит старое значение |
|
||||||
|
| 2 | Нет self-healing при удалении Deployment | `ServiceReconciler` | Если Deployment удалили вручную — контроллер не пересоздаёт. Нет cross-namespace watch (`sless-fn-*`) и нет `RequeueAfter`. Reconcile срабатывает только при изменении CRD |
|
||||||
|
|
||||||
|
### Что НЕ упало (важно)
|
||||||
|
|
||||||
|
- DELETE во время Building → CRD удалён, kaniko Job убит, Deployment не создан ✅
|
||||||
|
- Duplicate create + Ready → 409 ✅
|
||||||
|
- env_vars через PUT → k8s Deployment обновился, rollout OK, invoke вернул новое значение ✅
|
||||||
|
- 3 параллельных build → все 3 независимы, delete одного не ломает остальные ✅
|
||||||
|
- 40 параллельных invoke → 40/40 OK ✅
|
||||||
|
- Финальный teardown → все lc-* сервисы удалены ✅
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -14,8 +51,8 @@
|
|||||||
| 2 | `internal/api/handler/invoke.go` — убрать хардкод 35s дефолт | — | ✅ `TimeoutSec=0` → `&http.Client{}` (нет таймаута) |
|
| 2 | `internal/api/handler/invoke.go` — убрать хардкод 35s дефолт | — | ✅ `TimeoutSec=0` → `&http.Client{}` (нет таймаута) |
|
||||||
| 3 | `internal/api/handler/services.go` — валидация `timeout_sec` | — | ✅ `< 0` или `> 900` → HTTP 400 |
|
| 3 | `internal/api/handler/services.go` — валидация `timeout_sec` | — | ✅ `< 0` или `> 900` → HTTP 400 |
|
||||||
| 4 | `terraform/provider/…/service_resource.go` — schema + svcToModel | — | ✅ `0` → `null` в Terraform state |
|
| 4 | `terraform/provider/…/service_resource.go` — schema + svcToModel | — | ✅ `0` → `null` в Terraform state |
|
||||||
| 5 | Оператор Docker build v0.1.48 + push | operator | в процессе |
|
| 5 | Оператор Docker build v0.1.48 + push | operator | ✅ задеплоен, rollout OK |
|
||||||
| 6 | kubectl rollout + rollout status | k8s | в процессе |
|
| 6 | kubectl rollout + rollout status | k8s | ✅ |
|
||||||
|
|
||||||
### Изменения логики timeout_sec
|
### Изменения логики timeout_sec
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user