github.com/gocrane/crane@v0.11.0/pkg/utils/node.go (about) 1 package utils 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strconv" 7 8 "golang.org/x/net/context" 9 v1 "k8s.io/api/core/v1" 10 "k8s.io/apimachinery/pkg/api/errors" 11 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 12 clientset "k8s.io/client-go/kubernetes" 13 kubeclient "k8s.io/client-go/kubernetes" 14 corelisters "k8s.io/client-go/listers/core/v1" 15 "k8s.io/klog/v2" 16 kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1" 17 kubeletconfiginternal "k8s.io/kubernetes/pkg/kubelet/apis/config" 18 kubeletscheme "k8s.io/kubernetes/pkg/kubelet/apis/config/scheme" 19 20 topologyapi "github.com/gocrane/api/topology/v1alpha1" 21 ) 22 23 const defaultRetryTimes = 3 24 25 // UpdateNodeConditionsStatues be used to update node condition with check whether it needs to update 26 func UpdateNodeConditionsStatues(client clientset.Interface, nodeLister corelisters.NodeLister, nodeName string, condition v1.NodeCondition, retry *uint64) (*v1.Node, error) { 27 28 for i := uint64(0); i < GetUint64withDefault(retry, defaultRetryTimes); i++ { 29 node, err := nodeLister.Get(nodeName) 30 if err != nil { 31 return nil, err 32 } 33 34 updateNode, needUpdate := updateNodeConditions(node, condition) 35 if needUpdate { 36 klog.Warningf("Updating node condition %v", condition) 37 if updateNode, err = client.CoreV1().Nodes().UpdateStatus(context.Background(), updateNode, metav1.UpdateOptions{}); err != nil { 38 if errors.IsConflict(err) { 39 continue 40 } else { 41 return nil, err 42 } 43 } 44 } 45 46 return updateNode, nil 47 } 48 49 return nil, fmt.Errorf("update node failed, conflict too more times") 50 } 51 52 func updateNodeConditions(node *v1.Node, condition v1.NodeCondition) (*v1.Node, bool) { 53 updatedNode := node.DeepCopy() 54 55 // loop and found the condition type 56 for i, cond := range updatedNode.Status.Conditions { 57 if cond.Type == condition.Type { 58 if cond.Status == condition.Status { 59 return updatedNode, false 60 } else { 61 updatedNode.Status.Conditions[i] = condition 62 return updatedNode, true 63 } 64 } 65 } 66 67 // not found the condition, to add the condition to the end 68 updatedNode.Status.Conditions = append(updatedNode.Status.Conditions, condition) 69 70 return updatedNode, true 71 } 72 73 // UpdateNodeTaints be used to update node taints with check whether it needs to update 74 func UpdateNodeTaints(client clientset.Interface, nodeLister corelisters.NodeLister, nodeName string, taint v1.Taint, retry *uint64) (*v1.Node, error) { 75 76 for i := uint64(0); i < GetUint64withDefault(retry, defaultRetryTimes); i++ { 77 node, err := nodeLister.Get(nodeName) 78 if err != nil { 79 return nil, err 80 } 81 82 updateNode, needUpdate := updateNodeTaints(node, taint) 83 if needUpdate { 84 if updateNode, err = client.CoreV1().Nodes().Update(context.Background(), updateNode, metav1.UpdateOptions{}); err != nil { 85 if errors.IsConflict(err) { 86 continue 87 } else { 88 return nil, err 89 } 90 } 91 } 92 93 return updateNode, nil 94 } 95 96 return nil, fmt.Errorf("failed to update node taints after %d retries", GetUint64withDefault(retry, defaultRetryTimes)) 97 } 98 99 func updateNodeTaints(node *v1.Node, taint v1.Taint) (*v1.Node, bool) { 100 updatedNode := node.DeepCopy() 101 102 for i, t := range updatedNode.Spec.Taints { 103 if t.Key == taint.Key { 104 if (t.Value == taint.Value) && (t.Effect == taint.Effect) { 105 return updatedNode, false 106 } else { 107 updatedNode.Spec.Taints[i] = taint 108 return updatedNode, true 109 } 110 } 111 } 112 113 // not found the taint, to add the taint 114 updatedNode.Spec.Taints = append(updatedNode.Spec.Taints, taint) 115 return updatedNode, true 116 } 117 118 func RemoveNodeTaints(client clientset.Interface, nodeLister corelisters.NodeLister, nodeName string, taint v1.Taint, retry *uint64) (*v1.Node, error) { 119 for i := uint64(0); i < GetUint64withDefault(retry, defaultRetryTimes); i++ { 120 node, err := nodeLister.Get(nodeName) 121 if err != nil { 122 return nil, err 123 } 124 125 updateNode, needUpdate := removeNodeTaints(node, taint) 126 if needUpdate { 127 klog.V(4).Infof("Removing node taint %v", taint) 128 if updateNode, err = client.CoreV1().Nodes().Update(context.Background(), updateNode, metav1.UpdateOptions{}); err != nil { 129 if errors.IsConflict(err) { 130 continue 131 } else { 132 return nil, err 133 } 134 } 135 } 136 137 return updateNode, nil 138 } 139 140 return nil, fmt.Errorf("update node failed, conflict too more times") 141 } 142 143 func removeNodeTaints(node *v1.Node, taint v1.Taint) (*v1.Node, bool) { 144 145 updatedNode := node.DeepCopy() 146 147 var foundTaint = false 148 var taints []v1.Taint 149 150 for _, t := range updatedNode.Spec.Taints { 151 if t.Key == taint.Key && t.Effect == taint.Effect { 152 foundTaint = true 153 } else { 154 taints = append(taints, t) 155 } 156 } 157 158 // found the taint, remove it 159 if foundTaint { 160 updatedNode.Spec.Taints = taints 161 return updatedNode, true 162 } 163 164 return updatedNode, false 165 } 166 167 // IsNodeAwareOfTopology returns default topology awareness policy. 168 func IsNodeAwareOfTopology(attr map[string]string) *bool { 169 if val, exist := attr[topologyapi.LabelNodeTopologyAwarenessKey]; exist { 170 if awareness, err := strconv.ParseBool(val); err == nil { 171 return &awareness 172 } 173 } 174 return nil 175 } 176 177 // BuildZoneName returns the canonical name of a NUMA zone from its ID. 178 func BuildZoneName(nodeID int) string { 179 return fmt.Sprintf("node%d", nodeID) 180 } 181 182 func GetKubeletConfig(ctx context.Context, c kubeclient.Interface, hostname string) (*kubeletconfiginternal.KubeletConfiguration, error) { 183 result, err := c.CoreV1().RESTClient().Get(). 184 Resource("nodes"). 185 SubResource("proxy"). 186 Name(hostname). 187 Suffix("configz"). 188 Do(ctx). 189 Raw() 190 if err != nil { 191 return nil, err 192 } 193 194 // This hack because /configz reports the following structure: 195 // {"kubeletconfig": {the JSON representation of kubeletconfigv1beta1.KubeletConfiguration}} 196 type configzWrapper struct { 197 ComponentConfig kubeletconfigv1beta1.KubeletConfiguration `json:"kubeletconfig"` 198 } 199 configz := configzWrapper{} 200 201 if err = json.Unmarshal(result, &configz); err != nil { 202 return nil, fmt.Errorf("failed to unmarshal json for kubelet config: %v", err) 203 } 204 205 scheme, _, err := kubeletscheme.NewSchemeAndCodecs() 206 if err != nil { 207 return nil, err 208 } 209 cfg := kubeletconfiginternal.KubeletConfiguration{} 210 if err = scheme.Convert(&configz.ComponentConfig, &cfg, nil); err != nil { 211 return nil, err 212 } 213 214 return &cfg, nil 215 }