fix: harden scheduler-k3s cron manifests and dockerfile run startup

The cron-id label could exceed Kubernetes' 63-byte cap when commands or
schedules were long, and an all-digit job-suffix or cron-id rendered as
an unquoted YAML scalar caused the API server to reject manifests. Run
pods built from dockerfiles also occasionally hit the 10s startup wait
on a cold image pull, even though the pod was scheduled correctly.

The cron-id is now stored as an annotation and a shorter hash is used as
the selector label. Every interpolated annotation and label value in the
cron-job and deployment templates is now quoted to prevent numeric
coercion, and the run-pod wait timeout is raised to 30 seconds.
This commit is contained in:
Jose Diaz-Gonzalez
2026-05-11 14:49:58 -04:00
parent d0588698f5
commit b66df28d96
7 changed files with 198 additions and 38 deletions

View File

@@ -3,6 +3,7 @@ package scheduler_k3s
import (
"bytes"
"context"
"crypto/sha256"
"encoding/base64"
"errors"
"fmt"
@@ -23,6 +24,7 @@ import (
nginxvhosts "github.com/dokku/dokku/plugins/nginx-vhosts"
resty "github.com/go-resty/resty/v2"
kedav1alpha1 "github.com/kedacore/keda/v2/apis/keda/v1alpha1"
"github.com/multiformats/go-base36"
"golang.org/x/sync/errgroup"
"gopkg.in/yaml.v3"
"helm.sh/helm/v3/pkg/strvals"
@@ -2081,6 +2083,14 @@ func kubernetesNodeToNode(node v1.Node) Node {
}
}
// cronIDLabelValue returns a Kubernetes-label-safe hash of a cron ID.
// The raw cron ID can exceed the 63-byte label cap, so we keep it as an
// annotation and use this short hash for selectors.
func cronIDLabelValue(cronID string) string {
sum := sha256.Sum256([]byte(cronID))
return base36.EncodeToStringLc(sum[:16])
}
// parseMemoryQuantity parses a string into a valid memory quantity
func parseMemoryQuantity(input string) (string, error) {
if _, err := strconv.ParseInt(input, 10, 64); err == nil {