mirror of
https://github.com/kubernetes-sigs/descheduler.git
synced 2026-01-26 05:14:13 +01:00
feature: add PodsWithResourceClaims parameter in DefaultEvictorArgs PodProtections
Signed-off-by: googs1025 <googs1025@gmail.com>
This commit is contained in:
@@ -182,10 +182,11 @@ The Default Evictor Plugin is used by default for filtering pods before processi
|
|||||||
|
|
||||||
> Setting a value in `extraEnabled` **enables an additional protection rule**. This means the specified type of Pods will be **protected** from eviction.
|
> Setting a value in `extraEnabled` **enables an additional protection rule**. This means the specified type of Pods will be **protected** from eviction.
|
||||||
|
|
||||||
| Value | Meaning |
|
| Value | Meaning |
|
||||||
|--------------------|------------------------------------------------------------------------|
|
|----------------------------|------------------------------------------------------------------|
|
||||||
| `"PodsWithPVC"` | Prevents eviction of Pods using Persistent Volume Claims (PVCs). |
|
| `"PodsWithPVC"` | Prevents eviction of Pods using Persistent Volume Claims (PVCs). |
|
||||||
| `"PodsWithoutPDB"` | Prevents eviction of Pods without a PodDisruptionBudget (PDB). |
|
| `"PodsWithoutPDB"` | Prevents eviction of Pods without a PodDisruptionBudget (PDB). |
|
||||||
|
| `"PodsWithResourceClaims"` | Prevents eviction of Pods using ResourceClaims. |
|
||||||
|
|
||||||
### Example policy
|
### Example policy
|
||||||
|
|
||||||
|
|||||||
@@ -750,7 +750,7 @@ profiles:
|
|||||||
- "DefaultEvictor"
|
- "DefaultEvictor"
|
||||||
`),
|
`),
|
||||||
result: nil,
|
result: nil,
|
||||||
err: fmt.Errorf("in profile ProfileName: invalid pod protection policy in ExtraEnabled: \"InvalidProtection\". Valid options are: [PodsWithPVC PodsWithoutPDB]"),
|
err: fmt.Errorf("in profile ProfileName: invalid pod protection policy in ExtraEnabled: \"InvalidProtection\". Valid options are: [PodsWithPVC PodsWithoutPDB PodsWithResourceClaims]"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "test error when Disables an extra protection",
|
description: "test error when Disables an extra protection",
|
||||||
@@ -802,7 +802,7 @@ profiles:
|
|||||||
- "DefaultEvictor"
|
- "DefaultEvictor"
|
||||||
`),
|
`),
|
||||||
result: nil,
|
result: nil,
|
||||||
err: fmt.Errorf("in profile ProfileName: invalid pod protection policy in ExtraEnabled: \"DaemonSetPods\". Valid options are: [PodsWithPVC PodsWithoutPDB]"),
|
err: fmt.Errorf("in profile ProfileName: invalid pod protection policy in ExtraEnabled: \"DaemonSetPods\". Valid options are: [PodsWithPVC PodsWithoutPDB PodsWithResourceClaims]"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -211,3 +211,17 @@ func evictionConstraintsForIgnorePodsWithoutPDB(ignorePodsWithoutPDB bool, handl
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func evictionConstraintsForResourceClaimsPods(protectionEnabled bool) []constraint {
|
||||||
|
if protectionEnabled {
|
||||||
|
return []constraint{
|
||||||
|
func(pod *v1.Pod) error {
|
||||||
|
if utils.IsPodWithResourceClaims(pod) {
|
||||||
|
return fmt.Errorf("pod has ResourceClaims and descheduler is configured to protect ResourceClaims pods")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ func applyEffectivePodProtections(d *DefaultEvictor, podProtections []PodProtect
|
|||||||
applyDaemonSetPodsProtection(d, protectionMap)
|
applyDaemonSetPodsProtection(d, protectionMap)
|
||||||
applyPvcPodsProtection(d, protectionMap)
|
applyPvcPodsProtection(d, protectionMap)
|
||||||
applyPodsWithoutPDBProtection(d, protectionMap, handle)
|
applyPodsWithoutPDBProtection(d, protectionMap, handle)
|
||||||
|
applyPodsWithResourceClaimsProtection(d, protectionMap)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -168,6 +169,11 @@ func applyPodsWithoutPDBProtection(d *DefaultEvictor, protectionMap map[PodProte
|
|||||||
d.constraints = append(d.constraints, evictionConstraintsForIgnorePodsWithoutPDB(isProtectionEnabled, handle)...)
|
d.constraints = append(d.constraints, evictionConstraintsForIgnorePodsWithoutPDB(isProtectionEnabled, handle)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyPodsWithResourceClaimsProtection(d *DefaultEvictor, protectionMap map[PodProtection]bool) {
|
||||||
|
isProtectionEnabled := protectionMap[PodsWithResourceClaims]
|
||||||
|
d.constraints = append(d.constraints, evictionConstraintsForResourceClaimsPods(isProtectionEnabled)...)
|
||||||
|
}
|
||||||
|
|
||||||
// getEffectivePodProtections determines which policies are currently active.
|
// getEffectivePodProtections determines which policies are currently active.
|
||||||
// It supports both new-style (PodProtections) and legacy-style flags.
|
// It supports both new-style (PodProtections) and legacy-style flags.
|
||||||
func getEffectivePodProtections(args *DefaultEvictorArgs) []PodProtection {
|
func getEffectivePodProtections(args *DefaultEvictorArgs) []PodProtection {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
"sigs.k8s.io/descheduler/pkg/api"
|
"sigs.k8s.io/descheduler/pkg/api"
|
||||||
evictionutils "sigs.k8s.io/descheduler/pkg/descheduler/evictions/utils"
|
evictionutils "sigs.k8s.io/descheduler/pkg/descheduler/evictions/utils"
|
||||||
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
|
podutil "sigs.k8s.io/descheduler/pkg/descheduler/pod"
|
||||||
@@ -860,6 +861,24 @@ func TestDefaultEvictorFilter(t *testing.T) {
|
|||||||
},
|
},
|
||||||
result: false,
|
result: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
description: "Pod with ResourceClaims is not evicted because 'PodsWithResourceClaims' is in extraPodProtections",
|
||||||
|
pods: []*v1.Pod{
|
||||||
|
test.BuildTestPod("p20", 400, 0, n1.Name, func(pod *v1.Pod) {
|
||||||
|
pod.ObjectMeta.OwnerReferences = test.GetNormalPodOwnerRefList()
|
||||||
|
pod.Spec.ResourceClaims = []v1.PodResourceClaim{
|
||||||
|
{
|
||||||
|
Name: "test-claim",
|
||||||
|
ResourceClaimName: ptr.To("test-resource-claim"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
podProtections: PodProtections{
|
||||||
|
ExtraEnabled: []PodProtection{PodsWithResourceClaims},
|
||||||
|
},
|
||||||
|
result: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testCases {
|
for _, test := range testCases {
|
||||||
@@ -1049,6 +1068,26 @@ func TestGetEffectivePodProtections_TableDriven(t *testing.T) {
|
|||||||
},
|
},
|
||||||
wantResult: []PodProtection{PodsWithLocalStorage, SystemCriticalPods, PodsWithPVC},
|
wantResult: []PodProtection{PodsWithLocalStorage, SystemCriticalPods, PodsWithPVC},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "NewConfig_EnableOneExtra(PodsWithResourceClaims)_ReturnsDefaultPlusOne",
|
||||||
|
args: &DefaultEvictorArgs{
|
||||||
|
PodProtections: PodProtections{
|
||||||
|
DefaultDisabled: []PodProtection{},
|
||||||
|
ExtraEnabled: []PodProtection{PodsWithResourceClaims},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantResult: append(defaultSet, PodsWithResourceClaims),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "NewConfig_DisableAndEnable_ReturnsModifiedSet",
|
||||||
|
args: &DefaultEvictorArgs{
|
||||||
|
PodProtections: PodProtections{
|
||||||
|
DefaultDisabled: []PodProtection{FailedBarePods, DaemonSetPods},
|
||||||
|
ExtraEnabled: []PodProtection{PodsWithPVC, PodsWithResourceClaims},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantResult: []PodProtection{PodsWithLocalStorage, SystemCriticalPods, PodsWithPVC, PodsWithResourceClaims},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|||||||
@@ -55,12 +55,13 @@ type DefaultEvictorArgs struct {
|
|||||||
type PodProtection string
|
type PodProtection string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PodsWithLocalStorage PodProtection = "PodsWithLocalStorage"
|
PodsWithLocalStorage PodProtection = "PodsWithLocalStorage"
|
||||||
DaemonSetPods PodProtection = "DaemonSetPods"
|
DaemonSetPods PodProtection = "DaemonSetPods"
|
||||||
SystemCriticalPods PodProtection = "SystemCriticalPods"
|
SystemCriticalPods PodProtection = "SystemCriticalPods"
|
||||||
FailedBarePods PodProtection = "FailedBarePods"
|
FailedBarePods PodProtection = "FailedBarePods"
|
||||||
PodsWithPVC PodProtection = "PodsWithPVC"
|
PodsWithPVC PodProtection = "PodsWithPVC"
|
||||||
PodsWithoutPDB PodProtection = "PodsWithoutPDB"
|
PodsWithoutPDB PodProtection = "PodsWithoutPDB"
|
||||||
|
PodsWithResourceClaims PodProtection = "PodsWithResourceClaims"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PodProtections holds the list of enabled and disabled protection policies.
|
// PodProtections holds the list of enabled and disabled protection policies.
|
||||||
@@ -98,9 +99,11 @@ var defaultPodProtections = []PodProtection{
|
|||||||
// Currently supported extra policies:
|
// Currently supported extra policies:
|
||||||
// - PodsWithPVC: Protects pods using PersistentVolumeClaims.
|
// - PodsWithPVC: Protects pods using PersistentVolumeClaims.
|
||||||
// - PodsWithoutPDB: Protects pods lacking a PodDisruptionBudget.
|
// - PodsWithoutPDB: Protects pods lacking a PodDisruptionBudget.
|
||||||
|
// - PodsWithResourceClaims: Protects pods using ResourceClaims.
|
||||||
var extraPodProtections = []PodProtection{
|
var extraPodProtections = []PodProtection{
|
||||||
PodsWithPVC,
|
PodsWithPVC,
|
||||||
PodsWithoutPDB,
|
PodsWithoutPDB,
|
||||||
|
PodsWithResourceClaims,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoEvictionPolicy dictates whether a no-eviction policy is preferred or mandatory.
|
// NoEvictionPolicy dictates whether a no-eviction policy is preferred or mandatory.
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ func TestValidateDefaultEvictorArgs(t *testing.T) {
|
|||||||
ExtraEnabled: []PodProtection{"InvalidPolicy"},
|
ExtraEnabled: []PodProtection{"InvalidPolicy"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
errInfo: fmt.Errorf(`invalid pod protection policy in ExtraEnabled: "InvalidPolicy". Valid options are: [PodsWithPVC PodsWithoutPDB]`),
|
errInfo: fmt.Errorf(`invalid pod protection policy in ExtraEnabled: "InvalidPolicy". Valid options are: [PodsWithPVC PodsWithoutPDB PodsWithResourceClaims]`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid ExtraEnabled: Misspelled policy",
|
name: "Invalid ExtraEnabled: Misspelled policy",
|
||||||
@@ -131,7 +131,7 @@ func TestValidateDefaultEvictorArgs(t *testing.T) {
|
|||||||
ExtraEnabled: []PodProtection{"PodsWithPVCC"},
|
ExtraEnabled: []PodProtection{"PodsWithPVCC"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
errInfo: fmt.Errorf(`invalid pod protection policy in ExtraEnabled: "PodsWithPVCC". Valid options are: [PodsWithPVC PodsWithoutPDB]`),
|
errInfo: fmt.Errorf(`invalid pod protection policy in ExtraEnabled: "PodsWithPVCC". Valid options are: [PodsWithPVC PodsWithoutPDB PodsWithResourceClaims]`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid ExtraEnabled: Policy from DefaultDisabled list",
|
name: "Invalid ExtraEnabled: Policy from DefaultDisabled list",
|
||||||
@@ -140,7 +140,7 @@ func TestValidateDefaultEvictorArgs(t *testing.T) {
|
|||||||
ExtraEnabled: []PodProtection{DaemonSetPods},
|
ExtraEnabled: []PodProtection{DaemonSetPods},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
errInfo: fmt.Errorf(`invalid pod protection policy in ExtraEnabled: "DaemonSetPods". Valid options are: [PodsWithPVC PodsWithoutPDB]`),
|
errInfo: fmt.Errorf(`invalid pod protection policy in ExtraEnabled: "DaemonSetPods". Valid options are: [PodsWithPVC PodsWithoutPDB PodsWithResourceClaims]`),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Invalid DefaultDisabled: Unknown policy",
|
name: "Invalid DefaultDisabled: Unknown policy",
|
||||||
|
|||||||
@@ -120,6 +120,11 @@ func IsPodWithPVC(pod *v1.Pod) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsPodWithResourceClaims returns true if the pod has resource claims.
|
||||||
|
func IsPodWithResourceClaims(pod *v1.Pod) bool {
|
||||||
|
return len(pod.Spec.ResourceClaims) != 0
|
||||||
|
}
|
||||||
|
|
||||||
// IsPodCoveredByPDB returns true if the pod is covered by at least one PodDisruptionBudget.
|
// IsPodCoveredByPDB returns true if the pod is covered by at least one PodDisruptionBudget.
|
||||||
func IsPodCoveredByPDB(pod *v1.Pod, lister policyv1.PodDisruptionBudgetLister) (bool, error) {
|
func IsPodCoveredByPDB(pod *v1.Pod, lister policyv1.PodDisruptionBudgetLister) (bool, error) {
|
||||||
// We can't use the GetPodPodDisruptionBudgets expansion method here because it treats no pdb as an error,
|
// We can't use the GetPodPodDisruptionBudgets expansion method here because it treats no pdb as an error,
|
||||||
|
|||||||
Reference in New Issue
Block a user