fix: operator v0.1.49 — Resources update + self-healing requeue

БАГ 1: ensureServiceDeployment UPDATE блок теперь обновляет Containers[0].Resources
  → memory_mb через PUT применяется к k8s Deployment

БАГ 2: ensureServiceDeployment возвращает RequeueAfter: 60s вместо Result{}
  → ручное удаление Deployment пересоздаётся контроллером в течение 60s

lifecycle-тест: 47/47 PASS (ранее 44/44 с 2 known bugs)
This commit is contained in:
Naeel
2026-03-21 18:51:02 +03:00
parent 9b74358979
commit f65677a4d0
4 changed files with 45 additions and 14 deletions
+6 -4
View File
@@ -210,6 +210,8 @@ func (r *ServiceReconciler) ensureServiceDeployment(ctx context.Context, svc *sl
} else {
existing.Spec.Template.Spec.Containers[0].Image = svc.Status.ImageRef
existing.Spec.Template.Spec.Containers[0].Env = desired.Spec.Template.Spec.Containers[0].Env
// Обновляем ресурсы — иначе memory_mb из PUT не применяется к Deployment
existing.Spec.Template.Spec.Containers[0].Resources = desired.Spec.Template.Spec.Containers[0].Resources
existing.Spec.Template.Spec.ImagePullSecrets = desired.Spec.Template.Spec.ImagePullSecrets
if err := r.Update(ctx, existing); err != nil {
return ctrl.Result{}, fmt.Errorf("update service deployment: %w", err)
@@ -297,15 +299,15 @@ func (r *ServiceReconciler) ensureServiceDeployment(ctx context.Context, svc *sl
}
}
return ctrl.Result{}, nil
// Периодический requeue — self-healing: если Deployment/Service/Ingress удалены вручную, контроллер их пересоздаст
return ctrl.Result{RequeueAfter: 60 * time.Second}, nil
}
// buildServiceDeployment формирует Deployment манифест.
func (r *ServiceReconciler) buildServiceDeployment(svc *slessv1alpha1.Service, namespace string) *appsv1.Deployment {
replicas := int32(1)
envVars := []corev1.EnvVar{
{Name: "SLESS_ENTRYPOINT", Value: svc.Spec.Entrypoint},
}
var envVars []corev1.EnvVar
// Сортируем ключи для стабильного порядка — нестабильный порядок env vars вызывает лишние rollout'ы
keys := make([]string, 0, len(svc.Spec.Env))
for k := range svc.Spec.Env {
+1 -1
View File
@@ -74,7 +74,7 @@ spec:
containers:
- name: operator
# При обновлении версии оператора — менять тег здесь (не latest!)
image: pearlharbor.registryk8s.services.ngcloud.ru/naeel/sless-operator:v0.1.48
image: pearlharbor.registryk8s.services.ngcloud.ru/naeel/sless-operator:v0.1.49
# Always — чтобы всегда тянуть по точному тегу (не кешировать старый)
imagePullPolicy: Always
ports:
+13 -8
View File
@@ -4,7 +4,7 @@
---
## 2026-03-21 — БАГ: memory_mb через PUT не применяется в k8s Deployment (НЕ ИСПРАВЛЕН)
## 2026-03-21 — БАГ: memory_mb через PUT не применяется в k8s Deployment (ИСПРАВЛЕН v0.1.49)
### Симптом
@@ -27,16 +27,19 @@ existing.Spec.Template.Spec.Containers[0].Env = desired.Spec.Template.Spec.Con
```
`desired` Deployment строится с правильным `memory_mb`, но в `existing` он не копируется.
### Фикс (не применён)
### Фикс (применён в v0.1.49)
```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.Containers[0].Resources = desired.Spec.Template.Spec.Containers[0].Resources // ← ДОБАВЛЕНО
existing.Spec.Template.Spec.ImagePullSecrets = desired.Spec.Template.Spec.ImagePullSecrets
```
### Проверка
`operator_lifecycle_test.sh` тест 2.13 → PASS (47/47)
### Файл
`controllers/service_controller.go` ~ строка 241
@@ -47,7 +50,7 @@ existing.Spec.Template.Spec.ImagePullSecrets = desired.Spec.Template.Spe
---
## 2026-03-21 — БАГ: нет self-healing — ручное удаление Deployment не восстанавливается (НЕ ИСПРАВЛЕН)
## 2026-03-21 — БАГ: нет self-healing — ручное удаление Deployment не восстанавливается (ИСПРАВЛЕН v0.1.49)
### Симптом
@@ -64,14 +67,16 @@ kubectl delete deployment my-svc -n sless-fn-sless-xxx
Deployment живёт в `sless-fn-sless-xxx` — другой namespace. controller-runtime не допускает `Owns()` для cross-namespace ресурсов.
`ensureServiceDeployment` вызывается только когда `phase=Ready` И пришёл reconcile event (=изменение CRD). Просто удалённый Deployment event не генерирует.
### Фикс (вариант)
### Фикс (применён в v0.1.49)
Добавить `RequeueAfter: 60s` в `ensureServiceDeployment` — тогда контроллер будет периодически проверять и пересоздавать:
Добавлен `RequeueAfter: 60s` в конец `ensureServiceDeployment`:
```go
// В конце ensureServiceDeployment:
// Периодический requeue — self-healing: если Deployment/Service/Ingress удалены вручную, контроллер их пересоздаст
return ctrl.Result{RequeueAfter: 60 * time.Second}, nil
```
Или использовать `Watches()` с cross-namespace mapper (сложнее).
### Проверка
`operator_lifecycle_test.sh` тест 3.2 → PASS (47/47)
### Файл
+25 -1
View File
@@ -1,6 +1,30 @@
# Прогресс разработки
Последнее обновление: 2026-03-21 (operator_lifecycle_test.sh — 44/44 PASS; 2 бага оператора найдены)
Последнее обновление: 2026-03-21 (operator v0.1.49 — оба бага исправлены; lifecycle-тест 47/47 PASS)
---
## 2026-03-21 — Сессия 6: исправление багов оператора v0.1.49
### Что сделано
| # | Компонент | Результат |
|---|-----------|-----------|
| 1 | БАГ 1 исправлен: добавлен `Resources` в UPDATE блок `ensureServiceDeployment` | ✅ |
| 2 | БАГ 2 исправлен: добавлен `RequeueAfter: 60s` в конец `ensureServiceDeployment` | ✅ |
| 3 | go build, docker build+push v0.1.49, kubectl rollout | ✅ |
| 4 | `operator_lifecycle_test.sh` после фикса | ✅ 47/47 PASS (ранее 44/44 с 2 known bugs) |
### Изменения в коде
**controllers/service_controller.go**:
```go
// БАГ 1 — UPDATE блок ensureServiceDeployment
existing.Spec.Template.Spec.Containers[0].Resources = desired.Spec.Template.Spec.Containers[0].Resources // ДОБАВЛЕНО
// БАГ 2 — конец ensureServiceDeployment
return ctrl.Result{RequeueAfter: 60 * time.Second}, nil // БЫЛО: Result{}, nil
```
---