Skip to content
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

Merged
merged 9 commits into from
Sep 6, 2017
Merged

Conversation

r2d4
Copy link
Contributor

@r2d4 r2d4 commented Aug 24, 2017

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.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Aug 24, 2017
// 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"),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cc @dlorenc @cftorres this was my trick to get around the /etc/docker/certs.d error.

@r2d4
Copy link
Contributor Author

r2d4 commented Aug 24, 2017

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

@r2d4 r2d4 changed the title Cache images in minikube [WIP] Cache images in minikube Aug 24, 2017
@k8s-ci-robot k8s-ci-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Aug 24, 2017
@r2d4 r2d4 force-pushed the cache-images-4-minikube branch 2 times, most recently from 812fd4f to 58c8bc6 Compare August 25, 2017 06:17
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
@codecov-io
Copy link

codecov-io commented Aug 31, 2017

Codecov Report

Merging #1881 into master will decrease coverage by 0.82%.
The diff coverage is 2.85%.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
pkg/minikube/cluster/cluster.go 30.34% <ø> (ø) ⬆️
pkg/minikube/bootstrapper/localkube/localkube.go 30.85% <0%> (-1.74%) ⬇️
pkg/minikube/machine/cache_images.go 2.5% <2.5%> (ø)
cmd/minikube/cmd/start.go 10.09% <6.66%> (+0.13%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dd91fea...3fb711c. Read the comment docs.

@r2d4 r2d4 changed the title [WIP] Cache images in minikube Cache images in minikube Aug 31, 2017
@r2d4
Copy link
Contributor Author

r2d4 commented Aug 31, 2017

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)
Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

# 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
Copy link
Contributor

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.

Copy link
Contributor Author

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"
Copy link
Contributor

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?

Copy link
Contributor Author

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.

return nil
}

func CacheImages(images []string, cacheDir string) error {
Copy link
Contributor

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 {
Copy link
Contributor

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?

Copy link
Contributor Author

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

Copy link
Contributor Author

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?

Copy link
Contributor Author

@r2d4 r2d4 Sep 6, 2017

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.

Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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"
Copy link
Contributor

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.

Copy link
Contributor Author

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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.

@r2d4 r2d4 mentioned this pull request Aug 31, 2017
Copy link
Contributor

@dlorenc dlorenc left a 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.

@r2d4
Copy link
Contributor Author

r2d4 commented Sep 6, 2017

I'm waiting to upgrade containers/image and remove the certs.d hack until all of the libraries we vendor use lowercase sirupsen/logrus instead of Sirupsen/logrus.

Sirupsen/logrus
Azure/go-ansiterm
codedellemc/goscaleio
docker/distrubution
docker/docker
docker/go-connections
opencontainers/runc

@r2d4
Copy link
Contributor Author

r2d4 commented Sep 6, 2017

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

@r2d4
Copy link
Contributor Author

r2d4 commented Sep 6, 2017

Added the feature flag for cache-images, enabled by default.

To disable caching and loading, use minikube start --cache-images=false

@r2d4 r2d4 merged commit 0e6e930 into kubernetes:master Sep 6, 2017
@r2d4 r2d4 deleted the cache-images-4-minikube branch September 6, 2017 22:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants