func createNodes()

in kinder/pkg/cluster/manager/create.go [158:247]


func createNodes(clusterName string, flags *CreateOptions) error {
	// compute the desired nodes, and inform the user that we are setting them up
	desiredNodes := nodesToCreate(clusterName, flags)
	numberOfNodes := len(desiredNodes)
	if flags.externalEtcd {
		numberOfNodes++
	}
	fmt.Printf("Preparing nodes %s\n", strings.Repeat("📦", numberOfNodes))

	// detect CRI runtime installed into images before actually creating nodes
	runtime, err := status.InspectCRIinImage(flags.image)
	if err != nil {
		log.Errorf("Error detecting CRI for images %s! %v", flags.image, err)
		return err
	}
	log.Infof("Detected %s container runtime for image %s", runtime, flags.image)

	createHelper, err := nodes.NewCreateHelper(runtime)
	if err != nil {
		log.Errorf("Error creating NewCreateHelper for CRI %s! %v", flags.image, err)
		return err
	}

	// create all of the node containers, concurrently
	fns := []func() error{}
	for _, desiredNode := range desiredNodes {
		desiredNode := desiredNode // capture loop variable
		fns = append(fns, func() error {
			switch desiredNode.Role {
			case constants.ExternalLoadBalancerNodeRoleValue:
				return createHelper.CreateExternalLoadBalancer(clusterName, desiredNode.Name)
			case constants.ControlPlaneNodeRoleValue, constants.WorkerNodeRoleValue:
				return createHelper.CreateNode(clusterName, desiredNode.Name, flags.image, desiredNode.Role, flags.volumes)
			default:
				return nil
			}
		})
	}

	log.Info("Creating nodes...")
	if err := untilError(fns); err != nil {
		return err
	}

	// add an external etcd if explicitly requested
	if flags.externalEtcd {
		log.Info("Getting required etcd image...")
		c, err := status.FromDocker(clusterName)
		if err != nil {
			return err
		}

		etcdImage, err := c.BootstrapControlPlane().EtcdImage()
		if err != nil {
			return err
		}

		// attempt to explicitly pull the etcdImage if it doesn't exist locally
		// we don't care if this errors, we'll still try to run which also pulls
		_, _ = host.PullImage(etcdImage, 4)

		log.Info("Creating external etcd...")
		if err := createHelper.CreateExternalEtcd(clusterName, fmt.Sprintf("%s-etcd", clusterName), etcdImage); err != nil {
			return err
		}
	}

	// get the cluster
	c, err := status.FromDocker(clusterName)
	if err != nil {
		return err
	}

	// writes to the nodes the cluster settings that will be re-used by kinder during the cluster lifecycle.
	c.Settings = &status.ClusterSettings{
		IPFamily: status.IPv4Family, // support for ipv6 is still WIP
	}
	if err := c.WriteSettings(); err != nil {
		return err
	}

	// writes to the nodes the node settings
	for _, n := range c.K8sNodes() {
		if err := n.WriteNodeSettings(&status.NodeSettings{}); err != nil {
			return err
		}
	}

	return nil
}