Change:
When using PDBs with or (percentage), it is not supported to reference pods via a PDB selector, that do not have a supported controller owner reference: Deployment, ReplicationController, ReplicaSet, and StatefulSet controllers or a resource implementing subresource This is also documented Nevertheless, there are still people who create PDBs a pods without controllers that ignore this. For example PDBs that set , want to block eviction, and node drain (it works for them but the PDB status is invalid). Unfortunately there is no feedback for the user to receive when this happens. The KCM logs is the only place that informs the user when unmanaged pods are found. Which I think is insufficient. There should be some way to inform users about this. Since it cannot be know on admission we probably have to do it when reconciling the PDB and unmanaged pods are found. Options: an event when this is detected - probably needs to be throttled in some way a condition in a PDB status that would be set and admins could monitor these to detect misbehaving PDBs create a PDB create unmanaged pod observe incorrect status because this configuration is unsupported No response <detailsNA </details<detailsNA </details<detailsNA </details<details</details<details</details<details</details
/sig apps
/triage accepted This was discussed during today's sig-apps, we've agreed to add a warning event right next to the log statement from the original description
I'll take this on.
/assign
/reopen I did some more testing for the unsupported controllers and found out that these are covered by the event, so I posted a followup to reflect that The new event should cover only the naked pods
Reopened this issue. <detailsIn response to : /reopen Instructions 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

Discussion:
} // We have unmamanged pods, instead of erroring and hotlooping in disruption controller, log and continue. if len(unmanagedPods) > 0 { <del> klog.V(4).Infof("found unmanaged pods associated with this PDB: %v", unmanagedPods) </del> <ins> klog.Warningf("found unmanaged pods associated with this PDB: %v", unmanagedPods) </ins> dc.recorder.Eventf(pdb, v1.EventTypeWarning, "UnmanagedPods", "Pods selected by this PodDisruptionBudget (selector: %v) were found "+ <del> "to be unmanaged or managed by an unsupported controller (missing a /scale subresource). As a result, the status of the PDB "+ "cannot be calculated correctly, which may result in undefined behavior. To account for these pods please set ".spec.minAvailable" "+ </del> <ins> "to be unmanaged. As a result, the status of the PDB cannot be calculated correctly, which may result in undefined behavior. "+ "To account for these pods please set ".spec.minAvailable" "+ </ins> "field of the PDB to an integer value.", pdb.Spec.Selector) }

dc.rsListerSynced = alwaysReady dc.dListerSynced = alwaysReady dc.ssListerSynced = alwaysReady <del> dc.recorder = record.NewFakeRecorder(10) </del> <ins> dc.recorder = record.NewFakeRecorder(100) </ins> informerFactory.Start(ctx.Done()) informerFactory.WaitForCacheSync(ctx.Done())

dc.sync(ctx, pdbName) ps.VerifyDisruptionAllowed(t, pdbName, 0) <del> verifyUnsupportedControllerEventEmitted(t, dc) </del> <ins> verifyEventEmitted(t, dc, "UnmanagedPods") </ins> }

dc.sync(ctx, pdbName) ps.VerifyDisruptionAllowed(t, pdbName, 0) <del> verifyUnsupportedControllerEventEmitted(t, dc) </del> <ins> verifyEventEmitted(t, dc, "UnmanagedPods") } // Create a pod  with unsupported controller, and verify that a PDB with a percentage // specified won't allow a disruption. func TestUnsupportedControllerPod(t *testing.T) { dc, ps := newFakeDisruptionController() pdb, pdbName := newMinAvailablePodDisruptionBudget(t, intstr.FromString("28%")) add(t, dc.pdbStore, pdb) ctx := context.TODO() dc.sync(ctx, pdbName) // This verifies that when a PDB has 0 pods, disruptions are not allowed. ps.VerifyDisruptionAllowed(t, pdbName, 0) pod, _ := newPod(t, "naked") isController := true pod.OwnerReferences = append(pod.OwnerReferences, metav1.OwnerReference{ APIVersion: "apps.test.io/v1", Kind:       "TestWorkload", Name:       "fake-controller", UID:        "b7329742-8daa-493a-8881-6ca07139172b", Controller: &isController, }) add(t, dc.podStore, pod) dc.sync(ctx, pdbName) ps.VerifyDisruptionAllowed(t, pdbName, 0) verifyEventEmitted(t, dc, "CalculateExpectedPodCountFailed") </ins> } // Verify that disruption controller is not erroring when unmanaged pods are found

add(t, dc.podStore, pod) dc.sync(ctx, pdbName) ps.VerifyNoStatusError(t, pdbName) <del> verifyUnsupportedControllerEventEmitted(t, dc) </del> <ins> verifyEventEmitted(t, dc, "UnmanagedPods") </ins> } // Check if the unmanaged pods are correctly collected or not

t.Fatalf("expected one pod to be unmanaged pod but found %d", len(unmanagedPods)) } ps.VerifyNoStatusError(t, pdbName) <del> verifyUnsupportedControllerEventEmitted(t, dc) </del> <ins> verifyEventEmitted(t, dc, "UnmanagedPods") </ins> } // Verify that we count the scale of a ReplicaSet even when it has no Deployment.

}) } <del> func verifyUnsupportedControllerEventEmitted(t *testing.T, dc *disruptionController) { // Verify that an UnmanagedPod event is generated found := false for e := range dc.recorder.(*record.FakeRecorder).Events { if strings.Contains(e, "managed by an unsupported controller") { found = true break </del> <ins> func verifyEventEmitted(t *testing.T, dc *disruptionController, expectedEvent string) { ticker := time.NewTicker(500 * time.Millisecond) for { select { case e := <-dc.recorder.(*record.FakeRecorder).Events: if strings.Contains(e, expectedEvent) { return } case <-ticker.C: t.Fatalf("Timed out: expected event not generated: %v", expectedEvent) </ins> } } <del> if !found { t.Fatalf("UnmanagedPod event not generated") } </del> } // TestMain adds klog flags to make debugging tests easier.