From 5ff67c9c1e22c0e53b5fbccc94692c5e6dcd834f Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Tue, 10 Mar 2020 16:11:11 -0700 Subject: [PATCH 1/3] Update Newest to 1.18.0-beta.2 --- pkg/minikube/bootstrapper/bsutil/kubelet_test.go | 2 +- pkg/minikube/constants/constants.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/minikube/bootstrapper/bsutil/kubelet_test.go b/pkg/minikube/bootstrapper/bsutil/kubelet_test.go index a6344c264798..3019ee1f5255 100644 --- a/pkg/minikube/bootstrapper/bsutil/kubelet_test.go +++ b/pkg/minikube/bootstrapper/bsutil/kubelet_test.go @@ -79,7 +79,7 @@ Wants=crio.service [Service] ExecStart= -ExecStart=/var/lib/minikube/binaries/v1.17.3/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=/var/run/crio/crio.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m +ExecStart=/var/lib/minikube/binaries/v1.18.0-beta.2/kubelet --authorization-mode=Webhook --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --cgroup-driver=cgroupfs --client-ca-file=/var/lib/minikube/certs/ca.crt --cluster-domain=cluster.local --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=/var/run/crio/crio.sock --fail-swap-on=false --hostname-override=minikube --image-service-endpoint=/var/run/crio/crio.sock --kubeconfig=/etc/kubernetes/kubelet.conf --node-ip=192.168.1.100 --pod-manifest-path=/etc/kubernetes/manifests --runtime-request-timeout=15m [Install] `, diff --git a/pkg/minikube/constants/constants.go b/pkg/minikube/constants/constants.go index 0f6af77d31a1..5caeeb7505ab 100644 --- a/pkg/minikube/constants/constants.go +++ b/pkg/minikube/constants/constants.go @@ -28,7 +28,7 @@ const ( // DefaultKubernetesVersion is the default kubernetes version DefaultKubernetesVersion = "v1.17.3" // NewestKubernetesVersion is the newest Kubernetes version to test against - NewestKubernetesVersion = "v1.17.3" + NewestKubernetesVersion = "v1.18.0-beta.2" // OldestKubernetesVersion is the oldest Kubernetes version to test against OldestKubernetesVersion = "v1.11.10" // DefaultClusterName is the default nane for the k8s cluster From 71a22787c3ba69198471f1d440f393beebcf70ad Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Tue, 10 Mar 2020 20:48:38 -0700 Subject: [PATCH 2/3] Update Kubernetes image mapping to match v1.18 --- cmd/minikube/cmd/start.go | 11 +++++++---- pkg/minikube/bootstrapper/bsutil/kubeadm.go | 3 ++- pkg/minikube/bootstrapper/bsutil/kubelet.go | 5 +++-- pkg/minikube/bootstrapper/bsutil/versions.go | 12 ------------ .../bootstrapper/bsutil/versions_test.go | 10 ---------- pkg/minikube/bootstrapper/images/images.go | 16 +++++++++++----- pkg/minikube/bootstrapper/kubeadm/kubeadm.go | 7 ++++--- pkg/minikube/cruntime/containerd.go | 9 +++++---- pkg/minikube/cruntime/crio.go | 9 +++++---- pkg/minikube/cruntime/cruntime.go | 3 ++- pkg/minikube/machine/cache_images.go | 1 + pkg/minikube/node/config.go | 11 ++++++++--- pkg/minikube/node/start.go | 7 ++++++- pkg/util/utils.go | 8 +++++++- pkg/util/utils_test.go | 12 ++++++++++++ 15 files changed, 73 insertions(+), 51 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 758deb59a2e3..2806297f04a9 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -431,8 +431,11 @@ func showKubectlInfo(kcs *kubeconfig.Settings, k8sVersion string, machineName st glog.Infof("kubectl: %s, cluster: %s (minor skew: %d)", client, cluster, minorSkew) if client.Major != cluster.Major || minorSkew > 1 { - out.WarningT("{{.path}} is version {{.client_version}}, and is incompatible with Kubernetes {{.cluster_version}}. You will need to update {{.path}} or use 'minikube kubectl' to connect with this cluster", + out.Ln("") + out.T(out.Warning, "{{.path}} is v{{.client_version}}, which may be incompatible with Kubernetes v{{.cluster_version}}.", out.V{"path": path, "client_version": client, "cluster_version": cluster}) + out.T(out.Tip, "You can also use 'minikube kubectl -- ' to invoke a matching version", + out.V{"path": path, "client_version": client}) } return nil } @@ -549,7 +552,7 @@ func validateDriver(ds registry.DriverState, existing *config.ClusterConfig) { exit.WithCodeT(exit.Config, "Exiting.") } -func selectImageRepository(mirrorCountry string) (bool, string, error) { +func selectImageRepository(mirrorCountry string, v semver.Version) (bool, string, error) { var tryCountries []string var fallback string glog.Infof("selecting image repository for country %s ...", mirrorCountry) @@ -577,7 +580,7 @@ func selectImageRepository(mirrorCountry string) (bool, string, error) { } checkRepository := func(repo string) error { - pauseImage := images.Pause(repo) + pauseImage := images.Pause(v, repo) ref, err := name.ParseReference(pauseImage, name.WeakValidation) if err != nil { return err @@ -796,7 +799,7 @@ func generateCfgFromFlags(cmd *cobra.Command, k8sVersion string, drvName string) repository := viper.GetString(imageRepository) mirrorCountry := strings.ToLower(viper.GetString(imageMirrorCountry)) if strings.ToLower(repository) == "auto" || mirrorCountry != "" { - found, autoSelectedRepository, err := selectImageRepository(mirrorCountry) + found, autoSelectedRepository, err := selectImageRepository(mirrorCountry, semver.MustParse(k8sVersion)) if err != nil { exit.WithError("Failed to check main repository and mirrors for images for images", err) } diff --git a/pkg/minikube/bootstrapper/bsutil/kubeadm.go b/pkg/minikube/bootstrapper/bsutil/kubeadm.go index 0f37e5ae11de..3aa1bb52d481 100644 --- a/pkg/minikube/bootstrapper/bsutil/kubeadm.go +++ b/pkg/minikube/bootstrapper/bsutil/kubeadm.go @@ -30,6 +30,7 @@ import ( "k8s.io/minikube/pkg/minikube/constants" "k8s.io/minikube/pkg/minikube/cruntime" "k8s.io/minikube/pkg/minikube/vmpath" + "k8s.io/minikube/pkg/util" ) // Container runtimes @@ -38,7 +39,7 @@ const remoteContainerRuntime = "remote" // GenerateKubeadmYAML generates the kubeadm.yaml file func GenerateKubeadmYAML(mc config.ClusterConfig, r cruntime.Manager, n config.Node) ([]byte, error) { k8s := mc.KubernetesConfig - version, err := ParseKubernetesVersion(k8s.KubernetesVersion) + version, err := util.ParseKubernetesVersion(k8s.KubernetesVersion) if err != nil { return nil, errors.Wrap(err, "parsing kubernetes version") } diff --git a/pkg/minikube/bootstrapper/bsutil/kubelet.go b/pkg/minikube/bootstrapper/bsutil/kubelet.go index d3b7cd6f8034..8ec9d01fc671 100644 --- a/pkg/minikube/bootstrapper/bsutil/kubelet.go +++ b/pkg/minikube/bootstrapper/bsutil/kubelet.go @@ -26,11 +26,12 @@ import ( "k8s.io/minikube/pkg/minikube/bootstrapper/images" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/cruntime" + "k8s.io/minikube/pkg/util" ) func extraKubeletOpts(mc config.ClusterConfig, nc config.Node, r cruntime.Manager) (map[string]string, error) { k8s := mc.KubernetesConfig - version, err := ParseKubernetesVersion(k8s.KubernetesVersion) + version, err := util.ParseKubernetesVersion(k8s.KubernetesVersion) if err != nil { return nil, errors.Wrap(err, "parsing kubernetes version") } @@ -62,7 +63,7 @@ func extraKubeletOpts(mc config.ClusterConfig, nc config.Node, r cruntime.Manage extraOpts["hostname-override"] = nc.Name } - pauseImage := images.Pause(k8s.ImageRepository) + pauseImage := images.Pause(version, k8s.ImageRepository) if _, ok := extraOpts["pod-infra-container-image"]; !ok && k8s.ImageRepository != "" && pauseImage != "" && k8s.ContainerRuntime != remoteContainerRuntime { extraOpts["pod-infra-container-image"] = pauseImage } diff --git a/pkg/minikube/bootstrapper/bsutil/versions.go b/pkg/minikube/bootstrapper/bsutil/versions.go index 0d11ccf2e74a..4c06b134015a 100644 --- a/pkg/minikube/bootstrapper/bsutil/versions.go +++ b/pkg/minikube/bootstrapper/bsutil/versions.go @@ -21,23 +21,11 @@ import ( "strings" "github.com/blang/semver" - "github.com/pkg/errors" "k8s.io/minikube/pkg/minikube/config" "k8s.io/minikube/pkg/minikube/vmpath" "k8s.io/minikube/pkg/util" ) -// ParseKubernetesVersion parses the kubernetes version -func ParseKubernetesVersion(version string) (semver.Version, error) { - // Strip leading 'v' prefix from version for semver parsing - v, err := semver.Make(version[1:]) - if err != nil { - return semver.Version{}, errors.Wrap(err, "invalid version, must begin with 'v'") - } - - return v, nil -} - // versionIsBetween checks if a version is between (or including) two given versions func versionIsBetween(version, gte, lte semver.Version) bool { if gte.NE(semver.Version{}) && !version.GTE(gte) { diff --git a/pkg/minikube/bootstrapper/bsutil/versions_test.go b/pkg/minikube/bootstrapper/bsutil/versions_test.go index e08e9b92d6b5..a22efeeb35d1 100644 --- a/pkg/minikube/bootstrapper/bsutil/versions_test.go +++ b/pkg/minikube/bootstrapper/bsutil/versions_test.go @@ -91,13 +91,3 @@ func TestVersionIsBetween(t *testing.T) { }) } } - -func TestParseKubernetesVersion(t *testing.T) { - version, err := ParseKubernetesVersion("v1.8.0-alpha.5") - if err != nil { - t.Fatalf("Error parsing version: %v", err) - } - if version.NE(semver.MustParse("1.8.0-alpha.5")) { - t.Errorf("Expected: %s, Actual:%s", "1.8.0-alpha.5", version) - } -} diff --git a/pkg/minikube/bootstrapper/images/images.go b/pkg/minikube/bootstrapper/images/images.go index 30035be30650..1029e940073b 100644 --- a/pkg/minikube/bootstrapper/images/images.go +++ b/pkg/minikube/bootstrapper/images/images.go @@ -25,11 +25,15 @@ import ( "github.com/blang/semver" ) -// Pause returns the image name to pull for the pause image -func Pause(mirror string) string { +// Pause returns the image name to pull for a given Kubernetes version +func Pause(v semver.Version, mirror string) string { // Should match `PauseVersion` in: // https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go - return path.Join(kubernetesRepo(mirror), "pause"+archTag(false)+"3.1") + pv := "3.2" + if semver.MustParseRange("<1.18.0-alpha.0")(v) { + pv = "3.1" + } + return path.Join(kubernetesRepo(mirror), "pause"+archTag(false)+pv) } // essentials returns images needed too bootstrap a kubenretes @@ -41,7 +45,7 @@ func essentials(mirror string, v semver.Version) []string { componentImage("kube-apiserver", v, mirror), coreDNS(v, mirror), etcd(v, mirror), - Pause(mirror), + Pause(v, mirror), } return imgs } @@ -61,8 +65,10 @@ func componentImage(name string, v semver.Version, mirror string) string { func coreDNS(v semver.Version, mirror string) string { // Should match `CoreDNSVersion` in // https://github.com/kubernetes/kubernetes/blob/master/cmd/kubeadm/app/constants/constants.go - cv := "1.6.5" + cv := "1.6.7" switch v.Minor { + case 17: + cv = "1.6.5" case 16: cv = "1.6.2" case 15, 14: diff --git a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go index e9817044563c..e827f69be4aa 100644 --- a/pkg/minikube/bootstrapper/kubeadm/kubeadm.go +++ b/pkg/minikube/bootstrapper/kubeadm/kubeadm.go @@ -54,6 +54,7 @@ import ( "k8s.io/minikube/pkg/minikube/machine" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/vmpath" + "k8s.io/minikube/pkg/util" "k8s.io/minikube/pkg/version" ) @@ -164,7 +165,7 @@ func (k *Bootstrapper) StartCluster(cfg config.ClusterConfig) error { glog.Infof("StartCluster complete in %s", time.Since(start)) }() - version, err := bsutil.ParseKubernetesVersion(cfg.KubernetesConfig.KubernetesVersion) + version, err := util.ParseKubernetesVersion(cfg.KubernetesConfig.KubernetesVersion) if err != nil { return errors.Wrap(err, "parsing kubernetes version") } @@ -293,7 +294,7 @@ func (k *Bootstrapper) restartCluster(cfg config.ClusterConfig) error { glog.Infof("restartCluster took %s", time.Since(start)) }() - version, err := bsutil.ParseKubernetesVersion(cfg.KubernetesConfig.KubernetesVersion) + version, err := util.ParseKubernetesVersion(cfg.KubernetesConfig.KubernetesVersion) if err != nil { return errors.Wrap(err, "parsing kubernetes version") } @@ -363,7 +364,7 @@ func (k *Bootstrapper) restartCluster(cfg config.ClusterConfig) error { // DeleteCluster removes the components that were started earlier func (k *Bootstrapper) DeleteCluster(k8s config.KubernetesConfig) error { - version, err := bsutil.ParseKubernetesVersion(k8s.KubernetesVersion) + version, err := util.ParseKubernetesVersion(k8s.KubernetesVersion) if err != nil { return errors.Wrap(err, "parsing kubernetes version") } diff --git a/pkg/minikube/cruntime/containerd.go b/pkg/minikube/cruntime/containerd.go index 37d651bc3ca9..b5828b977729 100644 --- a/pkg/minikube/cruntime/containerd.go +++ b/pkg/minikube/cruntime/containerd.go @@ -25,6 +25,7 @@ import ( "strings" "text/template" + "github.com/blang/semver" "github.com/golang/glog" "github.com/pkg/errors" "k8s.io/minikube/pkg/minikube/bootstrapper/images" @@ -112,7 +113,7 @@ type Containerd struct { Socket string Runner CommandRunner ImageRepository string - KubernetesVersion string + KubernetesVersion semver.Version } // Name is a human readable name for containerd @@ -170,13 +171,13 @@ func (r *Containerd) Available() error { } // generateContainerdConfig sets up /etc/containerd/config.toml -func generateContainerdConfig(cr CommandRunner, imageRepository string) error { +func generateContainerdConfig(cr CommandRunner, imageRepository string, kv semver.Version) error { cPath := containerdConfigFile t, err := template.New("containerd.config.toml").Parse(containerdConfigTemplate) if err != nil { return err } - pauseImage := images.Pause(imageRepository) + pauseImage := images.Pause(kv, imageRepository) opts := struct{ PodInfraContainerImage string }{PodInfraContainerImage: pauseImage} var b bytes.Buffer if err := t.Execute(&b, opts); err != nil { @@ -199,7 +200,7 @@ func (r *Containerd) Enable(disOthers bool) error { if err := populateCRIConfig(r.Runner, r.SocketPath()); err != nil { return err } - if err := generateContainerdConfig(r.Runner, r.ImageRepository); err != nil { + if err := generateContainerdConfig(r.Runner, r.ImageRepository, r.KubernetesVersion); err != nil { return err } if err := enableIPForwarding(r.Runner); err != nil { diff --git a/pkg/minikube/cruntime/crio.go b/pkg/minikube/cruntime/crio.go index 8b4be028cfb6..6b52c4f23100 100644 --- a/pkg/minikube/cruntime/crio.go +++ b/pkg/minikube/cruntime/crio.go @@ -21,6 +21,7 @@ import ( "os/exec" "strings" + "github.com/blang/semver" "github.com/golang/glog" "github.com/pkg/errors" "k8s.io/minikube/pkg/minikube/bootstrapper/images" @@ -37,13 +38,13 @@ type CRIO struct { Socket string Runner CommandRunner ImageRepository string - KubernetesVersion string + KubernetesVersion semver.Version } // generateCRIOConfig sets up /etc/crio/crio.conf -func generateCRIOConfig(cr CommandRunner, imageRepository string) error { +func generateCRIOConfig(cr CommandRunner, imageRepository string, kv semver.Version) error { cPath := crioConfigFile - pauseImage := images.Pause(imageRepository) + pauseImage := images.Pause(kv, imageRepository) c := exec.Command("/bin/bash", "-c", fmt.Sprintf("sudo sed -e 's|^pause_image = .*$|pause_image = \"%s\"|' -i %s", pauseImage, cPath)) if _, err := cr.RunCmd(c); err != nil { @@ -116,7 +117,7 @@ func (r *CRIO) Enable(disOthers bool) error { if err := populateCRIConfig(r.Runner, r.SocketPath()); err != nil { return err } - if err := generateCRIOConfig(r.Runner, r.ImageRepository); err != nil { + if err := generateCRIOConfig(r.Runner, r.ImageRepository, r.KubernetesVersion); err != nil { return err } if err := enableIPForwarding(r.Runner); err != nil { diff --git a/pkg/minikube/cruntime/cruntime.go b/pkg/minikube/cruntime/cruntime.go index 468b84442970..cd6683cdd69b 100644 --- a/pkg/minikube/cruntime/cruntime.go +++ b/pkg/minikube/cruntime/cruntime.go @@ -21,6 +21,7 @@ import ( "fmt" "os/exec" + "github.com/blang/semver" "github.com/golang/glog" "github.com/pkg/errors" "k8s.io/minikube/pkg/minikube/assets" @@ -114,7 +115,7 @@ type Config struct { // ImageRepository image repository to download image from ImageRepository string // KubernetesVersion Kubernetes version - KubernetesVersion string + KubernetesVersion semver.Version } // ListOptions are the options to use for listing containers diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index ffa0aa7c186d..19bdce0fb2f6 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -79,6 +79,7 @@ func LoadImages(cc *config.ClusterConfig, runner command.Runner, images []string }() var g errgroup.Group + cr, err := cruntime.New(cruntime.Config{Type: cc.KubernetesConfig.ContainerRuntime, Runner: runner}) if err != nil { return errors.Wrap(err, "runtime") diff --git a/pkg/minikube/node/config.go b/pkg/minikube/node/config.go index e93a7fc4d87b..66716557f2ec 100644 --- a/pkg/minikube/node/config.go +++ b/pkg/minikube/node/config.go @@ -24,6 +24,7 @@ import ( "strconv" "strings" + "github.com/blang/semver" "github.com/docker/machine/libmachine" "github.com/docker/machine/libmachine/host" "github.com/golang/glog" @@ -55,9 +56,13 @@ var ( ) // configureRuntimes does what needs to happen to get a runtime going. -func configureRuntimes(runner cruntime.CommandRunner, drvName string, k8s config.KubernetesConfig) cruntime.Manager { - config := cruntime.Config{Type: viper.GetString(containerRuntime), Runner: runner, ImageRepository: k8s.ImageRepository, KubernetesVersion: k8s.KubernetesVersion} - cr, err := cruntime.New(config) +func configureRuntimes(runner cruntime.CommandRunner, drvName string, k8s config.KubernetesConfig, kv semver.Version) cruntime.Manager { + co := cruntime.Config{ + Type: viper.GetString(containerRuntime), + Runner: runner, ImageRepository: k8s.ImageRepository, + KubernetesVersion: kv, + } + cr, err := cruntime.New(co) if err != nil { exit.WithError("Failed runtime", err) } diff --git a/pkg/minikube/node/start.go b/pkg/minikube/node/start.go index 8dfbde664360..249fe5cf1b25 100644 --- a/pkg/minikube/node/start.go +++ b/pkg/minikube/node/start.go @@ -62,8 +62,13 @@ func Start(mc config.ClusterConfig, n config.Node, primary bool, existingAddons // wait for preloaded tarball to finish downloading before configuring runtimes waitCacheRequiredImages(&cacheGroup) + sv, err := util.ParseKubernetesVersion(mc.KubernetesConfig.KubernetesVersion) + if err != nil { + return nil, err + } + // configure the runtime (docker, containerd, crio) - cr := configureRuntimes(mRunner, driverName, mc.KubernetesConfig) + cr := configureRuntimes(mRunner, driverName, mc.KubernetesConfig, sv) showVersionInfo(k8sVersion, cr) //TODO(sharifelgamal): Part out the cluster-wide operations, perhaps using the "primary" param diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 9ab0a57bb361..1e4cf0394248 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -23,7 +23,8 @@ import ( "path/filepath" "strconv" - units "github.com/docker/go-units" + "github.com/blang/semver" + "github.com/docker/go-units" "github.com/pkg/errors" "k8s.io/minikube/pkg/minikube/exit" "k8s.io/minikube/pkg/minikube/out" @@ -89,3 +90,8 @@ func MaybeChownDirRecursiveToMinikubeUser(dir string) error { } return nil } + +// ParseKubernetesVersion parses the kubernetes version +func ParseKubernetesVersion(version string) (semver.Version, error) { + return semver.Make(version[1:]) +} diff --git a/pkg/util/utils_test.go b/pkg/util/utils_test.go index b8a3514d28d5..5b705a508fde 100644 --- a/pkg/util/utils_test.go +++ b/pkg/util/utils_test.go @@ -18,6 +18,8 @@ package util import ( "testing" + + "github.com/blang/semver" ) func TestGetBinaryDownloadURL(t *testing.T) { @@ -58,3 +60,13 @@ func TestCalculateSizeInMB(t *testing.T) { } } } + +func TestParseKubernetesVersion(t *testing.T) { + version, err := ParseKubernetesVersion("v1.8.0-alpha.5") + if err != nil { + t.Fatalf("Error parsing version: %v", err) + } + if version.NE(semver.MustParse("1.8.0-alpha.5")) { + t.Errorf("Expected: %s, Actual:%s", "1.8.0-alpha.5", version) + } +} From 12fd0b007e1a354fd3419c717cd055b915e373b9 Mon Sep 17 00:00:00 2001 From: Thomas Stromberg Date: Tue, 10 Mar 2020 20:52:54 -0700 Subject: [PATCH 3/3] Revert kubectl mismatch UI change --- cmd/minikube/cmd/start.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cmd/minikube/cmd/start.go b/cmd/minikube/cmd/start.go index 2806297f04a9..eea67e9b6bb8 100644 --- a/cmd/minikube/cmd/start.go +++ b/cmd/minikube/cmd/start.go @@ -431,11 +431,8 @@ func showKubectlInfo(kcs *kubeconfig.Settings, k8sVersion string, machineName st glog.Infof("kubectl: %s, cluster: %s (minor skew: %d)", client, cluster, minorSkew) if client.Major != cluster.Major || minorSkew > 1 { - out.Ln("") - out.T(out.Warning, "{{.path}} is v{{.client_version}}, which may be incompatible with Kubernetes v{{.cluster_version}}.", + out.WarningT("{{.path}} is version {{.client_version}}, and is incompatible with Kubernetes {{.cluster_version}}. You will need to update {{.path}} or use 'minikube kubectl' to connect with this cluster", out.V{"path": path, "client_version": client, "cluster_version": cluster}) - out.T(out.Tip, "You can also use 'minikube kubectl -- ' to invoke a matching version", - out.V{"path": path, "client_version": client}) } return nil }