mirror of
https://github.com/GoogleContainerTools/kaniko
synced 2026-10-19 09:45:09 +02:00
Improve cache layer uploads. (#443)
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.
This commit is contained in:
@@ -43,3 +43,7 @@ func (b *BaseCommand) MetadataOnly() bool {
|
||||
func (b *BaseCommand) RequiresUnpackedFS() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *BaseCommand) ShouldCacheOutput() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -45,6 +46,8 @@ type DockerCommand interface {
|
||||
MetadataOnly() bool
|
||||
|
||||
RequiresUnpackedFS() bool
|
||||
|
||||
ShouldCacheOutput() bool
|
||||
}
|
||||
|
||||
func GetCommand(cmd instructions.Command, buildcontext string) (DockerCommand, error) {
|
||||
|
||||
@@ -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
|
||||
|
||||
+24
-16
@@ -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"
|
||||
@@ -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.
|
||||
@@ -184,6 +188,7 @@ func (s *stageBuilder) build() error {
|
||||
return err
|
||||
}
|
||||
|
||||
cacheGroup := errgroup.Group{}
|
||||
for index, command := range cmds {
|
||||
if command == nil {
|
||||
continue
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user