1
0
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:
googs1025
2025-01-02 08:54:39 +08:00
parent f2211e1cef
commit 9c7e01de67
8 changed files with 83 additions and 15 deletions

View File

@@ -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

View File

@@ -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]"),
}, },
} }

View File

@@ -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
}

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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.

View File

@@ -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",

View File

@@ -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,