From 5121ef80a509f72dd75356b268506d1cc1bb9b10 Mon Sep 17 00:00:00 2001 From: iwilltry42 Date: Wed, 22 Apr 2020 13:18:26 +0200 Subject: [PATCH] create/start/stop cluster: fix how Master-LoadBalancer is treated - always include the k3d.role label and use LoadBalancerRole for masterlb - start masterlb last when starting a stopped cluster so it won't fail --- cmd/create/createNode.go | 4 ++-- cmd/root.go | 2 ++ pkg/cluster/cluster.go | 24 +++++++++++++++++++++--- pkg/cluster/node.go | 6 ++---- pkg/runtimes/docker/node.go | 1 + pkg/runtimes/docker/translate.go | 3 +-- pkg/types/types.go | 17 +++++++++-------- 7 files changed, 38 insertions(+), 19 deletions(-) diff --git a/cmd/create/createNode.go b/cmd/create/createNode.go index 5967b601..db4d7cc8 100644 --- a/cmd/create/createNode.go +++ b/cmd/create/createNode.go @@ -84,10 +84,10 @@ func parseCreateNodeCmd(cmd *cobra.Command, args []string) ([]*k3d.Node, *k3d.Cl log.Errorln("No node role specified") log.Fatalln(err) } - if _, ok := k3d.DefaultK3dRoles[roleStr]; !ok { + if _, ok := k3d.NodeRoles[roleStr]; !ok { log.Fatalf("Unknown node role '%s'\n", roleStr) } - role := k3d.DefaultK3dRoles[roleStr] + role := k3d.NodeRoles[roleStr] // --image image, err := cmd.Flags().GetString("image") diff --git a/cmd/root.go b/cmd/root.go index 5b8428f8..06a2b7f7 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -111,6 +111,8 @@ func initLogging() { log.SetLevel(log.DebugLevel) case "WARN": log.SetLevel(log.WarnLevel) + case "ERROR": + log.SetLevel(log.ErrorLevel) default: log.SetLevel(log.InfoLevel) } diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index 8e80bc47..8cf36fbf 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -245,7 +245,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt */ // *** MasterLoadBalancer *** - // Generate a comma-separated list of master/server names to pass to the proxy container + // Generate a comma-separated list of master/server names to pass to the LB container servers := "" for _, node := range cluster.Nodes { if node.Role == k3d.MasterRole { @@ -258,7 +258,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt } } - // Create proxy as a modified node with proxyRole + // Create LB as a modified node with loadbalancerRole lbNode := &k3d.Node{ Name: fmt.Sprintf("%s-%s-masterlb", k3d.DefaultObjectNamePrefix, cluster.Name), Image: k3d.DefaultLBImage, @@ -267,7 +267,7 @@ func CreateCluster(ctx context.Context, cluster *k3d.Cluster, runtime k3drt.Runt fmt.Sprintf("SERVERS=%s", servers), fmt.Sprintf("PORT=%s", k3d.DefaultAPIPort), }, - Role: k3d.NoRole, + Role: k3d.LoadBalancerRole, Labels: k3d.DefaultObjectLabels, // TODO: createLoadBalancer: add more expressive labels Network: cluster.Network.Name, } @@ -438,7 +438,16 @@ func StartCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error { log.Infof("Starting cluster '%s'", cluster.Name) failed := 0 + var masterlb *k3d.Node for _, node := range cluster.Nodes { + + // skip the LB, because we want to start it last + if node.Role == k3d.LoadBalancerRole { + masterlb = node + continue + } + + // start node if err := runtime.StartNode(node); err != nil { log.Warningf("Failed to start node '%s': Try to start it manually", node.Name) failed++ @@ -446,6 +455,15 @@ func StartCluster(cluster *k3d.Cluster, runtime k3drt.Runtime) error { } } + // start masterlb + if masterlb != nil { + log.Debugln("Starting masterlb...") + if err := runtime.StartNode(masterlb); err != nil { // FIXME: we could run into a nullpointer exception here + log.Warningf("Failed to start masterlb '%s': Try to start it manually", masterlb.Name) + failed++ + } + } + if failed > 0 { return fmt.Errorf("Failed to start %d nodes: Try to start them manually", failed) } diff --git a/pkg/cluster/node.go b/pkg/cluster/node.go index f973f7c2..e62b50ee 100644 --- a/pkg/cluster/node.go +++ b/pkg/cluster/node.go @@ -112,6 +112,8 @@ func CreateNode(node *k3d.Node, runtime runtimes.Runtime) error { labels[k] = v } node.Labels = labels + // second most important: the node role label + node.Labels["k3d.role"] = string(node.Role) // ### Environment ### node.Env = append(node.Env, k3d.DefaultNodeEnv...) // append default node env vars @@ -150,7 +152,6 @@ func DeleteNode(runtime runtimes.Runtime, node *k3d.Node) error { // patchWorkerSpec adds worker node specific settings to a node func patchWorkerSpec(node *k3d.Node) error { node.Args = append([]string{"agent"}, node.Args...) - node.Labels["k3d.role"] = string(k3d.WorkerRole) // TODO: maybe put those in a global var DefaultWorkerNodeSpec? return nil } @@ -160,9 +161,6 @@ func patchMasterSpec(node *k3d.Node) error { // command / arguments node.Args = append([]string{"server"}, node.Args...) - // role label - node.Labels["k3d.role"] = string(k3d.MasterRole) // TODO: maybe put those in a global var DefaultMasterNodeSpec? - // Add labels and TLS SAN for the exposed API // FIXME: For now, the labels concerning the API on the master nodes are only being used for configuring the kubeconfig node.Labels["k3d.master.api.hostIP"] = node.MasterOpts.ExposeAPI.HostIP // TODO: maybe get docker machine IP here diff --git a/pkg/runtimes/docker/node.go b/pkg/runtimes/docker/node.go index 8b90b7ca..f0889d98 100644 --- a/pkg/runtimes/docker/node.go +++ b/pkg/runtimes/docker/node.go @@ -107,6 +107,7 @@ func (d Docker) StartNode(node *k3d.Node) error { } // actually start the container + log.Infof("Starting Node '%s'", node.Name) if err := docker.ContainerStart(ctx, nodeContainer.ID, types.ContainerStartOptions{}); err != nil { return err } diff --git a/pkg/runtimes/docker/translate.go b/pkg/runtimes/docker/translate.go index de010eeb..46e70e0e 100644 --- a/pkg/runtimes/docker/translate.go +++ b/pkg/runtimes/docker/translate.go @@ -63,7 +63,6 @@ func TranslateNodeToContainer(node *k3d.Node) (*NodeInDocker, error) { } /* Tmpfs Mounts */ - // TODO: do we need this or can the default be a map with empty values already? hostConfig.Tmpfs = make(map[string]string) for _, mnt := range k3d.DefaultTmpfsMounts { hostConfig.Tmpfs[mnt] = "" @@ -111,7 +110,7 @@ func TranslateContainerToNode(cont *types.Container) (*k3d.Node, error) { Name: cont.Names[0], Image: cont.Image, Labels: cont.Labels, - Role: k3d.DefaultK3dRoles[cont.Labels["k3d.role"]], // TODO: what if this is not present? + Role: k3d.NodeRoles[cont.Labels["k3d.role"]], // TODO: what if this is not present? // TODO: all the rest } return node, nil diff --git a/pkg/types/types.go b/pkg/types/types.go index 59b163b4..8e2010bd 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -49,16 +49,17 @@ type Role string // existing k3d node roles const ( - MasterRole Role = "master" - WorkerRole Role = "worker" - NoRole Role = "noRole" - ProxyRole Role = "proxy" + MasterRole Role = "master" + WorkerRole Role = "worker" + NoRole Role = "noRole" + LoadBalancerRole Role = "loadbalancer" ) -// DefaultK3dRoles defines the roles available for nodes -var DefaultK3dRoles = map[string]Role{ - string(MasterRole): MasterRole, - string(WorkerRole): WorkerRole, +// NodeRoles defines the roles available for nodes +var NodeRoles = map[string]Role{ + string(MasterRole): MasterRole, + string(WorkerRole): WorkerRole, + string(LoadBalancerRole): LoadBalancerRole, } // DefaultObjectLabels specifies a set of labels that will be attached to k3d objects by default