diff --git a/controllers/service_controller.go b/controllers/service_controller.go index d469e89..899974f 100644 --- a/controllers/service_controller.go +++ b/controllers/service_controller.go @@ -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 { diff --git a/deployments/k8s/operator.yaml b/deployments/k8s/operator.yaml index 59b9af9..df9533a 100644 --- a/deployments/k8s/operator.yaml +++ b/deployments/k8s/operator.yaml @@ -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: diff --git a/doc/errors/log.md b/doc/errors/log.md index 009b49f..2d17bac 100644 --- a/doc/errors/log.md +++ b/doc/errors/log.md @@ -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) ### Файл diff --git a/doc/progress.md b/doc/progress.md index 33487c9..e36d556 100644 --- a/doc/progress.md +++ b/doc/progress.md @@ -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 +``` ---