diff --git a/cmd/kind/create/cluster/createcluster.go b/cmd/kind/create/cluster/createcluster.go index d3d3cd999f..16407a5951 100644 --- a/cmd/kind/create/cluster/createcluster.go +++ b/cmd/kind/create/cluster/createcluster.go @@ -35,6 +35,7 @@ type flagpole struct { Name string Config string ImageName string + CNI string Retain bool IPv6 bool Wait time.Duration @@ -55,6 +56,7 @@ func NewCommand() *cobra.Command { cmd.Flags().StringVar(&flags.Name, "name", cluster.DefaultName, "cluster context name") cmd.Flags().StringVar(&flags.Config, "config", "", "path to a kind config file") cmd.Flags().StringVar(&flags.ImageName, "image", "", "node docker image to use for booting the cluster") + cmd.Flags().StringVar(&flags.CNI, "cni", "", "URL with the CNI installation manifest") cmd.Flags().BoolVar(&flags.Retain, "retain", false, "retain nodes for debugging when cluster creation fails") cmd.Flags().BoolVar(&flags.IPv6, "ipv6", false, "creates an IPv6 cluster") cmd.Flags().DurationVar(&flags.Wait, "wait", time.Duration(0), "Wait for control plane node to be ready (default 0s)") @@ -109,6 +111,7 @@ func runE(flags *flagpole, cmd *cobra.Command, args []string) error { create.Retain(flags.Retain), create.WaitForReady(flags.Wait), create.IPv6(flags.IPv6), + create.CNI(flags.CNI), ); err != nil { return errors.Wrap(err, "failed to create cluster") } diff --git a/pkg/cluster/create/cluster.go b/pkg/cluster/create/cluster.go index 74ce26580d..af66f812d7 100644 --- a/pkg/cluster/create/cluster.go +++ b/pkg/cluster/create/cluster.go @@ -48,3 +48,11 @@ func IPv6(ipv6 bool) ClusterOption { return o } } + +// CNI install a different CNI plugins using the manifest provided +func CNI(cni string) ClusterOption { + return func(o *internalcreate.Options) *internalcreate.Options { + o.CNI = cni + return o + } +} diff --git a/pkg/cluster/internal/create/create.go b/pkg/cluster/internal/create/create.go index cf323b5326..bae6dcefe2 100644 --- a/pkg/cluster/internal/create/create.go +++ b/pkg/cluster/internal/create/create.go @@ -37,6 +37,7 @@ type Options struct { Retain bool WaitForReady time.Duration IPv6 bool + CNI string } // Cluster creates a cluster @@ -85,6 +86,8 @@ func Cluster(c *context.Context, cfg *config.Config, opts *Options) error { cc.IPv6 = true } + cc.CNI = opts.CNI + // attempt to explicitly pull the required node images if they doesn't exist locally // we don't care if this errors, we'll still try to run which also pulls cc.EnsureNodeImages() diff --git a/pkg/cluster/internal/create/createcontext.go b/pkg/cluster/internal/create/createcontext.go index 612c285991..f30570ddad 100644 --- a/pkg/cluster/internal/create/createcontext.go +++ b/pkg/cluster/internal/create/createcontext.go @@ -43,6 +43,7 @@ type Context struct { *DerivedConfig Retain bool // if we should retain nodes after failing to create. IPv6 bool // use IPv6 to configure the cluster. + CNI string // install a different CNI plugin ExecOptions []ExecOption // options to be forwarded to the exec command. } diff --git a/pkg/cluster/internal/create/kubeadm-init.go b/pkg/cluster/internal/create/kubeadm-init.go index b190ab92d1..d1d54a8a95 100644 --- a/pkg/cluster/internal/create/kubeadm-init.go +++ b/pkg/cluster/internal/create/kubeadm-init.go @@ -105,25 +105,39 @@ func runKubeadmInit(ec *execContext, configNode *NodeReplica) error { // install the CNI network plugin // TODO(bentheelder): support other overlay networks // first probe for a pre-installed manifest - haveDefaultCNIManifest := true - if err := node.Command("test", "-f", "/kind/manifests/default-cni.yaml").Run(); err != nil { - haveDefaultCNIManifest = false - } - if haveDefaultCNIManifest { - // we found the default manifest, install that - // the images should already be loaded along with kubernetes - if err := node.Command( - "kubectl", "create", "--kubeconfig=/etc/kubernetes/admin.conf", - "-f", "/kind/manifests/default-cni.yaml", - ).Run(); err != nil { - return errors.Wrap(err, "failed to apply overlay network") + log.Debug("CNI option ", ec.Context.CNI, "\n") + if ec.Context.CNI == "" { + haveDefaultCNIManifest := true + if err := node.Command("test", "-f", "/kind/manifests/default-cni.yaml").Run(); err != nil { + haveDefaultCNIManifest = false + } + + if haveDefaultCNIManifest { + // we found the default manifest, install that + // the images should already be loaded along with kubernetes + if err := node.Command( + "kubectl", "create", "--kubeconfig=/etc/kubernetes/admin.conf", + "-f", "/kind/manifests/default-cni.yaml", + ).Run(); err != nil { + return errors.Wrap(err, "failed to apply overlay network") + } + } else { + // fallback to our old pattern of installing weave using their recommended method + if err := node.Command( + "/bin/sh", "-c", + `kubectl apply --kubeconfig=/etc/kubernetes/admin.conf -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version --kubeconfig=/etc/kubernetes/admin.conf | base64 | tr -d '\n')"`, + ).Run(); err != nil { + return errors.Wrap(err, "failed to apply overlay network") + } } } else { - // fallback to our old pattern of installing weave using their recommended method - if err := node.Command( - "/bin/sh", "-c", - `kubectl apply --kubeconfig=/etc/kubernetes/admin.conf -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version --kubeconfig=/etc/kubernetes/admin.conf | base64 | tr -d '\n')"`, - ).Run(); err != nil { + cmd := node.Command( + "kubectl", "--kubeconfig=/etc/kubernetes/admin.conf", + "apply", "-f", ec.Context.CNI, + ) + lines, err := exec.CombinedOutputLines(cmd) + log.Debug(strings.Join(lines, "\n")) + if err != nil { return errors.Wrap(err, "failed to apply overlay network") } }