diff --git a/controllers/function_controller.go b/controllers/function_controller.go index 0307ea9..a9c7bf5 100644 --- a/controllers/function_controller.go +++ b/controllers/function_controller.go @@ -208,18 +208,11 @@ func (r *FunctionReconciler) ensureDeployment(ctx context.Context, fn *slessv1al return ctrl.Result{}, fmt.Errorf("get deployment: %w", err) } - // Обновляем образ и imagePullSecrets если изменились (новая сборка или смена конфига) + // Обновляем образ и imagePullSecrets при новой сборке. + // Тег образа уникален per build (sha256 от s3Key) → imagePullPolicy: IfNotPresent + // корректно подтягивает новый образ без дополнительных хаков. existing.Spec.Template.Spec.Containers[0].Image = fn.Status.ImageRef existing.Spec.Template.Spec.ImagePullSecrets = desired.Spec.Template.Spec.ImagePullSecrets - // Принудительный rollout restart при каждой новой сборке. - // Необходимо т.к. image tag :latest не меняется — без этой аннотации - // kubelet берёт кешированный образ и pod не видит новый код. - if fn.Status.LastBuiltAt != nil { - if existing.Spec.Template.Annotations == nil { - existing.Spec.Template.Annotations = map[string]string{} - } - existing.Spec.Template.Annotations["kubectl.kubernetes.io/restartedAt"] = fn.Status.LastBuiltAt.Time.Format(time.RFC3339) - } if err := r.Update(ctx, existing); err != nil { return ctrl.Result{}, fmt.Errorf("update deployment: %w", err) } diff --git a/deployments/k8s/operator.yaml b/deployments/k8s/operator.yaml index 4d4d2db..736ed05 100644 --- a/deployments/k8s/operator.yaml +++ b/deployments/k8s/operator.yaml @@ -3,7 +3,7 @@ # Состав: # - ConfigMap: не-секретные env vars (S3_ENDPOINT, REGISTRY_HOST и т.д.) # - Secret: секретные данные (S3 keys, postgres DSN, API token, docker auth) -# - Deployment: оператор naeel/sless-operator:v0.1.11 в namespace sless +# - Deployment: оператор naeel/sless-operator:v0.1.12 в namespace sless # - Service: ClusterIP :9090 (REST API) # - Ingress: sless-api.kube5s.ru → :9090 (внешний доступ с TLS) # @@ -70,7 +70,7 @@ spec: containers: - name: operator # При обновлении версии оператора — менять тег здесь (не latest!) - image: naeel/sless-operator:v0.1.11 + image: naeel/sless-operator:v0.1.12 # Always — чтобы всегда тянуть по точному тегу (не кешировать старый) imagePullPolicy: Always ports: diff --git a/doc/progress.md b/doc/progress.md index 2da6664..dd9a023 100644 --- a/doc/progress.md +++ b/doc/progress.md @@ -1,6 +1,6 @@ # Прогресс разработки -Последнее обновление: 2026-03-08 (operator v0.1.11, provider v0.1.5) +Последнее обновление: 2026-03-08 (operator v0.1.12, provider v0.1.5) ## Статусы: ✅ готово | 🔄 в процессе | ⏳ не начато diff --git a/examples/hello-node/job.tf b/examples/hello-node/job.tf index cd168bc..d8bf31e 100644 --- a/examples/hello-node/job.tf +++ b/examples/hello-node/job.tf @@ -36,7 +36,7 @@ resource "sless_job" "hello_run" { function = sless_function.hello_job.name event_json = jsonencode({ numbers = [1, 2, 3, 4, 5] }) wait_timeout_sec = 600 - run_id = 5 + run_id = 7 } output "job_phase" { diff --git a/internal/builder/builder.go b/internal/builder/builder.go index f643d86..b8d1c06 100644 --- a/internal/builder/builder.go +++ b/internal/builder/builder.go @@ -9,6 +9,7 @@ package builder import ( "context" + "crypto/sha256" "fmt" "time" @@ -60,9 +61,12 @@ func New(c client.Client, cfg Config) *Builder { } // ImageRef возвращает полный путь к образу в registry для данной функции и версии. +// Тег = первые 12 символов sha256(s3Key): уникален per build, не меняется при +// повторном reconcile с тем же s3Key, не требует хаков с :latest. func (b *Builder) ImageRef(namespace, funcName, s3Key string) string { - // Используем s3Key как уникальный тег чтобы разные версии не перезаписывали друг друга - return fmt.Sprintf("%s/sless-%s-%s:latest", b.registryHost, namespace, funcName) + h := sha256.Sum256([]byte(s3Key)) + tag := fmt.Sprintf("%x", h[:6]) // 12 hex-символов + return fmt.Sprintf("%s/sless-%s-%s:%s", b.registryHost, namespace, funcName, tag) } // Build запускает kaniko Job для сборки образа функции.