-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache images in minikube #1881
Cache images in minikube #1881
Conversation
pkg/minikube/machine/cache_images.go
Outdated
// By default, the image library will try to look at /etc/docker/certs.d | ||
// As a non-root user, this would result in a permissions error, | ||
// so, we skip this step by just looking in the minikube home directory. | ||
DockerCertPath: constants.MakeMiniPath("cache"), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Im closing #1671 in favor of this approach. It's probably better not to pollute the ISO with these container images. This also allows us to selectively cache and load images, so we can load localkube's images and kubeadm's images. We could also modify this to cache addons |
813d69f
to
737bc4e
Compare
812fd4f
to
58c8bc6
Compare
This PR introduces caching of localkube images. It makes a best effort to cache the essential images localkube needs as minikube starts up. Currently, the list of cached images is hardcoded, but future work might entail 1. Cached images as a property of the cluster bootstrapper - to allow localkube and kubeadm to cache their respective images. 2. Addons contain image information. Then, we can selectively cache and preload only the addon images that are enabled.
We shouldn't blow away the cache on every integration test. keep .minikube for tests hack/jenkins: Delete VM before manual cleanup
It is useful to be able to have a command runner to call directly in the integration tests
5419365
to
e7aa059
Compare
Codecov Report
@@ Coverage Diff @@
## master #1881 +/- ##
==========================================
- Coverage 31.05% 30.22% -0.83%
==========================================
Files 74 75 +1
Lines 4302 4433 +131
==========================================
+ Hits 1336 1340 +4
- Misses 2791 2916 +125
- Partials 175 177 +2
Continue to review full report at Codecov.
|
I think this is ready for review @dlorenc @aaron-prindle. As a nice bonus, this makes minikube usable offline after the images have been cached. |
@@ -67,7 +67,7 @@ KUBE_CROSS_DOCKER_CMD := docker run -w /go/src/$(REPOPATH) --user $(shell id -u) | |||
|
|||
# $(call MINIKUBE_GO_BUILD_CMD, output file, OS) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The file perms changed on here too to 755.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
hack/jenkins/common.sh
Outdated
# See the default image | ||
./out/minikube-${OS_ARCH} start -h | grep iso | ||
|
||
# see what driver we are using | ||
which docker-machine-driver-${VM_DRIVER} || true | ||
tree ~/.minikube || true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about "find ~/.minikube"? Not all systems have tree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up putting it on the build slaves, find is probably simpler
"github.com/pkg/errors" | ||
) | ||
|
||
const tempLoadDir = "/tmp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we use this? Could we use os.Tempdir?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in the minikube VM. I think I tried to send the files over stdin with docker load, but I think it was a little tricky. I ended up just scping them into the VM and cleaning them up after the load.
pkg/minikube/machine/cache_images.go
Outdated
return nil | ||
} | ||
|
||
func CacheImages(images []string, cacheDir string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A comment explaining what the resulting cache directory will look like might help.
return nil | ||
} | ||
|
||
func LoadImages(cmd bootstrapper.CommandRunner, images []string, cacheDir string) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function looks almost exactly the same as the previous one. Any way you could refactor it to take the LoadFromCache/Cache functions as a parameter to avoid the repetition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yeah good catch. Will do that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The functions have different signatures, so I've been having a little trouble figuring out how to share code here. Any suggestions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't fix this one. I gave it an attempt, but all my attempts ended up way more verbose than the current solution.
I think this would probably be easiest if Cache and Load were methods on the bootstrapper, so they could have the same signature. However, that limits when we can actually call them. Since CacheImages doesn't actually require the bootstrapper, we can call it as soon as we start minikube up, rather than possibly waiting for SSH to be available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, one more quick idea here. Does it make sense to start loading each image as it becomes available in the cache? Right now you're downloading all the images in parallel, then loading all the images in parallel. What if it was "download and load" all images in parallel?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had that before, but I think this is actually better. Combining cache and load forces us to wait for the machine to be SSH-able before we do anything (since we'll need a bootstrapper before we run load)
This caches in parallel as soon as we run a minikube start
, but then as soon as the machine is ready, it tries a blocking load in parallel. So both cache and load start as soon as they can.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, good call.
@@ -22,6 +22,8 @@ import ( | |||
"strings" | |||
"testing" | |||
|
|||
"k8s.io/minikube/pkg/minikube/constants" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
755 on this file too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
if err := machine.CacheImages(integrationTestImages, constants.ImageCacheDir); err != nil { | ||
t.Fatalf("caching images: %s", err) | ||
} | ||
if err := machine.LoadFromCacheBlocking(&minikubeRunner, constants.ImageCacheDir); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have this in a loop. Is that just because we only have one image here? It's used in a loop later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we're just calling the single loader directly for busybox, where the other one loads a list of images.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it probably makes sense to leave this behind a flag that's turned off by default at first, and enable it in our CI for a little while, WDYT? The code looks good otherwise.
I'm waiting to upgrade containers/image and remove the certs.d hack until all of the libraries we vendor use lowercase
|
Why disable it? It won't error or prevent minikube from running. If it fails a cache or a load, it will simply fail silently and log a warning. Seems like a pretty safe optimization |
Added the feature flag for cache-images, enabled by default. To disable caching and loading, use |
This PR uses the containers/image library to pull images while minikube is starting up, cache them in the minikube home directory, and then load them into the docker daemon.
This makes the cluster boot up much quicker and reliably.
Theres probably a bit of work to be done with how I'm caching the images to save space by reusing layers, but I think this is a good first pass.