treewide: stop using LZ4 for initrd compression
There are two issues at play here: One is a bug in pierrec/lz4 when
using the legacy framing format [1]. This bit us when we hit a broken
size region with CL:2130, taking hours to debug.
The other is the fact that the Linux LZ4 frame format has significant
design issues [2], especially with concatenanted initrds.
The first issue could be fixed by switching to a different LZ4
implementation (we do even have the reference impl in the monorepo) but
there is no API to generate the legacy frame format and things like [3],
a patch carried by Ubuntu to fix more edge cases just do not inspire
confidence in such a solution.
Thus, this CL switches over to using zstd for compressing initrds.
Zstd is slower than LZ4 for decompressing, but it still decompresses at
multiple GB/s per core while having a much better compression ratio.
It also doesn't have any Linux-specific bits and Linux uses the
reference implementation for decoding, which should make it much more
robust. So overall I think this is a good tradeoff.
[1] https://github.com/pierrec/lz4/issues/156
[2] https://github.com/lz4/lz4/issues/956#issuecomment-736705712
[3] https://launchpadlibrarian.net/507407918/0001-unlz4-Handle-0-size-chunks-discard-trailing-padding-.patch
Change-Id: I69cf69f2f361de325f4b39f2d3644ee729643716
Reviewed-on: https://review.monogon.dev/c/monogon/+/2313
Tested-by: Jenkins CI
Reviewed-by: Serge Bazanski <serge@monogon.tech>
diff --git a/cloud/agent/e2e/main_test.go b/cloud/agent/e2e/main_test.go
index 27bcd03..277cc55 100644
--- a/cloud/agent/e2e/main_test.go
+++ b/cloud/agent/e2e/main_test.go
@@ -21,7 +21,7 @@
"time"
"github.com/cavaliergopher/cpio"
- "github.com/pierrec/lz4/v4"
+ "github.com/klauspost/compress/zstd"
"golang.org/x/sys/unix"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
@@ -183,7 +183,7 @@
if err != nil {
t.Fatal(err)
}
- initramfsOrigPath, err := datafile.ResolveRunfile("cloud/agent/initramfs.cpio.lz4")
+ initramfsOrigPath, err := datafile.ResolveRunfile("cloud/agent/initramfs.cpio.zst")
if err != nil {
t.Fatal(err)
}
@@ -207,9 +207,11 @@
if err != nil {
t.Fatal(err)
}
- compressedOut := lz4.NewWriter(initramfsFile)
- compressedOut.Apply(lz4.LegacyOption(true))
- cpioW := cpio.NewWriter(compressedOut)
+ compressedW, err := zstd.NewWriter(initramfsFile, zstd.WithEncoderLevel(1))
+ if err != nil {
+ t.Fatal(err)
+ }
+ cpioW := cpio.NewWriter(compressedW)
cpioW.WriteHeader(&cpio.Header{
Name: "/init.pb",
Size: int64(len(agentInitRaw)),
@@ -217,7 +219,7 @@
})
cpioW.Write(agentInitRaw)
cpioW.Close()
- compressedOut.Close()
+ compressedW.Close()
grpcGuestFwd := fmt.Sprintf("guestfwd=tcp:%s-tcp:127.0.0.1:%d", grpcAddr.String(), grpcListenAddr.Port)
blobGuestFwd := fmt.Sprintf("guestfwd=tcp:%s-tcp:127.0.0.1:%d", blobAddr.String(), blobListenAddr.Port)