From 461ac096f953fc78abc437654f179f47b62c2fd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CNaeel=E2=80=9D?= Date: Sun, 8 Mar 2026 12:13:15 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20FunctionJob=20=D0=B7=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=81=D0=B0=D0=BB=20=D0=B2=20Running=20=E2=80=94=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20RequeueAfter=20pol?= =?UTF-8?q?ling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controllers/functionjob_controller.go | 18 ++++++++++++++---- deployments/k8s/operator.yaml | 2 +- deployments/k8s/rbac.yaml | 3 ++- examples/hello-node/code/handler-http.js | 1 + examples/hello-node/code/handler-job.js | 1 + examples/hello-node/handler-http.zip | Bin 409 -> 410 bytes examples/hello-node/handler-job.zip | Bin 489 -> 489 bytes internal/api/handler/upload.go | 2 +- 8 files changed, 20 insertions(+), 7 deletions(-) diff --git a/controllers/functionjob_controller.go b/controllers/functionjob_controller.go index 320fa4c..5035b49 100644 --- a/controllers/functionjob_controller.go +++ b/controllers/functionjob_controller.go @@ -1,4 +1,4 @@ -// Изменено: 2026-03-08 +// Изменено: 2026-03-08 (fix: RequeueAfter для poll статуса Job) // FunctionJobReconciler — контроллер одноразовых запусков функций. // При создании FunctionJob: // 1. Ждёт пока Function станет Ready @@ -14,6 +14,7 @@ package controllers import ( "context" "fmt" + "time" batchv1 "k8s.io/api/batch/v1" corev1 "k8s.io/api/core/v1" @@ -180,6 +181,8 @@ func (r *FunctionJobReconciler) Reconcile(ctx context.Context, req ctrl.Request) } // syncJobStatus читает статус k8s Job и обновляет FunctionJob.Status. +// Если Job ещё выполняется — запрашивает повторный reconcile через 5 сек +// (Owns не работает кросс-неймспейсно, поэтому используем polling). func (r *FunctionJobReconciler) syncJobStatus(ctx context.Context, fj *slessv1alpha1.FunctionJob, job *batchv1.Job) (ctrl.Result, error) { if job.Status.Succeeded > 0 { now := metav1.Now() @@ -191,8 +194,13 @@ func (r *FunctionJobReconciler) syncJobStatus(ctx context.Context, fj *slessv1al fj.Status.Phase = slessv1alpha1.FunctionJobPhaseFailed fj.Status.CompletionTime = &now fj.Status.Message = "job failed, check pod logs: kubectl logs -n sless-fn-" + fj.Namespace + " -l functionjob=" + fj.Name + } else { + // Job ещё выполняется — перечитаем через 5 секунд + if err := r.Status().Update(ctx, fj); err != nil { + return ctrl.Result{}, fmt.Errorf("sync job status: %w", err) + } + return ctrl.Result{RequeueAfter: 5 * time.Second}, nil } - // Running — ничего не меняем, перечитаем при следующем reconcile if err := r.Status().Update(ctx, fj); err != nil { return ctrl.Result{}, fmt.Errorf("sync job status: %w", err) } @@ -251,10 +259,12 @@ func fnEnvVars(fn *slessv1alpha1.Function) []corev1.EnvVar { func int32Ptr(i int32) *int32 { return &i } -// SetupWithManager регистрирует контроллер и настраивает watch на k8s Job. +// SetupWithManager регистрирует контроллер. +// Owns(&batchv1.Job{}) намеренно убрано: Job создаётся в другом namespace +// (sless-fn-*), где OwnerReference кросс-неймспейсно не работают. +// Вместо этого используется RequeueAfter-polling в syncJobStatus. func (r *FunctionJobReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&slessv1alpha1.FunctionJob{}). - Owns(&batchv1.Job{}). Complete(r) } diff --git a/deployments/k8s/operator.yaml b/deployments/k8s/operator.yaml index 59e3359..eb93da2 100644 --- a/deployments/k8s/operator.yaml +++ b/deployments/k8s/operator.yaml @@ -70,7 +70,7 @@ spec: containers: - name: operator # При обновлении версии оператора — менять тег здесь (не latest!) - image: naeel/sless-operator:v0.1.8 + image: naeel/sless-operator:v0.1.10 # Always — чтобы всегда тянуть по точному тегу (не кешировать старый) imagePullPolicy: Always ports: diff --git a/deployments/k8s/rbac.yaml b/deployments/k8s/rbac.yaml index d544522..f87075e 100644 --- a/deployments/k8s/rbac.yaml +++ b/deployments/k8s/rbac.yaml @@ -38,9 +38,10 @@ rules: resources: ["services", "namespaces"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # Secrets — pull-секрет копируется в sless-fn-* namespace при создании функций + # list/watch нужны для controller-runtime cache (информер на secrets) - apiGroups: [""] resources: ["secrets"] - verbs: ["get", "create"] + verbs: ["get", "list", "watch", "create", "update", "patch"] - apiGroups: ["networking.k8s.io"] resources: ["ingresses"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] diff --git a/examples/hello-node/code/handler-http.js b/examples/hello-node/code/handler-http.js index 7a15d05..ec016dc 100644 --- a/examples/hello-node/code/handler-http.js +++ b/examples/hello-node/code/handler-http.js @@ -5,3 +5,4 @@ exports.handle = async (event) => { const name = event.name || 'World'; return { message: `Hello, ${name}!` }; }; + diff --git a/examples/hello-node/code/handler-job.js b/examples/hello-node/code/handler-job.js index 3342114..5081ff9 100644 --- a/examples/hello-node/code/handler-job.js +++ b/examples/hello-node/code/handler-job.js @@ -7,3 +7,4 @@ exports.handle = async (event) => { const sum = numbers.reduce((acc, n) => acc + n, 0); return { input: numbers, sum, count: numbers.length }; }; + diff --git a/examples/hello-node/handler-http.zip b/examples/hello-node/handler-http.zip index c0c865e7dbee49c0aeca3ff2606cb8508dd64841..03b93538014f4381c2ca397b0e112812fbb2c108 100644 GIT binary patch delta 67 zcmbQqJd1gQ0i!`-9Ww*N|NjBr>>NwYV=A~985k^pIKZ2cNrYL1fddE`7!