Skip to content

Commit

Permalink
Improve cache layer uploads. (GoogleContainerTools#443)
Browse files Browse the repository at this point in the history
This change only uploads layers that were created from cache misses on RUN commands.
It also improves the cache-checking logic to handle this case.
Finally, it makes cache layer uploads happen in parallel with the rest of the build, logging
a warning if any fail.
  • Loading branch information
dlorenc committed Nov 12, 2018
1 parent 063663e commit 8408c53
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 17 deletions.
4 changes: 4 additions & 0 deletions pkg/commands/base_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ func (b *BaseCommand) MetadataOnly() bool {
func (b *BaseCommand) RequiresUnpackedFS() bool {
return false
}

func (b *BaseCommand) ShouldCacheOutput() bool {
return false
}
3 changes: 3 additions & 0 deletions pkg/commands/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type DockerCommand interface {
String() string
// A list of files to snapshot, empty for metadata commands or nil if we don't know
FilesToSnapshot() []string

// Return a cache-aware implementation of this command, if it exists.
CacheCommand(v1.Image) DockerCommand

Expand All @@ -45,6 +46,8 @@ type DockerCommand interface {
MetadataOnly() bool

RequiresUnpackedFS() bool

ShouldCacheOutput() bool
}

func GetCommand(cmd instructions.Command, buildcontext string) (DockerCommand, error) {
Expand Down
4 changes: 4 additions & 0 deletions pkg/commands/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ func (r *RunCommand) RequiresUnpackedFS() bool {
return true
}

func (r *RunCommand) ShouldCacheOutput() bool {
return true
}

type CachingRunCommand struct {
BaseCommand
img v1.Image
Expand Down
40 changes: 24 additions & 16 deletions pkg/executor/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import (
"strconv"
"time"

"golang.org/x/sync/errgroup"

"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/mutate"
Expand Down Expand Up @@ -119,15 +121,17 @@ func (s *stageBuilder) optimize(compositeKey CompositeCache, cfg v1.Config, cmds
if err != nil {
return err
}
img, err := layerCache.RetrieveLayer(ck)
if err != nil {
logrus.Infof("No cached layer found for cmd %s", command.String())
break
}
if command.ShouldCacheOutput() {
img, err := layerCache.RetrieveLayer(ck)
if err != nil {
logrus.Infof("No cached layer found for cmd %s", command.String())
break
}

if cacheCmd := command.CacheCommand(img); cacheCmd != nil {
logrus.Infof("Using caching version of cmd: %s", command.String())
cmds[i] = cacheCmd
if cacheCmd := command.CacheCommand(img); cacheCmd != nil {
logrus.Infof("Using caching version of cmd: %s", command.String())
cmds[i] = cacheCmd
}
}

// Mutate the config for any commands that require it.
Expand Down Expand Up @@ -184,6 +188,7 @@ func (s *stageBuilder) build() error {
return err
}

cacheGroup := errgroup.Group{}
for index, command := range cmds {
if command == nil {
continue
Expand Down Expand Up @@ -222,10 +227,19 @@ func (s *stageBuilder) build() error {
if err != nil {
return err
}
if err := s.saveSnapshotToImage(command.String(), ck, tarPath); err != nil {
// Push layer to cache (in parallel) now along with new config file
if s.opts.Cache && command.ShouldCacheOutput() {
cacheGroup.Go(func() error {
return pushLayerToCache(s.opts, ck, tarPath, command.String())
})
}
if err := s.saveSnapshotToImage(command.String(), tarPath); err != nil {
return err
}
}
if err := cacheGroup.Wait(); err != nil {
logrus.Warnf("error uploading layer to cache: %s", err)
}
return nil
}

Expand Down Expand Up @@ -266,7 +280,7 @@ func (s *stageBuilder) shouldTakeSnapshot(index int, files []string) bool {
return true
}

func (s *stageBuilder) saveSnapshotToImage(createdBy string, ck string, tarPath string) error {
func (s *stageBuilder) saveSnapshotToImage(createdBy string, tarPath string) error {
if tarPath == "" {
return nil
}
Expand All @@ -283,12 +297,6 @@ func (s *stageBuilder) saveSnapshotToImage(createdBy string, ck string, tarPath
if err != nil {
return err
}
// Push layer to cache now along with new config file
if s.opts.Cache {
if err := pushLayerToCache(s.opts, ck, layer, createdBy); err != nil {
return err
}
}
s.image, err = mutate.Append(s.image,
mutate.Addendum{
Layer: layer,
Expand Down
6 changes: 5 additions & 1 deletion pkg/executor/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,11 @@ func DoPush(image v1.Image, opts *config.KanikoOptions) error {

// pushLayerToCache pushes layer (tagged with cacheKey) to opts.Cache
// if opts.Cache doesn't exist, infer the cache from the given destination
func pushLayerToCache(opts *config.KanikoOptions, cacheKey string, layer v1.Layer, createdBy string) error {
func pushLayerToCache(opts *config.KanikoOptions, cacheKey string, tarPath string, createdBy string) error {
layer, err := tarball.LayerFromFile(tarPath)
if err != nil {
return err
}
cache, err := cache.Destination(opts, cacheKey)
if err != nil {
return errors.Wrap(err, "getting cache destination")
Expand Down

0 comments on commit 8408c53

Please sign in to comment.