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

Fix upgrade size calculation inside k8s #537

Merged
merged 5 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ require (
require (
github.com/distribution/reference v0.6.0
github.com/gofrs/uuid v4.4.0+incompatible
github.com/google/go-github/v64 v64.0.0
github.com/twpayne/go-vfs/v5 v5.0.4
github.com/google/go-github/v63 v63.0.0
github.com/twpayne/go-vfs/v4 v4.3.0
)

require (
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004 h1:G+9t9cEtnC9jFiTxyptEKuNIAbiN5ZCQzX2a74lj3xg=
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004/go.mod h1:KmHnJWQrgEvbuy0vcvj00gtMqbvNn1L+3YUZLK/B92c=
github.com/kairos-io/kairos-sdk v0.4.2 h1:tq0a6R9qSotatFt20q/+oIHJSN+XTQWji4XgHk5Vvlw=
github.com/kairos-io/kairos-sdk v0.4.2/go.mod h1:1x8VaVt1ppXxQUlNyDRksoDglR423hxfEtjx6qWDO7w=
github.com/kairos-io/kairos-sdk v0.4.3 h1:gIC/PsWjv9/Z+6RIHRG9IS5MB9gACw1ZjPAi7VydSSo=
github.com/kairos-io/kairos-sdk v0.4.3/go.mod h1:bxUPzirl8vNtqB48FJ2835QKio3d3PrHbkAejkibV8I=
github.com/kairos-io/kcrypt v0.12.2 h1:+lr8FGS0AW6D5dWSmaR3+AobL1TBTnOFgCSYctKY+5I=
github.com/kairos-io/kcrypt v0.12.2/go.mod h1:7SPiHzNMYl4MlxeB30s1YlHDYByTusu7u1mU5Nvicm0=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
Expand Down Expand Up @@ -791,8 +791,8 @@ howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/mount-utils v0.31.0 h1:o+a+n6gyZ7MGc6bIERU3LeFTHbLDBiVReaDpWlJotUE=
k8s.io/mount-utils v0.31.0/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU=
k8s.io/mount-utils v0.31.1 h1:f8UrH9kRynljmdNGM6BaCvFUON5ZPKDgE+ltmYqI4wA=
k8s.io/mount-utils v0.31.1/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
pault.ag/go/modprobe v0.1.2 h1:bblunaPhqpTxGDJ5TVFW/4gheohBPleF2dIV6j6sWkI=
Expand Down
28 changes: 25 additions & 3 deletions pkg/config/spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,11 +811,33 @@ func GetSourceSize(config *Config, source *v1.ImageSource) (int64, error) {
size = int64(float64(size) * 2.5)
case source.IsDir():
filesVisited = make(map[string]bool, 30000) // An Ubuntu system has around 27k files. This improves performance by not having to resize the map for every file visited

// In kubernetes we use the suc script to upgrade (https://github.com/kairos-io/packages/blob/main/packages/system/suc-upgrade/suc-upgrade.sh)
// , which mounts the host root into $HOST_DIR
// we should skip that dir when calculating the size as we would be doubling the calculated size
// Plus we will hit the usual things when checking a running system. Processes that go away, tmpfiles, etc...

// This is always set for pods running under kubernetes
underKubernetes := os.Getenv("KUBERNETES_SERVICE_HOST")
// Try to get the HOST_DIR in case we are not using the default one
hostDir := os.Getenv("HOST_DIR")
// If we are under kubernetes but the HOST_DIR var is empty, default to /host as system-upgrade-controller mounts
// the host in that dir by default
if underKubernetes != "" && hostDir == "" {
hostDir = "/host"
}
err = fsutils.WalkDirFs(config.Fs, source.Value(), func(path string, d fs.DirEntry, err error) error {
v := getSize(&size, filesVisited, path, d, err)

return v
// If its empty we are just not setting it, so probably out of the k8s upgrade path
if hostDir != "" && strings.HasPrefix(path, hostDir) {
config.Logger.Logger.Debug().Str("path", path).Str("hostDir", hostDir).Msg("Skipping file as it is a host directory")
} else if strings.HasPrefix(path, "/proc") || strings.HasPrefix(path, "/dev") || strings.HasPrefix(path, "/run") {
config.Logger.Logger.Debug().Str("path", path).Str("hostDir", hostDir).Msg("Skipping dir as it is a system directory (/proc, /dev or /run)")
} else {
v := getSize(&size, filesVisited, path, d, err)
return v
}

return nil
})

case source.IsFile():
Expand Down
41 changes: 39 additions & 2 deletions pkg/config/spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package config_test

import (
"bytes"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -653,19 +654,23 @@ func createFileOfSizeInMB(filename string, sizeInMB int) error {
return nil
}

var _ = Describe("GetSourceSize", func() {
var _ = Describe("GetSourceSize", Label("GetSourceSize"), func() {
var tempDir string
var tempFilePath string
var err error
var logger sdkTypes.KairosLogger
var conf *config.Config
var imageSource *v1.ImageSource
var memLog bytes.Buffer

BeforeEach(func() {
tempDir, err = os.MkdirTemp("/tmp", "kairos-test")
Expect(err).To(BeNil())

logger = sdkTypes.NewNullLogger()
//logger = sdkTypes.NewNullLogger()
memLog = bytes.Buffer{}
logger = sdkTypes.NewBufferLogger(&memLog)
logger.SetLevel("debug")
conf = config.NewConfig(
config.WithLogger(logger),
)
Expand All @@ -678,6 +683,7 @@ var _ = Describe("GetSourceSize", func() {
})

AfterEach(func() {
fmt.Println(memLog.String())
defer os.RemoveAll(tempDir)
})

Expand All @@ -693,4 +699,35 @@ var _ = Describe("GetSourceSize", func() {
Expect(err).ToNot(HaveOccurred())
Expect(sizeAfter).To(Equal(sizeBefore))
})
It("Skips the kubernetes host dir when calculating the sizes if set", func() {
sizeBefore, err := config.GetSourceSize(conf, imageSource)
Expect(err).To(BeNil())
Expect(sizeBefore).ToNot(BeZero())

Expect(os.Mkdir(filepath.Join(tempDir, "host"), os.ModePerm)).ToNot(HaveOccurred())
Expect(createFileOfSizeInMB(filepath.Join(tempDir, "host", "what.txt"), 200)).ToNot(HaveOccurred())
// Set env var like the suc upgrade does
Expect(os.Setenv("HOST_DIR", filepath.Join(tempDir, "host"))).ToNot(HaveOccurred())

sizeAfter, err := config.GetSourceSize(conf, imageSource)
Expect(err).ToNot(HaveOccurred())
Expect(sizeAfter).To(Equal(sizeBefore))
})
It("Counts the kubernetes host dir when calculating the sizes if not set", func() {
sizeBefore, err := config.GetSourceSize(conf, imageSource)
Expect(err).To(BeNil())
Expect(sizeBefore).ToNot(BeZero())

Expect(os.Mkdir(filepath.Join(tempDir, "host"), os.ModePerm)).ToNot(HaveOccurred())
Expect(createFileOfSizeInMB(filepath.Join(tempDir, "host", "what.txt"), 200)).ToNot(HaveOccurred())

sizeAfter, err := config.GetSourceSize(conf, imageSource)
Expect(err).ToNot(HaveOccurred())
Expect(sizeAfter).ToNot(Equal(sizeBefore))
Expect(sizeAfter).ToNot(BeZero())
// Size is 2 files of 200 + 100Mb on top, normalized from bytes to MB
// So take those 200Mb, converts to bytes by multiplying them (400*1024*1024), then back to MB by dividing
// what we get (/1000/1000) then we finish by adding and extra 100MB on top, like the GetSourceSize does internally
Expect(sizeAfter).To(Equal(int64((400 * 1024 * 1024 / 1000 / 1000) + 100)))
})
})
Loading