@@ -17,11 +17,16 @@ limitations under the License.
17
17
package huaweicloud
18
18
19
19
import (
20
+ "context"
20
21
"fmt"
21
22
22
23
apiv1 "k8s.io/api/core/v1"
24
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25
+ "k8s.io/apimachinery/pkg/util/sets"
23
26
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
24
27
huaweicloudsdkasmodel "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/huaweicloud/huaweicloud-sdk-go-v3/services/as/v1/model"
28
+ "k8s.io/client-go/kubernetes"
29
+ "k8s.io/client-go/tools/clientcmd"
25
30
"k8s.io/klog/v2"
26
31
schedulerframework "k8s.io/kubernetes/pkg/scheduler/framework/v1alpha1"
27
32
)
@@ -98,13 +103,26 @@ func (asg *AutoScalingGroup) DeleteNodes(nodes []*apiv1.Node) error {
98
103
return err
99
104
}
100
105
101
- instanceIds := make ([] string , 0 , len ( instances ) )
106
+ instanceSet := sets . NewString ( )
102
107
for _ , instance := range instances {
103
- for _ , n := range nodes {
104
- if n .Spec .ProviderID == instance .Id {
105
- instanceIds = append (instanceIds , instance .Id )
106
- }
108
+ instanceSet .Insert (instance .Id )
109
+ }
110
+
111
+ instanceIds := make ([]string , 0 , len (instances ))
112
+ nodeNames := make ([]string , 0 , len (instances ))
113
+ for _ , node := range nodes {
114
+ providerID := node .Spec .ProviderID
115
+
116
+ // If one of the nodes not belongs to this auto scaling group, means there is something wrong happened,
117
+ // so, we should reject the whole deleting request.
118
+ if ! instanceSet .Has (providerID ) {
119
+ klog .Errorf ("delete node not belongs this node group is not allowed. group: %s, node: %s" , asg .groupID , providerID )
120
+ return fmt .Errorf ("node does not belong to this node group" )
107
121
}
122
+
123
+ klog .V (1 ).Infof ("going to remove node from scaling group. group: %s, node: %s" , asg .groupID , providerID )
124
+ instanceIds = append (instanceIds , providerID )
125
+ nodeNames = append (nodeNames , node .Name )
108
126
}
109
127
110
128
err = asg .cloudServiceManager .DeleteScalingInstances (asg .groupID , instanceIds )
@@ -113,6 +131,12 @@ func (asg *AutoScalingGroup) DeleteNodes(nodes []*apiv1.Node) error {
113
131
return err
114
132
}
115
133
134
+ err = asg .deleteNodesFromCluster (nodeNames )
135
+ if err != nil {
136
+ klog .Warningf ("failed to delete nodes from cluster. error: %v" , err )
137
+ return err
138
+ }
139
+
116
140
return nil
117
141
}
118
142
@@ -202,3 +226,34 @@ func (asg *AutoScalingGroup) Autoprovisioned() bool {
202
226
func (asg * AutoScalingGroup ) String () string {
203
227
return fmt .Sprintf ("group: %s min=%d max=%d" , asg .groupID , asg .minInstanceNumber , asg .maxInstanceNumber )
204
228
}
229
+
230
+ func (asg * AutoScalingGroup ) deleteNodesFromCluster (nodeNames []string ) error {
231
+ restConfig , err := clientcmd .BuildConfigFromFlags ("" , "" )
232
+ if err != nil {
233
+ klog .Warningf ("Failed to delete nodes from cluster due to can not get config. error: %v" , err )
234
+ return err
235
+ }
236
+
237
+ kubeClient , err := kubernetes .NewForConfig (restConfig )
238
+ if err != nil {
239
+ klog .Warningf ("Failed to delete nodes from cluster due to can not get kube-client. error: %v" , err )
240
+ return err
241
+ }
242
+
243
+ var failedNodes []string
244
+ for _ , nodeName := range nodeNames {
245
+ err := kubeClient .CoreV1 ().Nodes ().Delete (context .TODO (), nodeName , metav1.DeleteOptions {})
246
+ if err != nil {
247
+ klog .Warningf ("Failed to delete node from cluster. node: %s, error: %s" , nodeName , err )
248
+ failedNodes = append (failedNodes , nodeName )
249
+ continue
250
+ }
251
+ klog .V (1 ).Infof ("deleted one node from cluster. node name: %s" , nodeName )
252
+ }
253
+
254
+ if len (failedNodes ) != 0 {
255
+ return fmt .Errorf ("failed to delete %d node(s) from cluster" , len (failedNodes ))
256
+ }
257
+
258
+ return nil
259
+ }
0 commit comments