What happened:
When a CronJob has spec.timeZone set to a non-UTC timezone (e.g. Asia/Singapore) and the
kube-state-metrics container image does not include tzdata, kube-state-metrics panics and enters
CrashLoopBackOff, taking down all cluster metrics collection.
The panic originates in internal/store/cronjob.go:254 where getNextScheduledTime() prefixes
the schedule with CRON_TZ=<timezone>, passes it to cron.ParseStandard(), which calls
time.LoadLocation() — failing without tzdata — and the error is passed directly to panic(err)
with no recovery.
What you expected to happen:
The error should be logged and the kube_cronjob_next_schedule_time metric skipped for the
affected CronJob. The process should continue running and serving metrics for all other resources.
How to reproduce it (as minimally and precisely as possible):
# Apply any CronJob with spec.timeZone set to a named timezone
kubectl apply -f - <<EOF
apiVersion: batch/v1
kind: CronJob
metadata:
name: tz-test
spec:
schedule: "0 4 * * 1-5"
timeZone: "Asia/Singapore"
jobTemplate:
spec:
template:
spec:
containers:
- name: test
image: busybox
command: ["echo", "hello"]
restartPolicy: OnFailure
EOF
# kube-state-metrics will panic immediately with:
# panic: Failed to parse cron job schedule 'CRON_TZ=Asia/Singapore 0 4 * * 1-5':
# provided bad location Asia/Singapore: unknown time zone Asia/Singapore
Anything else we need to know?:
spec.timeZone is a stable Kubernetes API field since v1.27. The panic(err) in cronjob.go:254
means any cluster using this field with kube-state-metrics deployed without tzdata will lose all
metrics. The fix is two-fold:
- Replace
panic(err) with a logged error that skips the metric for the affected CronJob
- Include tzdata in the container image so named timezones resolve correctly
Suggested fix for cronjob.go:254:
if err != nil {
klog.Errorf("failed to compute next schedule time for cronjob %s/%s: %v",
j.Namespace, j.Name, err)
return &metric.Family{Metrics: ms}
}
Environment:
- kube-state-metrics version: (please fill in)
- Kubernetes version:
v1.32.12
- Cloud provider or hardware configuration: AWS EKS
- Other info: kube-state-metrics container image does not include tzdata;
time.LoadLocation() fails for any named timezone
What happened:
When a CronJob has
spec.timeZoneset to a non-UTC timezone (e.g.Asia/Singapore) and thekube-state-metrics container image does not include tzdata, kube-state-metrics panics and enters
CrashLoopBackOff, taking down all cluster metrics collection.The panic originates in
internal/store/cronjob.go:254wheregetNextScheduledTime()prefixesthe schedule with
CRON_TZ=<timezone>, passes it tocron.ParseStandard(), which callstime.LoadLocation()— failing without tzdata — and the error is passed directly topanic(err)with no recovery.
What you expected to happen:
The error should be logged and the
kube_cronjob_next_schedule_timemetric skipped for theaffected CronJob. The process should continue running and serving metrics for all other resources.
How to reproduce it (as minimally and precisely as possible):
Anything else we need to know?:
spec.timeZoneis a stable Kubernetes API field since v1.27. Thepanic(err)incronjob.go:254means any cluster using this field with kube-state-metrics deployed without tzdata will lose all
metrics. The fix is two-fold:
panic(err)with a logged error that skips the metric for the affected CronJobSuggested fix for
cronjob.go:254:Environment:
v1.32.12time.LoadLocation()fails for any named timezone