kaniko icon indicating copy to clipboard operation
kaniko copied to clipboard

Single-snapshot breaks caching

Open AndreKR opened this issue 3 years ago • 4 comments

This might be difficult to fix, but I wanted to open an issue anyway to discuss possible solutions or workarounds.

When --single-snapshot is given, only a single snapshot is made at the end each stage. I don't know how the cache key is calculated for this final snapshot.

In a subsequent build, cache keys are calculated for each RUN line, but since those lines have never been snapshotted nor uploaded to the cache, they will always generate a cache miss.

There is a demonstration of the issue here: Command line Dockerfile Build log

Note how the cache key for the stage is 3789525c5a2203fceeee7a568b0a3d88a9a928cf7ddb2aa1111d47223e8939c0, but the cache key for the first RUN line is 73354b53a39213254fd5c366b87f7a6d67413c1ec7eca6223551fbf541b7541f, which never gets cached.

Description Yes/No
Please check if this a new feature you are proposing
  • - [X] (somewhat)
Please check if the build works in docker but not in kaniko (not applicable as docker build has no functionality equivalent to --single-snapshot
Please check if this error is seen when you use --cache flag
  • - [X]
Please check if your dockerfile is a multistage dockerfile
  • - [ ]

The full solution would probably entail calculating a cache key for the whole stage beforehand. I don't know if that is possible - actually it might? Cache keys only depend on contents of COPY file and the text of RUN lines, right? Both is know at the start of the build.

A bit of background info:

The reason why I personally use --single-snapshot is to have simpler output images, not performance. This opens the possibility of a workaround: Provide an option (like --snaphot-for-cache) that, if given in addition to --single-snapshot, still snapshots the separate layers to upload them to the cache but also makes one final snapshot for the target image.

The reason why I personally want to use --cache is that I have multistage builds with different targets but they all share previous stages. IOW, my Dockerfile looks like this:

FROM ... AS intermediate1
...

FROM .. AS target1
COPY --from=intermediate1

FROM .. AS target2
COPY --from=intermediate1

and then I run executor --target target1; executor --target target2, which results in intermediate1 being built twice. Therefore I'd like to have a cache for the whole intermediate1 stage without actually having to create a named image in the registry.

AndreKR avatar Jul 24 '21 18:07 AndreKR

Thanks for reporting, we're experiencing the same issue.

internalsystemerror avatar Jul 13 '22 13:07 internalsystemerror

I'm experiencing a similar problem related to combined usage of caching & single-snapshot. As described in this issue, kaniko builds executed with --single-snapshot seem to perform cache-lookups for each RUN but do not push to the cache , therefore leading to unnecessary rebuilds. However, it seems to be more problematic when those cache-lookups actually result in a hit (e.g. because a kaniko build on the same Dockerfile was executed before without --single-snapshot and created the cache entries), since it leads to failing builds or potentially even wrong output.

Steps to reproduce:

Dockerfile:

FROM busybox:1.35.0 as base
RUN touch file.txt
RUN touch somethingelse.txt

FROM base
RUN cat file.txt

kaniko image: gcr.io/kaniko-project/executor:v1.9.1-debug

kaniko args: run 1 (fill cache): --cache --skip-unused-stages --target base

run 2 (retreive cached layers built by run1): --cache --single-snapshot

observed behavior: run 2 fails with error

...
INFO[0003] No cached layer found for cmd RUN cat file.txt 
INFO[0003] Unpacking rootfs as cmd RUN cat file.txt requires it. 
INFO[0003] Initializing snapshotter ...                 
INFO[0003] Taking snapshot of full filesystem...        
INFO[0003] RUN cat file.txt                             
INFO[0003] Cmd: /bin/sh                                 
INFO[0003] Args: [-c cat file.txt]                      
INFO[0003] Running: [/bin/sh -c cat file.txt]           
cat: can't open 'file.txt': No such file or directory
error building image: error building stage: failed to execute command: waiting for process to exit: exit status 1

It seems like kaniko only retrieves&uses the cached-layer for the last RUN instruction and ignores other RUNs before that (resulting image contains somethingelse.txt but file.txt is missing) if the cache was filled without using single-snapshot.

lntzr avatar Mar 01 '23 13:03 lntzr