From 9c1a4f4fc0f50764c7aba448d8146500879f5716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Sun, 18 Apr 2021 14:04:26 +0200 Subject: [PATCH 1/3] Allow to load remote images directly without cache --- cmd/minikube/cmd/image.go | 11 ++++ pkg/minikube/cruntime/containerd.go | 5 ++ pkg/minikube/cruntime/cri.go | 13 +++++ pkg/minikube/cruntime/crio.go | 5 ++ pkg/minikube/cruntime/cruntime.go | 2 + pkg/minikube/cruntime/docker.go | 13 +++++ pkg/minikube/machine/cache_images.go | 80 ++++++++++++++++++++++++++ site/content/en/docs/commands/image.md | 1 + 8 files changed, 130 insertions(+) diff --git a/cmd/minikube/cmd/image.go b/cmd/minikube/cmd/image.go index d9baa0f5b2c8..25b2b1787578 100644 --- a/cmd/minikube/cmd/image.go +++ b/cmd/minikube/cmd/image.go @@ -38,6 +38,7 @@ var imageCmd = &cobra.Command{ } var ( + pull bool imgDaemon bool imgRemote bool ) @@ -74,6 +75,15 @@ var loadImageCmd = &cobra.Command{ exit.Error(reason.Usage, "loading profile", err) } + if pull { + // Pull image from remote registry, without doing any caching except in container runtime. + // This is similar to daemon.Image but it is done by the container runtime in the cluster. + if err := machine.DoPullImages(args, profile); err != nil { + exit.Error(reason.GuestImageLoad, "Failed to pull image", err) + } + return + } + var local bool if imgRemote || imgDaemon { local = false @@ -166,6 +176,7 @@ $ minikube image list func init() { imageCmd.AddCommand(loadImageCmd) imageCmd.AddCommand(removeImageCmd) + loadImageCmd.Flags().BoolVarP(&pull, "pull", "", false, "Pull the remote image (no caching)") loadImageCmd.Flags().BoolVar(&imgDaemon, "daemon", false, "Cache image from docker daemon") loadImageCmd.Flags().BoolVar(&imgRemote, "remote", false, "Cache image from remote registry") imageCmd.AddCommand(listImageCmd) diff --git a/pkg/minikube/cruntime/containerd.go b/pkg/minikube/cruntime/containerd.go index c811f40f3f38..11bcaf9fef1e 100644 --- a/pkg/minikube/cruntime/containerd.go +++ b/pkg/minikube/cruntime/containerd.go @@ -267,6 +267,11 @@ func (r *Containerd) LoadImage(path string) error { return nil } +// PullImage pulls an image into this runtime +func (r *Containerd) PullImage(name string) error { + return pullCRIImage(r.Runner, name) +} + // RemoveImage removes a image func (r *Containerd) RemoveImage(name string) error { return removeCRIImage(r.Runner, name) diff --git a/pkg/minikube/cruntime/cri.go b/pkg/minikube/cruntime/cri.go index f6f602da5254..7c1c1e5719ae 100644 --- a/pkg/minikube/cruntime/cri.go +++ b/pkg/minikube/cruntime/cri.go @@ -187,6 +187,19 @@ func killCRIContainers(cr CommandRunner, ids []string) error { return nil } +// pullCRIImage pulls image using crictl +func pullCRIImage(cr CommandRunner, name string) error { + klog.Infof("Pulling image: %s", name) + + crictl := getCrictlPath(cr) + args := append([]string{crictl, "pull"}, name) + c := exec.Command("sudo", args...) + if _, err := cr.RunCmd(c); err != nil { + return errors.Wrap(err, "crictl") + } + return nil +} + // removeCRIImage remove image using crictl func removeCRIImage(cr CommandRunner, name string) error { klog.Infof("Removing image: %s", name) diff --git a/pkg/minikube/cruntime/crio.go b/pkg/minikube/cruntime/crio.go index 4c1eee2c2711..210a2927b7b2 100644 --- a/pkg/minikube/cruntime/crio.go +++ b/pkg/minikube/cruntime/crio.go @@ -187,6 +187,11 @@ func (r *CRIO) LoadImage(path string) error { return nil } +// PullImage pulls an image +func (r *CRIO) PullImage(name string) error { + return pullCRIImage(r.Runner, name) +} + // RemoveImage removes a image func (r *CRIO) RemoveImage(name string) error { return removeCRIImage(r.Runner, name) diff --git a/pkg/minikube/cruntime/cruntime.go b/pkg/minikube/cruntime/cruntime.go index 1cd352fe61fa..979b8d072127 100644 --- a/pkg/minikube/cruntime/cruntime.go +++ b/pkg/minikube/cruntime/cruntime.go @@ -95,6 +95,8 @@ type Manager interface { // Load an image idempotently into the runtime on a host LoadImage(string) error + // Pull an image to the runtime from the container registry + PullImage(string) error // ImageExists takes image name and image sha checks if an it exists ImageExists(string, string) bool diff --git a/pkg/minikube/cruntime/docker.go b/pkg/minikube/cruntime/docker.go index 50b1f762897d..4298e75c1b71 100644 --- a/pkg/minikube/cruntime/docker.go +++ b/pkg/minikube/cruntime/docker.go @@ -191,6 +191,19 @@ func (r *Docker) LoadImage(path string) error { return nil } +// PullImage pulls an image +func (r *Docker) PullImage(name string) error { + klog.Infof("Pulling image: %s", name) + if r.UseCRI { + return pullCRIImage(r.Runner, name) + } + c := exec.Command("docker", "pull", name) + if _, err := r.Runner.RunCmd(c); err != nil { + return errors.Wrap(err, "pull image docker.") + } + return nil +} + // RemoveImage removes a image func (r *Docker) RemoveImage(name string) error { klog.Infof("Removing image: %s", name) diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index caea9a212c6c..41ca1b395f8a 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -294,6 +294,86 @@ func transferAndLoadImage(cr command.Runner, k8s config.KubernetesConfig, src st return nil } +// pullImages pulls images to the container run time +func pullImages(cruntime cruntime.Manager, images []string) error { + klog.Infof("PullImages start: %s", images) + start := time.Now() + + defer func() { + klog.Infof("PullImages completed in %s", time.Since(start)) + }() + + var g errgroup.Group + + for _, image := range images { + image := image + g.Go(func() error { + return cruntime.PullImage(image) + }) + } + if err := g.Wait(); err != nil { + return errors.Wrap(err, "error pulling images") + } + klog.Infoln("Successfully pulled images") + return nil +} + +func DoPullImages(images []string, profile *config.Profile) error { + api, err := NewAPIClient() + if err != nil { + return errors.Wrap(err, "error creating api client") + } + defer api.Close() + + succeeded := []string{} + failed := []string{} + + pName := profile.Name + + c, err := config.Load(pName) + if err != nil { + klog.Errorf("Failed to load profile %q: %v", pName, err) + return errors.Wrapf(err, "error loading config for profile :%v", pName) + } + + for _, n := range c.Nodes { + m := config.MachineName(*c, n) + + status, err := Status(api, m) + if err != nil { + klog.Warningf("error getting status for %s: %v", m, err) + continue + } + + if status == state.Running.String() { + h, err := api.Load(m) + if err != nil { + klog.Warningf("Failed to load machine %q: %v", m, err) + continue + } + runner, err := CommandRunner(h) + if err != nil { + return err + } + cruntime, err := cruntime.New(cruntime.Config{Type: c.KubernetesConfig.ContainerRuntime, Runner: runner}) + if err != nil { + return errors.Wrap(err, "error creating container runtime") + } + err = pullImages(cruntime, images) + if err != nil { + failed = append(failed, m) + klog.Warningf("Failed to pull images for profile %s %v", pName, err.Error()) + continue + } + succeeded = append(succeeded, m) + } + } + + klog.Infof("succeeded pulling to: %s", strings.Join(succeeded, " ")) + klog.Infof("failed pulling to: %s", strings.Join(failed, " ")) + return nil +} + // removeImages removes images from the container run time func removeImages(cruntime cruntime.Manager, images []string) error { klog.Infof("RemovingImages start: %s", images) diff --git a/site/content/en/docs/commands/image.md b/site/content/en/docs/commands/image.md index ac0d42bdb456..a1457499fa95 100644 --- a/site/content/en/docs/commands/image.md +++ b/site/content/en/docs/commands/image.md @@ -139,6 +139,7 @@ minikube image load image.tar ``` --daemon Cache image from docker daemon + --pull Pull the remote image (no caching) --remote Cache image from remote registry ``` From d8050ee03c0cb5b0a7c75a10d340d08dbcb7c797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Mon, 19 Apr 2021 21:55:29 +0200 Subject: [PATCH 2/3] Add documentation to the public image functions --- cmd/minikube/cmd/image.go | 2 +- pkg/minikube/machine/cache_images.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/cmd/minikube/cmd/image.go b/cmd/minikube/cmd/image.go index 25b2b1787578..62c50b44f543 100644 --- a/cmd/minikube/cmd/image.go +++ b/cmd/minikube/cmd/image.go @@ -78,7 +78,7 @@ var loadImageCmd = &cobra.Command{ if pull { // Pull image from remote registry, without doing any caching except in container runtime. // This is similar to daemon.Image but it is done by the container runtime in the cluster. - if err := machine.DoPullImages(args, profile); err != nil { + if err := machine.PullImages(args, profile); err != nil { exit.Error(reason.GuestImageLoad, "Failed to pull image", err) } return diff --git a/pkg/minikube/machine/cache_images.go b/pkg/minikube/machine/cache_images.go index 41ca1b395f8a..9412dca1a614 100644 --- a/pkg/minikube/machine/cache_images.go +++ b/pkg/minikube/machine/cache_images.go @@ -318,7 +318,8 @@ func pullImages(cruntime cruntime.Manager, images []string) error { return nil } -func DoPullImages(images []string, profile *config.Profile) error { +// PullImages pulls images to all nodes in profile +func PullImages(images []string, profile *config.Profile) error { api, err := NewAPIClient() if err != nil { return errors.Wrap(err, "error creating api client") @@ -398,6 +399,7 @@ func removeImages(cruntime cruntime.Manager, images []string) error { return nil } +// RemoveImages removes images from all nodes in profile func RemoveImages(images []string, profile *config.Profile) error { api, err := NewAPIClient() if err != nil { @@ -454,6 +456,7 @@ func RemoveImages(images []string, profile *config.Profile) error { return nil } +// ListImages lists images on all nodes in profile func ListImages(profile *config.Profile) error { api, err := NewAPIClient() if err != nil { From 7c7c25da1887f299ff42721e3a7c4f55cfb07983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anders=20F=20Bj=C3=B6rklund?= Date: Mon, 19 Apr 2021 21:58:16 +0200 Subject: [PATCH 3/3] Fix typo in comment to make golint more happy --- pkg/minikube/cruntime/cruntime.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/minikube/cruntime/cruntime.go b/pkg/minikube/cruntime/cruntime.go index 979b8d072127..1a5d0a8ae71d 100644 --- a/pkg/minikube/cruntime/cruntime.go +++ b/pkg/minikube/cruntime/cruntime.go @@ -152,7 +152,7 @@ type ListContainersOptions struct { Namespaces []string } -// ListImageOptions are the options to use for listing images +// ListImagesOptions are the options to use for listing images type ListImagesOptions struct { }