Controller未收到Job最终状态通知问题排查求助
问题背景
我正在开发一款生成batch/v1 Job的应用,需要将Job状态同步至自定义资源RequestedBackupAction的状态中。
控制器配置代码
func (r *JobsManagedByRequestedBackupActionObserver) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&riotkitorgv1alpha1.RequestedBackupAction{}). Owns(&batchv1.Job{}). Owns(&batchv1.CronJob{}). WithEventFilter(predicate.Funcs{ DeleteFunc: func(e event.DeleteEvent) bool { return false }, }). Complete(r) }
状态同步逻辑
在Reconcile方法中,根据请求获取RequestedBackupAction对象,再通过专属跟踪标签从API获取Job列表:
list, err := kj.client.Jobs(namespace).List(ctx, metav1.ListOptions{LabelSelector: v1alpha1.LabelTrackingId + "=" + trackingId})
异常现象
遍历Job对象时,日志仅输出活跃状态的记录:
time="2022-12-12T20:00:55Z" level=error msg="[++++++++++++] JOB name=app1-backup-vmqrp, failed=0, active=1, succeeded=0"
但实际Job已完成并进入失败状态(failed=1, active=0, succeeded=0),控制器却未收到该状态通知,Job最终状态如下:
status: conditions: - lastProbeTime: "2022-12-12T20:00:56Z" lastTransitionTime: "2022-12-12T20:00:56Z" message: Job has reached the specified backoff limit reason: BackoffLimitExceeded status: "True" type: Failed failed: 1 ready: 0 startTime: "2022-12-12T20:00:50Z" uncountedTerminatedPods: {}
可能的原因及解决办法
事件过滤器未允许Job状态变更事件
当前仅配置了DeleteFunc过滤,但默认的UpdateFunc只会在对象Generation字段变更时触发事件,而Job状态更新属于Status字段变更,不会修改Generation。需要显式实现UpdateFunc,让状态变更事件能触发Reconcile:WithEventFilter(predicate.Funcs{ DeleteFunc: func(e event.DeleteEvent) bool { return false }, UpdateFunc: func(e event.UpdateEvent) bool { oldJob := e.ObjectOld.(*batchv1.Job) newJob := e.ObjectNew.(*batchv1.Job) // 当Status字段变化时,允许触发事件 return !reflect.DeepEqual(oldJob.Status, newJob.Status) }, }).Job未正确设置所有者引用
Owns(&batchv1.Job{})仅会监听被RequestedBackupAction作为所有者的Job事件。如果创建Job时没有添加指向对应RequestedBackupAction的ownerReferences,控制器无法收到该Job的状态变更通知。生成Job时需补充所有者引用配置:job := &batchv1.Job{ // 其他Job配置 ObjectMeta: metav1.ObjectMeta{ // 其他元数据 OwnerReferences: []metav1.OwnerReference{ *metav1.NewControllerRef(requestedBackupAction, riotkitorgv1alpha1.GroupVersion.WithKind("RequestedBackupAction")), }, Labels: map[string]string{ v1alpha1.LabelTrackingId: trackingId, // 其他标签 }, }, }控制器缓存未同步最新Job状态
Reconcile触发时,控制器本地缓存可能还没同步到Job的最新状态,导致读取到旧数据。可以尝试直接调用API Server查询Job状态(而非依赖缓存),或者添加周期性Reconcile机制,确保即使事件丢失也能定期同步:ctrl.NewControllerManagedBy(mgr). // 其他控制器配置 WithOptions(controller.Options{ Reconciler: r, // 每10分钟触发一次全量Reconcile ReconcileInterval: 10 * time.Minute, }).Job状态变更事件未正常生成
检查Kubernetes集群中是否有Job状态变更的事件记录,执行kubectl get events查看相关事件是否存在,确认API Server是否正常发送状态更新事件。
内容的提问来源于stack exchange,提问作者Krzysztof Wesołowski

