kube-state-metrics CronJob 指标详解:从 14 个 kube_cronjob_* 指标到调度解析源码原理
kube-state-metrics CronJob 指标详解从 14 个 kube_cronjob_* 指标到调度解析源码原理【免费下载链接】kube-state-metricsAdd-on agent to generate and expose cluster-level metrics.项目地址: https://gitcode.com/GitHub_Trending/ku/kube-state-metrics本文围绕 kube-state-metrics 官方的 CronJob 指标文档docs/metrics/workload/cronjob-metrics.md展开完整覆盖全部 14 个kube_cronjob_*指标的含义、标签与稳定性状态并结合 internal/store/cronjob.go 的源码实现深入讲解下一调度时间的计算逻辑、时区处理、非法 cron 调度的容错机制以及如何通过--metric-annotations-allowlist/--metric-labels-allowlist等启动参数控制标签类指标的暴露。读完本文你将能够正确查询这些指标构建 CronJob 监控告警并理解指标背后的取数与解析原理。1. kube_cronjob_* 指标全览CronJob 指标全部为 Gauge 类型用于回答CronJob 是否还在正常调度、下一次调度何时发生、上次运行是否成功这类问题。文档中列出的完整指标清单如下指标名类型说明标签状态kube_cronjob_annotationsGauge将 Kubernetes annotation 转换为 Prometheus 标签由--metric-annotations-allowlist控制cronjob、namespace、annotation_CRONJOB_ANNOTATIONEXPERIMENTALkube_cronjob_infoGaugeCronJob 基本信息调度表达式、并发策略、时区cronjob、namespace、schedule、concurrency_policy、timezoneSTABLEkube_cronjob_labelsGauge将 Kubernetes label 转换为 Prometheus 标签由--metric-labels-allowlist控制cronjob、namespace、label_CRONJOB_LABELSTABLEkube_cronjob_createdGauge创建时间的 Unix 时间戳cronjob、namespaceSTABLEkube_cronjob_next_schedule_timeGauge下一次调度时间cronjob、namespaceSTABLEkube_cronjob_schedule_invalidGauge调度表达式在其配置的时区下无法解析时为 1cronjob、namespaceEXPERIMENTALkube_cronjob_status_activeGauge当前正在运行的 Job 数量cronjob、namespaceSTABLEkube_cronjob_status_last_schedule_timeGauge上次成功调度的 Unix 时间戳cronjob、namespaceSTABLEkube_cronjob_status_last_successful_timeGauge上次成功完成的 Unix 时间戳cronjob、namespaceSTABLEkube_cronjob_spec_suspendGauge是否已挂起1/0cronjob、namespaceSTABLEkube_cronjob_spec_starting_deadline_secondsGauge错过调度时间后启动 Job 的宽限秒数cronjob、namespaceSTABLEkube_cronjob_metadata_resource_versionGauge对象资源版本号cronjob、namespaceSTABLEkube_cronjob_spec_successful_job_history_limitGauge保留的成功 Job 数量上限cronjob、namespaceEXPERIMENTALkube_cronjob_spec_failed_job_history_limitGauge保留的失败 Job 数量上限cronjob、namespaceEXPERIMENTAL所有指标都带有两个固定基础标签cronjobcronjob-name与namespacecronjob-namespace。从源码结构看这一点由 internal/store/cronjob.go 中的wrapCronJobFunc统一注入var ( descCronJobLabelsName kube_cronjob_labels descCronJobLabelsDefaultLabels []string{namespace, cronjob} ) func wrapCronJobFunc(f func(*batchv1.CronJob) *metric.Family) func(interface{}) *metric.Family { return func(obj interface{}) *metric.Family { cronJob : obj.(*batchv1.CronJob) metricFamily : f(cronJob) for _, m : range metricFamily.Metrics { m.LabelKeys, m.LabelValues mergeKeyValues( descCronJobLabelsDefaultLabels, []string{cronJob.Namespace, cronJob.Name}, m.LabelKeys, m.LabelValues, ) } return metricFamily } }也就是说无论某个指标的生成函数自己声明了哪些标签最终都会与namespace、cronjob两个标签合并输出这保证了按命名空间/CronJob 维度做 PromQL 聚合时的标签一致性。2. 指标逐个解析2.1 kube_cronjob_info调度语义的载体kube_cronjob_info的取值恒为 1真正的信息量在其三个附加标签中kube_cronjob_info{concurrency_policyForbid,cronjobmy-cronjob,namespacens1,schedule0 */6 * * *,timezoneAsia/Shanghai} 1源码中对应逻辑internal/store/cronjob.gokube_cronjob_info生成函数直接读取j.Spec.Schedule、j.Spec.ConcurrencyPolicy并在Spec.TimeZone为空时回退为字符串localtimeZone : local if j.Spec.TimeZone ! nil { timeZone *j.Spec.TimeZone }注意测试用例中出现了timezonelocal的输出见 internal/store/cronjob_test.go这印证了未显式设置spec.timeZone时标签值为local而非空串。2.2 kube_cronjob_next_schedule_time判断调度是否延迟的核心指标该指标描述为下一次计划调度的 Unix 时间戳取值为lastScheduleTime之后的下一次触发时间若从未调度过则从 CronJob 创建时间起算。官方建议用它来判断 Job 是否延迟。其计算链路在 internal/store/cronjob.go 中分两层func parseSchedule(schedule string, timeZone *string) (cron.Schedule, error) { if timeZone ! nil { schedule fmt.Sprintf(CRON_TZ%s %s, *timeZone, schedule) } sched, err : cron.ParseStandard(schedule) if err ! nil { return nil, fmt.Errorf(failed to parse cron job schedule %s: %w, schedule, err) } return sched, nil } func getNextScheduledTime(schedule string, lastScheduleTime *metav1.Time, createdTime metav1.Time, timeZone *string) (time.Time, error) { sched, err : parseSchedule(schedule, timeZone) if err ! nil { return time.Time{}, err } if !lastScheduleTime.IsZero() { return sched.Next(lastScheduleTime.Time), nil } if !createdTime.IsZero() { return sched.Next(createdTime.Time), nil } return time.Time{}, errors.New(createdTime and lastScheduleTime are both zero) }可以推断出三个关键行为调度解析使用第三方 cron 库github.com/netresearch/go-cron并支持标准 5 段 cron 表达式cron.ParseStandard。时区通过CRON_TZ前缀注入表达式即 CronJob 的spec.timeZone会直接参与下一次触发时间的计算。两个基准时间的优先级优先status.lastScheduleTime其次creationTimestamp。两个值得注意的边界条件同样体现在源码中Suspended 的 CronJob 不输出该指标if err nil (j.Spec.Suspend nil || !*j.Spec.Suspend)。已挂起的 CronJob 不再产生下一次调度因此指标缺失而非输出 0这一点在 internal/store/cronjob_test.go 的SuspendedCronJob1用例中得到验证——期望输出里只有kube_cronjob_spec_suspend1没有next_schedule_time行。解析失败不输出、也不崩溃单个调度表达式无法解析时跳过next_schedule_time同时由kube_cronjob_schedule_invalid以值 1 暴露解析失败与 Kubernetes CronJob controller 的容错态度一致。2.3 kube_cronjob_schedule_invalid 与 IANA 时区数据库内嵌kube_cronjob_schedule_invalidEXPERIMENTAL在CronJob 的 schedule 在其配置的时区下无法解析时输出 1。源码直接复用parseSchedule做检测if _, err : parseSchedule(j.Spec.Schedule, j.Spec.TimeZone); err ! nil { ms append(ms, metric.Metric{Value: 1}) }一个容易被忽视的实现细节internal/store/cronjob.go 顶部显式内嵌了 IANA 时区数据库// Embed the IANA time zone database into the binary so that named time // zones (e.g. a CronJobs spec.timeZone of Asia/Singapore) resolve even // when running from a minimal/distroless image that ships no tzdata. _ time/tzdata这意味着即使 kube-state-metrics 运行在没有 tzdata 的极简/distroless 镜像中spec.timeZone: Asia/Singapore这类具名时区也能正确解析不会误报schedule_invalid1。internal/store/cronjob_test.go 的TestCronJobStoreScheduleParsing专门覆盖了三类解析失败场景*/120 4-22 * * *步长超范围、0 1 */32,1-7 * 3越界列表、Invalid/Zone非法时区以及具名时区正常解析的回归用例。2.4 状态类指标status_active / last_schedule_time / last_successful_time三个状态指标分别映射status子资源指标数据来源缺失行为kube_cronjob_status_activelen(j.Status.Active)恒输出可为 0kube_cronjob_status_last_schedule_timej.Status.LastScheduleTime.Unix()字段为 nil 时不输出该指标kube_cronjob_status_last_successful_timej.Status.LastSuccessfulTime.Unix()字段为 nil 时不输出该指标从源码结构看后两者都遵循指针为空则整个 Family 输出空 Metrics 列表的约定因此在 Prometheus 中新建、尚未运行过的 CronJob 上查不到这两个序列告警规则中应使用absent()或or组合来兜底。2.5 Spec 类指标suspend / starting_deadline_seconds / history limits / created / resource_versionkube_cronjob_spec_suspendboolFloat64(j.Spec.Suspend ! nil *j.Spec.Suspend)即 null 按 API 默认 false 处理输出 0true输出 1。kube_cronjob_spec_starting_deadline_seconds仅当Spec.StartingDeadlineSeconds ! nil时输出值为秒数测试用例中使用 300。kube_cronjob_spec_successful_job_history_limit/kube_cronjob_spec_failed_job_history_limit均为 EXPERIMENTAL同为 nil 敏感输出仅当字段显式设置时出现。kube_cronjob_createdCreationTimestamp.Unix()零值时间戳不输出。kube_cronjob_metadata_resource_version将metadata.resourceVersion作为数值输出可用于感知对象变更。2.6 标签类指标annotations 与 labelskube_cronjob_annotationsEXPERIMENTAL与kube_cronjob_labelsSTABLE将 Kubernetes 元数据中的 annotation/label 键值转成 Prometheus 标签前缀分别为annotation_与label_但默认不暴露。源码中的门槛检查非常直接if len(allowAnnotationsList) 0 { return metric.Family{} // 未配置 allowlist 时不输出任何样本 } annotationKeys, annotationValues : createPrometheusLabelKeysValues(annotation, j.Annotations, allowAnnotationsList)启用方式是在启动参数中配置白名单详见下节且该列表按资源维度复数名cronjobs解析由 internal/store/builder.go 把配置透传给生成函数cronjobs: func(b *Builder) []cache.Store { return b.buildStoresFunc( cronJobMetricFamilies(b.allowAnnotationsList[cronjobs], b.allowLabelsList[cronjobs]), batchv1.CronJob{}, createCronJobListWatch, b.useAPIServerCache, b.objectLimit, ) }输出示例来自测试用例allowlist 只放行了app.k8s.io/ownerkube_cronjob_annotations{annotation_app_k8s_io_ownerfoo,cronjobActiveRunningCronJob1,namespacens1} 13. 启用与配置启动参数与采集机制3.1 资源开关cronjobs在--resources参数的默认列表中即默认开启 CronJob 指标采集。完整默认值见 docs/developer/cli-arguments.md 的--resources说明certificatesigningrequests,configmaps,cronjobs,daemonsets,...,volumeattachments。如果启用了多资源分片部署可参考 examples/daemonsetsharding/deployment.yaml 中的部署清单方式。3.2 --metric-annotations-allowlist 与 --metric-labels-allowlist这两个参数控制 2.6 节两个标签类指标的暴露格式要点摘自 docs/developer/cli-arguments.md按复数资源名 逗号分隔的键列表声明例如只放行 CronJob 上的ownerannotation--metric-annotations-allowlist cronjobs[owner]也可以为多资源同时配置如namespaces[kubernetes.io/team],cronjobs[app.k8s.io/owner]。每个资源可用单个*放行任意键cronjobs[*]但官方明确警告其性能影响严重完整的通配*仅当它是列表第一项时生效。未配置时kube_cronjob_annotations/kube_cronjob_labels完全不出现在 /metrics 输出中注意kube_cronjob_labels的默认输出并不包含额外 label 键——基础标签cronjob/namespace由所有指标统一携带与白名单机制无关。3.3 数据采集方式从 internal/store/cronjob.go 的createCronJobListWatch看CronJob 数据经由BatchV1().CronJobs(ns).List/Watch建立 informer 本地缓存支持--namespace过滤ns与字段选择器fieldSelector。因此上述所有指标都反映 informer 缓存中最新的 CronJob 对象状态指标本身不产生对 API Server 的额外轮询压力对象规模较大时可通过--object-limit限制单资源缓存上限见 builder 中b.objectLimit的传递。4. 测试用例揭示的行为边界internal/store/cronjob_test.go 是理解各指标何时输出、何时缺失的最佳依据其中几个代表性场景时区参与计算ActiveRunningCronJobWithTZ1timeZone: Asia/Shanghai与同名无时区对象使用相同的lastScheduleTime和0 */6 * * *两者计算出的next_schedule_time相差恰好 4 小时UTC 与东八区的时差TestGetNextScheduledTime用UTC与Asia/Shanghai两个用例显式验证了这一差值。未调度过的新 CronJobActiveCronJob1NoLastScheduled的LastScheduleTime为 nilnext_schedule_time从creationTimestamp起算25 * * * *调度、下一分钟为 25 分。Suspend 为 nil 的回退ActiveCronJobNilSuspend用例验证省略suspend字段时按 false 处理kube_cronjob_spec_suspend0且正常输出next_schedule_time。Suspended 状态SuspendedCronJob1用例中next_schedule_time序列缺失、kube_cronjob_spec_suspend1、status_active0。非法调度/非法时区TestCronJobStoreScheduleParsing确认解析失败时只输出schedule_invalid1进程不会因单个坏对象而崩溃。5. 监控与告警思路基于上述指标可以构造几类典型的 PromQL 检查示例请结合自身集群实际标签调整调度延迟检测kube_cronjob_next_schedule_time time()持续一段时间说明下次触发点已过去但尚未调度未挂起时失败时区/调度表达式kube_cronjob_schedule_invalid 1长期无成功记录time() - kube_cronjob_status_last_successful_time 期望周期注意该指标在新建 CronJob 上不存在需要处理序列缺失挂起感知kube_cronjob_spec_suspend 1可与上述延迟告警做unless排除避免误报运行堆积kube_cronjob_status_active 1配合concurrency_policy ! Allow的kube_cronjob_info可能意味着上一次 Job 未正常结束。小结kube-state-metrics 的 CronJob 指标族以 14 个 Gauge 指标覆盖了调度配置kube_cronjob_info、kube_cronjob_spec_*、运行状态kube_cronjob_status_*、调度健康度kube_cronjob_next_schedule_time、kube_cronjob_schedule_invalid与元数据kube_cronjob_created、kube_cronjob_metadata_resource_version、kube_cronjob_annotations/labels五个维度。理解其实现时重点把握三点namespace/cronjob基础标签由wrapCronJobFunc统一注入next_schedule_time由parseSchedulegetNextScheduledTime基于lastScheduleTime或creationTimestamp与CRON_TZ前缀的时区表达式计算并通过内嵌time/tzdata保证具名时区在极简镜像中可用标签类指标默认关闭需经--metric-annotations-allowlist/--metric-labels-allowlist白名单显式开启。相关源码与测试分别位于 internal/store/cronjob.go、internal/store/cronjob_test.go、internal/store/builder.go参数细节可查阅 docs/developer/cli-arguments.md。【免费下载链接】kube-state-metricsAdd-on agent to generate and expose cluster-level metrics.项目地址: https://gitcode.com/GitHub_Trending/ku/kube-state-metrics创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考