Change:
Changing the label on a job template in a CronJob causes any Jobs held by the successful/failed history parameters to stop being tracked, so they never get cleaned up. Jobs with labels that don't match the (upgraded) CronJob, but still have an owner reference, should be subject to the history limit. a CronJob with a job template containing label , and non-zero history limit the CronJob to run and generate some Jobs (default 3 successful, 1 failed) the CronJob with a job template containing label the CronJob to run and generate some more Jobs there are more than 3 successful Jobs/1 failed Job! I believe this is the relevant code: The CronJob controller finds Jobs that it should care about by matching on the labels in the job template, this obviously breaks if the labels in the job template change. 21 Self-hosted No response No response No response No response_
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig apps
Experiencing another side-effect of this bug. If job template labels are updated while a cronjob has status (a scheduled job is running), then that cronjob gets stuck in . The cause seems to be the same as describes: once the job template labels are updated, cronjob controller V2 loses track of the jobs with the old labels, and therefore never updates the status of that active cronjob to indicate that the scheduled job has completed.
/assign

Discussion:
} func (jm *ControllerV2) getJobsToBeReconciled(cronJob *batchv1.CronJob) ([]*batchv1.Job, error) { <del> var jobSelector labels.Selector if len(cronJob.Spec.JobTemplate.Labels) == 0 { jobSelector = labels.Everything() } else { jobSelector = labels.Set(cronJob.Spec.JobTemplate.Labels).AsSelector() } jobList, err := jm.jobLister.Jobs(cronJob.Namespace).List(jobSelector) </del> <ins> // list all jobs: there may be jobs with labels that don't match the template anymore, // but that still have a ControllerRef to the given cronjob jobList, err := jm.jobLister.Jobs(cronJob.Namespace).List(labels.Everything()) </ins> if err != nil { return nil, err }

"github.com/robfig/cron/v3" batchv1 "k8s.io/api/batch/v1" <del> "k8s.io/api/core/v1" </del> <ins> v1 "k8s.io/api/core/v1" </ins> "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime"

}, expected: []*batchv1.Job{}, }, <ins> { name: "test getting jobs whose labels do not match job template", cronJob: &batchv1.CronJob{ ObjectMeta: metav1.ObjectMeta{Namespace: "foo-ns", Name: "fooer"}, Spec: batchv1.CronJobSpec{JobTemplate: batchv1.JobTemplateSpec{ ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"key": "value"}}, }}, }, jobs: []runtime.Object{ &batchv1.Job{ObjectMeta: metav1.ObjectMeta{ Namespace:       "foo-ns", Name:            "foo-fooer-owner-ref", Labels:          map[string]string{"key": "different-value"}, OwnerReferences: []metav1.OwnerReference{{Name: "fooer", Controller: &trueRef}}}, }, &batchv1.Job{ObjectMeta: metav1.ObjectMeta{ Namespace:       "foo-ns", Name:            "foo-other-owner-ref", Labels:          map[string]string{"key": "different-value"}, OwnerReferences: []metav1.OwnerReference{{Name: "another-cronjob", Controller: &trueRef}}}, }, }, expected: []*batchv1.Job{{ ObjectMeta: metav1.ObjectMeta{ Namespace:       "foo-ns", Name:            "foo-fooer-owner-ref", Labels:          map[string]string{"key": "different-value"}, OwnerReferences: []metav1.OwnerReference{{Name: "fooer", Controller: &trueRef}}}, }}, }, </ins> } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {