From 0c22171ad8a224e218b502b5e5995f611c3ae02d Mon Sep 17 00:00:00 2001 From: Steven Powell Date: Sat, 6 Jul 2024 12:37:27 -0500 Subject: [PATCH 1/5] Check kicbase arch --- pkg/minikube/download/image.go | 35 +++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/pkg/minikube/download/image.go b/pkg/minikube/download/image.go index d8a903d8cd86..1753d938b5d6 100644 --- a/pkg/minikube/download/image.go +++ b/pkg/minikube/download/image.go @@ -78,14 +78,35 @@ func ImageExistsInDaemon(img string) bool { // Check if image exists locally klog.Infof("Checking for %s in local docker daemon", img) cmd := exec.Command("docker", "images", "--format", "{{.Repository}}:{{.Tag}}@{{.Digest}}") - if output, err := cmd.Output(); err == nil { - if strings.Contains(string(output), image.TrimDockerIO(img)) { - klog.Infof("Found %s in local docker daemon, skipping pull", img) - return true - } + output, err := cmd.Output() + if err != nil { + klog.Warningf("failed to list docker images: %v", err) + return false } - // Else, pull it - return false + if !strings.Contains(string(output), image.TrimDockerIO(img)) { + return false + } + ref, err := name.ParseReference(img) + if err != nil { + klog.Warningf("failed to parse reference: %v", err) + return false + } + dImg, err := daemon.Image(ref) + if err != nil { + klog.Warningf("failed to get image from daemon: %v", err) + return false + } + cfg, err := dImg.ConfigFile() + if err != nil { + klog.Warningf("failed to get config for %s: %v", img, err) + return false + } + if cfg.Architecture != runtime.GOOS { + klog.Warningf("image %s is of wrong architecture", img) + return false + } + klog.Infof("Found %s in local docker daemon, skipping pull", img) + return true } // ImageToCache downloads img (if not present in cache) and writes it to the local cache directory From b557541e2e15a6a27a4ef8ea7a05c1b0af5fbe07 Mon Sep 17 00:00:00 2001 From: Steven Powell Date: Tue, 9 Jul 2024 17:24:42 -0500 Subject: [PATCH 2/5] fix pulling wrong kicbase, preload, and binaries --- pkg/minikube/detect/detect.go | 9 --------- pkg/minikube/download/binary.go | 4 +--- pkg/minikube/download/image.go | 3 ++- pkg/minikube/download/preload.go | 5 ++--- pkg/minikube/machine/cache_binaries.go | 4 ++-- pkg/minikube/node/cache.go | 2 +- 6 files changed, 8 insertions(+), 19 deletions(-) diff --git a/pkg/minikube/detect/detect.go b/pkg/minikube/detect/detect.go index ca98a3781e01..2322ff2ea9da 100644 --- a/pkg/minikube/detect/detect.go +++ b/pkg/minikube/detect/detect.go @@ -83,15 +83,6 @@ func IsAmd64M1Emulation() bool { return runtime.GOARCH == "amd64" && strings.HasPrefix(cpuid.CPU.BrandName, "VirtualApple") } -// EffectiveArch return architecture to use in minikube VM/container -// may differ from host arch -func EffectiveArch() string { - if IsAmd64M1Emulation() { - return "arm64" - } - return runtime.GOARCH -} - // MinikubeInstalledViaSnap returns true if the minikube binary path includes "snap". func MinikubeInstalledViaSnap() bool { ex, err := os.Executable() diff --git a/pkg/minikube/download/binary.go b/pkg/minikube/download/binary.go index 21b3edd5dabb..6de9d9c42814 100644 --- a/pkg/minikube/download/binary.go +++ b/pkg/minikube/download/binary.go @@ -22,8 +22,6 @@ import ( "path" "runtime" - "k8s.io/minikube/pkg/minikube/detect" - "github.com/blang/semver/v4" "github.com/pkg/errors" "k8s.io/klog/v2" @@ -81,7 +79,7 @@ func Binary(binary, version, osName, archName, binaryURL string) (string, error) return "", errors.Wrapf(err, "download failed: %s", url) } - if osName == runtime.GOOS && archName == detect.EffectiveArch() { + if osName == runtime.GOOS && archName == runtime.GOARCH { if err = os.Chmod(targetFilepath, 0755); err != nil { return "", errors.Wrapf(err, "chmod +x %s", targetFilepath) } diff --git a/pkg/minikube/download/image.go b/pkg/minikube/download/image.go index 1753d938b5d6..8fadedad5109 100644 --- a/pkg/minikube/download/image.go +++ b/pkg/minikube/download/image.go @@ -266,7 +266,8 @@ func CacheToDaemon(img string) (string, error) { return "", err } - cmd := exec.Command("docker", "pull", "--quiet", img) + platform := fmt.Sprintf("linux/%s", runtime.GOARCH) + cmd := exec.Command("docker", "pull", "--platform", platform, "--quiet", img) if output, err := cmd.CombinedOutput(); err != nil { klog.Warningf("failed to pull image digest (expected if offline): %s: %v", output, err) img = image.Tag(img) diff --git a/pkg/minikube/download/preload.go b/pkg/minikube/download/preload.go index 861ed2e79138..970ad656e59d 100644 --- a/pkg/minikube/download/preload.go +++ b/pkg/minikube/download/preload.go @@ -25,11 +25,11 @@ import ( "os" "path" "path/filepath" + "runtime" "strings" "cloud.google.com/go/storage" "google.golang.org/api/option" - "k8s.io/minikube/pkg/minikube/detect" "github.com/pkg/errors" "github.com/spf13/viper" @@ -64,8 +64,7 @@ func TarballName(k8sVersion, containerRuntime string) string { } else { storageDriver = "overlay2" } - arch := detect.EffectiveArch() - return fmt.Sprintf("preloaded-images-k8s-%s-%s-%s-%s-%s.tar.lz4", PreloadVersion, k8sVersion, containerRuntime, storageDriver, arch) + return fmt.Sprintf("preloaded-images-k8s-%s-%s-%s-%s-%s.tar.lz4", PreloadVersion, k8sVersion, containerRuntime, storageDriver, runtime.GOARCH) } // returns the name of the checksum file diff --git a/pkg/minikube/machine/cache_binaries.go b/pkg/minikube/machine/cache_binaries.go index 1962e58fe52e..25fc26e3d53e 100644 --- a/pkg/minikube/machine/cache_binaries.go +++ b/pkg/minikube/machine/cache_binaries.go @@ -18,6 +18,7 @@ package machine import ( "path" + "runtime" "github.com/pkg/errors" "golang.org/x/sync/errgroup" @@ -25,7 +26,6 @@ import ( "k8s.io/minikube/pkg/minikube/assets" "k8s.io/minikube/pkg/minikube/bootstrapper" "k8s.io/minikube/pkg/minikube/command" - "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/minikube/download" ) @@ -53,7 +53,7 @@ func CacheBinariesForBootstrapper(version string, excludeBinaries []string, bina } bin := bin // https://go.dev/doc/faq#closures_and_goroutines g.Go(func() error { - if _, err := download.Binary(bin, version, "linux", detect.EffectiveArch(), binariesURL); err != nil { + if _, err := download.Binary(bin, version, "linux", runtime.GOARCH, binariesURL); err != nil { return errors.Wrapf(err, "caching binary %s", bin) } return nil diff --git a/pkg/minikube/node/cache.go b/pkg/minikube/node/cache.go index 4050de1abfc2..6feffc855763 100644 --- a/pkg/minikube/node/cache.go +++ b/pkg/minikube/node/cache.go @@ -103,7 +103,7 @@ func CacheKubectlBinary(k8sVersion, binaryURL string) (string, error) { binary = "kubectl.exe" } - return download.Binary(binary, k8sVersion, runtime.GOOS, detect.EffectiveArch(), binaryURL) + return download.Binary(binary, k8sVersion, runtime.GOOS, runtime.GOARCH, binaryURL) } // doCacheBinaries caches Kubernetes binaries in the foreground From 03d5ee2856c3cbaee5fe3bf937cd07c1b83aa171 Mon Sep 17 00:00:00 2001 From: Steven Powell Date: Tue, 9 Jul 2024 21:28:35 -0500 Subject: [PATCH 3/5] prevent using amd64 binary on arm64 to start with docker driver --- pkg/minikube/registry/drvs/docker/docker.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pkg/minikube/registry/drvs/docker/docker.go b/pkg/minikube/registry/drvs/docker/docker.go index 5feeefb87c97..9d5b11424618 100644 --- a/pkg/minikube/registry/drvs/docker/docker.go +++ b/pkg/minikube/registry/drvs/docker/docker.go @@ -33,6 +33,7 @@ import ( "k8s.io/minikube/pkg/drivers/kic" "k8s.io/minikube/pkg/drivers/kic/oci" "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/minikube/detect" "k8s.io/minikube/pkg/minikube/driver" "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/registry" @@ -151,6 +152,17 @@ var dockerVersionOrState = func() (string, registry.State) { return "", registry.State{Error: err, Installed: false, Healthy: false, Fix: "Install Docker", Doc: docURL} } + if detect.IsAmd64M1Emulation() { + return "", registry.State{ + Reason: "PROVIDER_DOCKER_INCORRECT_ARCH", + Installed: true, + Running: true, + Error: errors.New("Cannot use amd64 minikube binary to start minikube cluster with Docker driver on arm64 machine"), + Fix: "Download and use arm64 version of the minikube binary", + Doc: "https://minikube.sigs.k8s.io/docs/start/", + } + } + ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second) defer cancel() From fa26408dfd26dac989f172041a847bc14a223e93 Mon Sep 17 00:00:00 2001 From: Steven Powell Date: Mon, 15 Jul 2024 15:35:46 -0500 Subject: [PATCH 4/5] refactor arch ehcking logic into func --- pkg/minikube/download/image.go | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/pkg/minikube/download/image.go b/pkg/minikube/download/image.go index 8fadedad5109..3c4fc41aaf50 100644 --- a/pkg/minikube/download/image.go +++ b/pkg/minikube/download/image.go @@ -86,27 +86,35 @@ func ImageExistsInDaemon(img string) bool { if !strings.Contains(string(output), image.TrimDockerIO(img)) { return false } - ref, err := name.ParseReference(img) + correctArch, err := isImageCorrectArch(img) if err != nil { - klog.Warningf("failed to parse reference: %v", err) + klog.Warning(err) return false } + if !correctArch { + klog.Warningf("image %s is of wrong architecture", img) + return false + } + klog.Infof("Found %s in local docker daemon, skipping pull", img) + return true +} + +// isImageCorrectArch is needed to resolve +// https://github.com/kubernetes/minikube/pull/19205 +func isImageCorrectArch(img string) (bool, error) { + ref, err := name.ParseReference(img) + if err != nil { + return false, fmt.Errorf("failed to parse reference: %v", err) + } dImg, err := daemon.Image(ref) if err != nil { - klog.Warningf("failed to get image from daemon: %v", err) - return false + return false, fmt.Errorf("failed to get image from daemon: %v", err) } cfg, err := dImg.ConfigFile() if err != nil { - klog.Warningf("failed to get config for %s: %v", img, err) - return false + return false, fmt.Errorf("failed to get config for %s: %v", img, err) } - if cfg.Architecture != runtime.GOOS { - klog.Warningf("image %s is of wrong architecture", img) - return false - } - klog.Infof("Found %s in local docker daemon, skipping pull", img) - return true + return cfg.Architecture == runtime.GOOS, nil } // ImageToCache downloads img (if not present in cache) and writes it to the local cache directory From 23a8c35ba42c51c0333c1c9aa30a99122c409bf2 Mon Sep 17 00:00:00 2001 From: Steven Powell Date: Tue, 16 Jul 2024 18:36:49 -0500 Subject: [PATCH 5/5] update isImageCorrectArch comment --- pkg/minikube/download/image.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/minikube/download/image.go b/pkg/minikube/download/image.go index 3c4fc41aaf50..b099e71834f4 100644 --- a/pkg/minikube/download/image.go +++ b/pkg/minikube/download/image.go @@ -99,7 +99,8 @@ func ImageExistsInDaemon(img string) bool { return true } -// isImageCorrectArch is needed to resolve +// isImageCorrectArch returns true if the image arch is the same as the binary +// arch. This is needed to resolve // https://github.com/kubernetes/minikube/pull/19205 func isImageCorrectArch(img string) (bool, error) { ref, err := name.ParseReference(img)