/* Copyright 2021 The Karmada Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package kubernetes import ( "context" "encoding/json" "errors" "fmt" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "k8s.io/klog/v2" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit/utils" ) func (i *CommandInitOption) getKarmadaAPIServerIP() error { if i.KarmadaAPIServerAdvertiseAddress != "" { i.KarmadaAPIServerIP = append(i.KarmadaAPIServerIP, utils.StringToNetIP(i.KarmadaAPIServerAdvertiseAddress)) return nil } nodeClient := i.KubeClientSet.CoreV1().Nodes() masterNodes, err := nodeClient.List(context.TODO(), metav1.ListOptions{LabelSelector: "node-role.kubernetes.io/master"}) if err != nil { return err } if len(masterNodes.Items) == 0 { masterNodes, err = nodeClient.List(context.TODO(), metav1.ListOptions{LabelSelector: "node-role.kubernetes.io/control-plane"}) if err != nil { return err } } if len(masterNodes.Items) == 0 { klog.Warning("The kubernetes cluster does not have a Master role.") } else { for _, v := range masterNodes.Items { i.KarmadaAPIServerIP = append(i.KarmadaAPIServerIP, utils.StringToNetIP(v.Status.Addresses[0].Address)) } return nil } klog.Info("Randomly select 3 Node IPs in the kubernetes cluster.") nodes, err := nodeClient.List(context.TODO(), metav1.ListOptions{}) if err != nil { return err } for number := 0; number < 3; number++ { if number >= len(nodes.Items) { break } i.KarmadaAPIServerIP = append(i.KarmadaAPIServerIP, utils.StringToNetIP(nodes.Items[number].Status.Addresses[0].Address)) } if len(i.KarmadaAPIServerIP) == 0 { return fmt.Errorf("karmada apiserver ip is empty") } return nil } // nodeStatus Check the node status, if it is an unhealthy node, return false. func nodeStatus(nodeConditions []corev1.NodeCondition) bool { for _, v := range nodeConditions { switch v.Type { case corev1.NodeReady: if v.Status != corev1.ConditionTrue { return false } case corev1.NodeMemoryPressure: if v.Status != corev1.ConditionFalse { return false } case corev1.NodeDiskPressure: if v.Status != corev1.ConditionFalse { return false } case corev1.NodeNetworkUnavailable: if v.Status != corev1.ConditionFalse { return false } case corev1.NodePIDPressure: if v.Status != corev1.ConditionFalse { return false } } } return true } // AddNodeSelectorLabels When EtcdStorageMode is hostPath, and EtcdNodeSelectorLabels is empty. // Select a healthy node to add labels, and schedule etcd to that node func (i *CommandInitOption) AddNodeSelectorLabels() error { nodes, err := i.KubeClientSet.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) if err != nil { return err } var etcdNodeName string var etcdSelectorLabels map[string]string for _, v := range nodes.Items { if v.Spec.Taints != nil { continue } if nodeStatus(v.Status.Conditions) { etcdNodeName = v.Name etcdSelectorLabels = v.Labels if etcdSelectorLabels == nil { etcdSelectorLabels = map[string]string{} } break } } if etcdSelectorLabels == nil { return errors.New("failed to find a healthy node for karmada-etcd") } etcdSelectorLabels["karmada.io/etcd"] = "" patchData := map[string]interface{}{"metadata": map[string]map[string]string{"labels": etcdSelectorLabels}} playLoadBytes, _ := json.Marshal(patchData) if _, err := i.KubeClientSet.CoreV1().Nodes().Patch(context.TODO(), etcdNodeName, types.StrategicMergePatchType, playLoadBytes, metav1.PatchOptions{}); err != nil { return err } return nil } func (i *CommandInitOption) isNodeExist(labels string) bool { node, err := i.KubeClientSet.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{LabelSelector: labels}) if err != nil { return false } if len(node.Items) == 0 { return false } klog.Infof("Find the node [ %s ] by label %s", node.Items[0].Name, labels) return true }