77 "github.com/rs/zerolog/log"
88
99 "github.com/p-program/kube-killer/core"
10+ v1 "k8s.io/api/core/v1"
1011 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1112 "k8s.io/apimachinery/pkg/types"
1213 "k8s.io/apimachinery/pkg/util/strategicpatch"
@@ -26,12 +27,15 @@ func NewNodeKiller(nodeName string) (*NodeKiller, error) {
2627 if err != nil {
2728 return nil , err
2829 }
29- k := NodeKiller {client : clientset }
30+ k := NodeKiller {
31+ client : clientset ,
32+ nodeName : nodeName ,
33+ }
3034 var gracePeriodSeconds int64 = 0
3135 k .deleteOption = metav1.DeleteOptions {
3236 GracePeriodSeconds : & gracePeriodSeconds ,
3337 }
34- return & k , err
38+ return & k , nil
3539}
3640
3741func (k * NodeKiller ) BlackHand () * NodeKiller {
@@ -79,9 +83,71 @@ func (k *NodeKiller) Kill() error {
7983 if err != nil {
8084 return err
8185 }
82- //# TODO:驱逐除了ds以外所有的pod
83- //kubectl drain $node --ignore-daemonsets
86+ // Drain all pods from the node except DaemonSet pods
87+ // Similar to: kubectl drain $node --ignore-daemonsets
88+ err = k .drainNodePods (clientset )
89+ if err != nil {
90+ return err
91+ }
8492 }
8593 //kubectl delete $node
8694 return nil
8795}
96+
97+ // drainNodePods evicts all pods from the node except DaemonSet pods
98+ // Similar to: kubectl drain $node --ignore-daemonsets
99+ func (k * NodeKiller ) drainNodePods (clientset * kubernetes.Clientset ) error {
100+ log .Info ().Msgf ("Draining pods from node %s (ignoring DaemonSet pods)" , k .nodeName )
101+
102+ // Get all pods on this node
103+ fieldSelector := "spec.nodeName=" + k .nodeName
104+ pods , err := clientset .CoreV1 ().Pods ("" ).List (context .TODO (), metav1.ListOptions {
105+ FieldSelector : fieldSelector ,
106+ })
107+ if err != nil {
108+ return err
109+ }
110+
111+ evictedCount := 0
112+ for _ , pod := range pods .Items {
113+ // Check if pod belongs to a DaemonSet
114+ if k .isDaemonSetPod (pod ) {
115+ log .Info ().Msgf ("Skipping DaemonSet pod %s/%s" , pod .Namespace , pod .Name )
116+ continue
117+ }
118+
119+ log .Info ().Msgf ("Evicting pod %s/%s from node %s" , pod .Namespace , pod .Name , k .nodeName )
120+ err = clientset .CoreV1 ().Pods (pod .Namespace ).Delete (context .TODO (), pod .Name , k .deleteOption )
121+ if err != nil {
122+ log .Error ().Err (err ).Msgf ("Failed to evict pod %s/%s" , pod .Namespace , pod .Name )
123+ continue
124+ }
125+ evictedCount ++
126+ }
127+
128+ log .Info ().Msgf ("Evicted %d pods from node %s" , evictedCount , k .nodeName )
129+ return nil
130+ }
131+
132+ // isDaemonSetPod checks if a pod belongs to a DaemonSet by examining OwnerReferences
133+ func (k * NodeKiller ) isDaemonSetPod (pod v1.Pod ) bool {
134+ for _ , ownerRef := range pod .OwnerReferences {
135+ if ownerRef .Kind == "DaemonSet" {
136+ return true
137+ }
138+ // Check if it's owned by a ReplicaSet that belongs to a DaemonSet
139+ // This is a more thorough check, but for simplicity, we'll check direct ownership
140+ if ownerRef .Kind == "ReplicaSet" {
141+ // Get the ReplicaSet to check its owner
142+ rs , err := k .client .AppsV1 ().ReplicaSets (pod .Namespace ).Get (context .TODO (), ownerRef .Name , metav1.GetOptions {})
143+ if err == nil {
144+ for _ , rsOwnerRef := range rs .OwnerReferences {
145+ if rsOwnerRef .Kind == "DaemonSet" {
146+ return true
147+ }
148+ }
149+ }
150+ }
151+ }
152+ return false
153+ }
0 commit comments