github.com/sealerio/sealer@v0.11.1-0.20240507115618-f4f89c5853ae/pkg/runtime/kubernetes/utils.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package kubernetes 16 17 import ( 18 "context" 19 "fmt" 20 "net" 21 "path" 22 "sort" 23 "strconv" 24 "strings" 25 "time" 26 27 "golang.org/x/sync/errgroup" 28 corev1 "k8s.io/api/core/v1" 29 "k8s.io/apimachinery/pkg/util/wait" 30 "k8s.io/client-go/tools/clientcmd" 31 runtimeClient "sigs.k8s.io/controller-runtime/pkg/client" 32 33 "github.com/sealerio/sealer/common" 34 "github.com/sealerio/sealer/pkg/ipvs" 35 "github.com/sealerio/sealer/pkg/runtime" 36 netutils "github.com/sealerio/sealer/utils/net" 37 "github.com/sealerio/sealer/utils/shellcommand" 38 ) 39 40 const ( 41 AuditPolicyYml = "audit-policy.yml" 42 KubeadmFileYml = "/etc/kubernetes/kubeadm.yaml" 43 AdminConf = "admin.conf" 44 ControllerConf = "controller-manager.conf" 45 SchedulerConf = "scheduler.conf" 46 KubeletConf = "kubelet.conf" 47 48 // kube file 49 KUBECONTROLLERCONFIGFILE = "/etc/kubernetes/controller-manager.conf" 50 KUBESCHEDULERCONFIGFILE = "/etc/kubernetes/scheduler.conf" 51 AdminKubeConfPath = "/etc/kubernetes/admin.conf" 52 LvscarePodFileName = "kube-lvscare.yaml" 53 ) 54 55 const ( 56 GetCustomizeCRISocket = "cat /etc/sealerio/cri/socket-path" 57 RemoteCleanCustomizeCRISocket = "rm -f /etc/sealerio/cri/socket-path" 58 RemoteAddEtcHosts = "cat /etc/hosts |grep '%s' || echo '%s' >> /etc/hosts" 59 RemoteReplaceKubeConfig = `grep -qF "apiserver.cluster.local" %s && sed -i 's/apiserver.cluster.local/%s/' %s && sed -i 's/apiserver.cluster.local/%s/' %s` 60 RemoveKubeConfig = "rm -rf /usr/bin/kube* && rm -rf ~/.kube/" 61 RemoteCleanK8sOnHost = `systemctl restart docker kubelet; if which kubeadm > /dev/null 2>&1;then kubeadm reset -f %s;fi && \ 62 rm -rf /etc/kubernetes/ && \ 63 rm -rf /etc/systemd/system/kubelet.service.d && rm -rf /etc/systemd/system/kubelet.service && \ 64 rm -rf /usr/bin/kubeadm && rm -rf /usr/bin/kubelet-pre-start.sh && \ 65 rm -rf /usr/bin/kubelet && rm -rf /usr/bin/kubectl && \ 66 rm -rf /var/lib/kubelet/* && rm -rf /etc/sysctl.d/k8s.conf && \ 67 rm -rf /etc/cni && rm -rf /opt/cni && \ 68 rm -rf /var/lib/etcd/* && rm -rf /var/etcd/* && rm -rf /root/.kube/config 69 ` 70 RemoteRemoveAPIServerEtcHost = "echo \"$(sed \"/%s/d\" /etc/hosts)\" > /etc/hosts" 71 KubeDeleteNode = "kubectl delete node %s" 72 73 RemoteCheckRoute = "seautil route check --host %s" 74 RemoteAddRoute = "seautil route add --host %s --gateway %s" 75 RemoteDelRoute = "if command -v seautil > /dev/null 2>&1; then seautil route del --host %s --gateway %s; fi" 76 ) 77 78 // StaticFile :static file should not be template, will never be changed while initialization. 79 type StaticFile struct { 80 DestinationDir string 81 Name string 82 } 83 84 // MasterStaticFiles Put static files here, can be moved to all master nodes before kubeadm execution 85 var MasterStaticFiles = []*StaticFile{ 86 { 87 DestinationDir: "/etc/kubernetes", 88 Name: AuditPolicyYml, 89 }, 90 } 91 92 // return node name from k8s cluster, if not found, return "" and error is nil 93 func (k *Runtime) getNodeNameByCmd(host net.IP) (string, error) { 94 cli, err := k.GetCurrentRuntimeDriver() 95 if err != nil { 96 return "", err 97 } 98 nodes := &corev1.NodeList{} 99 if err := cli.List(context.Background(), nodes); err != nil { 100 return "", err 101 } 102 103 for _, nodeInfo := range nodes.Items { 104 for _, addr := range nodeInfo.Status.Addresses { 105 if addr.Type == corev1.NodeInternalIP && host.String() == addr.Address { 106 return nodeInfo.Name, nil 107 } 108 } 109 } 110 111 return "", fmt.Errorf("failed to find node name for %s", host.String()) 112 } 113 114 func vlogToStr(vlog int) string { 115 str := strconv.Itoa(vlog) 116 return " -v " + str 117 } 118 119 type CommandType string 120 121 const InitMaster CommandType = "initMaster" 122 const JoinMaster CommandType = "joinMaster" 123 const JoinNode CommandType = "joinNode" 124 125 func (k *Runtime) Command(name CommandType, nodeNameOverride string) (string, error) { 126 //cmds := make(map[CommandType]string) 127 // Please convert your v1beta1 configuration files to v1beta2 using the 128 // "kubeadm config migrate" command of kubeadm v1.15.x, so v1.14 not support multi network interface. 129 cmds := map[CommandType]string{ 130 InitMaster: fmt.Sprintf("kubeadm init --config=%s --upload-certs", KubeadmFileYml), 131 JoinMaster: fmt.Sprintf("kubeadm join --config=%s", KubeadmFileYml), 132 JoinNode: fmt.Sprintf("kubeadm join --config=%s", KubeadmFileYml), 133 } 134 135 v, ok := cmds[name] 136 if !ok { 137 return "", fmt.Errorf("failed to get kubeadm command: %v", cmds) 138 } 139 if nodeNameOverride != "" { 140 v = fmt.Sprintf("%s --node-name %s", v, nodeNameOverride) 141 } 142 143 if runtime.IsInContainer() { 144 return fmt.Sprintf("%s%s%s", v, vlogToStr(k.Config.Vlog), " --ignore-preflight-errors=all"), nil 145 } 146 if name == InitMaster || name == JoinMaster { 147 return fmt.Sprintf("%s%s%s", v, vlogToStr(k.Config.Vlog), " --ignore-preflight-errors=SystemVerification,Port-10250,DirAvailable--etc-kubernetes-manifests"), nil 148 } 149 150 return fmt.Sprintf("%s%s%s", v, vlogToStr(k.Config.Vlog), " --ignore-preflight-errors=Port-10250,DirAvailable--etc-kubernetes-manifests"), nil 151 } 152 153 func (k *Runtime) getNodeNameOverride(ip net.IP) string { 154 if v, ok := k.infra.GetClusterEnv()[common.EnvUseIPasNodeName]; ok && v == "true" { 155 return ip.String() 156 } 157 158 return "" 159 } 160 161 func GetClientFromConfig(adminConfPath string) (runtimeClient.Client, error) { 162 adminConfig, err := clientcmd.BuildConfigFromFlags("", adminConfPath) 163 if nil != err { 164 return nil, err 165 } 166 167 var ret runtimeClient.Client 168 169 timeout := time.Second * 30 170 err = wait.PollImmediate(time.Second*10, timeout, func() (done bool, err error) { 171 cli, err := runtimeClient.New(adminConfig, runtimeClient.Options{}) 172 if nil != err { 173 return false, err 174 } 175 176 ns := corev1.Namespace{} 177 if err := cli.Get(context.Background(), runtimeClient.ObjectKey{Name: "default"}, &ns); nil != err { 178 return false, err 179 } 180 181 ret = cli 182 183 return true, nil 184 }) 185 186 return ret, err 187 } 188 189 func (k *Runtime) configureLvs(masterHosts, clientHosts []net.IP) error { 190 lvsImageURL := path.Join(k.Config.RegistryInfo.URL, common.LvsCareRepoAndTag) 191 192 var rs []string 193 var realEndpoints []string 194 195 masters := netutils.IPsToIPStrs(masterHosts) 196 sort.Strings(masters) 197 for _, m := range masters { 198 rep := net.JoinHostPort(m, "6443") 199 rs = append(rs, fmt.Sprintf("--rs %s", rep)) 200 realEndpoints = append(realEndpoints, rep) 201 } 202 vs := net.JoinHostPort(k.getAPIServerVIP().String(), "6443") 203 ipvsCmd := fmt.Sprintf("seautil ipvs --vs %s %s --health-path /healthz --health-schem https --run-once", vs, strings.Join(rs, " ")) 204 y, err := ipvs.LvsStaticPodYaml(common.KubeLvsCareStaticPodName, vs, realEndpoints, lvsImageURL, 205 "/healthz", "https") 206 if err != nil { 207 return err 208 } 209 lvscareStaticCmd := ipvs.GetCreateLvscareStaticPodCmd(y, LvscarePodFileName) 210 211 eg, _ := errgroup.WithContext(context.Background()) 212 213 // flush all cluster nodes as latest ipvs policy. 214 for i := range clientHosts { 215 node := clientHosts[i] 216 eg.Go(func() error { 217 err := k.infra.CmdAsync(node, nil, ipvsCmd, lvscareStaticCmd, shellcommand.CommandSetHostAlias(k.getAPIServerDomain(), k.getAPIServerVIP().String())) 218 if err != nil { 219 return fmt.Errorf("failed to config ndoes lvs policy %s: %v", ipvsCmd, err) 220 } 221 return nil 222 }) 223 } 224 225 return eg.Wait() 226 }