@@ -78,24 +78,36 @@ func (d *RemovePodsViolatingInterPodAntiAffinity) Name() string {
7878}
7979
8080func (d * RemovePodsViolatingInterPodAntiAffinity ) Deschedule (ctx context.Context , nodes []* v1.Node ) * frameworktypes.Status {
81+ podsList , err := d .handle .ClientSet ().CoreV1 ().Pods ("" ).List (ctx , metav1.ListOptions {})
82+ if err != nil {
83+ return & frameworktypes.Status {
84+ Err : fmt .Errorf ("error listing all pods: %v" , err ),
85+ }
86+ }
87+
88+ podsInANamespace := groupByNamespace (podsList )
89+
90+ runningPodFilter := func (pod * v1.Pod ) bool {
91+ return pod .Status .Phase != v1 .PodSucceeded && pod .Status .Phase != v1 .PodFailed
92+ }
93+ podsOnANode := groupByNodeName (podsList , podutil .WrapFilterFuncs (runningPodFilter , d .podFilter ))
94+
95+ nodeMap := createNodeMap (nodes )
96+
8197loop:
8298 for _ , node := range nodes {
8399 klog .V (1 ).InfoS ("Processing node" , "node" , klog .KObj (node ))
84- pods , err := podutil .ListPodsOnANode (node .Name , d .handle .GetPodsAssignedToNodeFunc (), d .podFilter )
85- if err != nil {
86- return & frameworktypes.Status {
87- Err : fmt .Errorf ("error listing pods: %v" , err ),
88- }
89- }
90- // sort the evictable Pods based on priority, if there are multiple pods with same priority, they are sorted based on QoS tiers.
100+ pods := podsOnANode [node .Name ]
101+ // sort the evict-able Pods based on priority, if there are multiple pods with same priority, they are sorted based on QoS tiers.
91102 podutil .SortPodsBasedOnPriorityLowToHigh (pods )
92103 totalPods := len (pods )
93104 for i := 0 ; i < totalPods ; i ++ {
94- if checkPodsWithAntiAffinityExist (pods [i ], pods ) && d .handle .Evictor ().Filter (pods [i ]) && d .handle .Evictor ().PreEvictionFilter (pods [i ]) {
105+ if checkPodsWithAntiAffinityExist (pods [i ], podsInANamespace , nodeMap ) && d .handle .Evictor ().Filter (pods [i ]) && d .handle .Evictor ().PreEvictionFilter (pods [i ]) {
95106 if d .handle .Evictor ().Evict (ctx , pods [i ], evictions.EvictOptions {}) {
96107 // Since the current pod is evicted all other pods which have anti-affinity with this
97108 // pod need not be evicted.
98- // Update pods.
109+ // Update allPods.
110+ podsInANamespace = removePodFromNamespaceMap (pods [i ], podsInANamespace )
99111 pods = append (pods [:i ], pods [i + 1 :]... )
100112 i --
101113 totalPods --
@@ -109,8 +121,54 @@ loop:
109121 return nil
110122}
111123
124+ func removePodFromNamespaceMap (podToRemove * v1.Pod , podMap map [string ][]* v1.Pod ) map [string ][]* v1.Pod {
125+ podList , ok := podMap [podToRemove .Namespace ]
126+ if ! ok {
127+ return podMap
128+ }
129+ for i := 0 ; i < len (podList ); i ++ {
130+ podToCheck := podList [i ]
131+ if podToRemove .Name == podToCheck .Name {
132+ podMap [podToRemove .Namespace ] = append (podList [:i ], podList [i + 1 :]... )
133+ return podMap
134+ }
135+ }
136+ return podMap
137+ }
138+
139+ func groupByNamespace (pods * v1.PodList ) map [string ][]* v1.Pod {
140+ m := make (map [string ][]* v1.Pod )
141+ for i := 0 ; i < len (pods .Items ); i ++ {
142+ pod := & (pods .Items [i ])
143+ m [pod .Namespace ] = append (m [pod .Namespace ], pod )
144+ }
145+ return m
146+ }
147+
148+ func groupByNodeName (pods * v1.PodList , filter podutil.FilterFunc ) map [string ][]* v1.Pod {
149+ m := make (map [string ][]* v1.Pod )
150+ if filter == nil {
151+ filter = func (p * v1.Pod ) bool { return true }
152+ }
153+ for i := 0 ; i < len (pods .Items ); i ++ {
154+ pod := & (pods .Items [i ])
155+ if filter (pod ) {
156+ m [pod .Spec .NodeName ] = append (m [pod .Spec .NodeName ], pod )
157+ }
158+ }
159+ return m
160+ }
161+
162+ func createNodeMap (nodes []* v1.Node ) map [string ]* v1.Node {
163+ m := make (map [string ]* v1.Node , len (nodes ))
164+ for _ , node := range nodes {
165+ m [node .GetName ()] = node
166+ }
167+ return m
168+ }
169+
112170// checkPodsWithAntiAffinityExist checks if there are other pods on the node that the current pod cannot tolerate.
113- func checkPodsWithAntiAffinityExist (pod * v1.Pod , pods [] * v1.Pod ) bool {
171+ func checkPodsWithAntiAffinityExist (pod * v1.Pod , pods map [ string ][] * v1.Pod , nodeMap map [ string ] * v1. Node ) bool {
114172 affinity := pod .Spec .Affinity
115173 if affinity != nil && affinity .PodAntiAffinity != nil {
116174 for _ , term := range getPodAntiAffinityTerms (affinity .PodAntiAffinity ) {
@@ -120,16 +178,52 @@ func checkPodsWithAntiAffinityExist(pod *v1.Pod, pods []*v1.Pod) bool {
120178 klog .ErrorS (err , "Unable to convert LabelSelector into Selector" )
121179 return false
122180 }
123- for _ , existingPod := range pods {
124- if existingPod .Name != pod .Name && utils .PodMatchesTermsNamespaceAndSelector (existingPod , namespaces , selector ) {
125- return true
181+ for namespace := range namespaces {
182+ for _ , existingPod := range pods [namespace ] {
183+ if existingPod .Name != pod .Name && utils .PodMatchesTermsNamespaceAndSelector (existingPod , namespaces , selector ) {
184+ node , ok := nodeMap [pod .Spec .NodeName ]
185+ if ! ok {
186+ continue
187+ }
188+ nodeHavingExistingPod , ok := nodeMap [existingPod .Spec .NodeName ]
189+ if ! ok {
190+ continue
191+ }
192+ if hasSameLabelValue (node , nodeHavingExistingPod , term .TopologyKey ) {
193+ klog .V (1 ).InfoS ("Found Pods violating PodAntiAffinity" , "pod to evicted" , klog .KObj (pod ))
194+ return true
195+ }
196+ }
126197 }
127198 }
128199 }
129200 }
130201 return false
131202}
132203
204+ func hasSameLabelValue (node1 , node2 * v1.Node , key string ) bool {
205+ if node1 .Name == node2 .Name {
206+ return true
207+ }
208+ node1Labels := node1 .Labels
209+ if node1Labels == nil {
210+ return false
211+ }
212+ node2Labels := node2 .Labels
213+ if node2Labels == nil {
214+ return false
215+ }
216+ value1 , ok := node1Labels [key ]
217+ if ! ok {
218+ return false
219+ }
220+ value2 , ok := node2Labels [key ]
221+ if ! ok {
222+ return false
223+ }
224+ return value1 == value2
225+ }
226+
133227// getPodAntiAffinityTerms gets the antiaffinity terms for the given pod.
134228func getPodAntiAffinityTerms (podAntiAffinity * v1.PodAntiAffinity ) (terms []v1.PodAffinityTerm ) {
135229 if podAntiAffinity != nil {
0 commit comments