Add containerd migration to daemon startup

Add layer migration on startup
Use image size threshold rather than image count
Add daemon integration test
Add test for migrating to containerd snapshotters
Add vfs migration
Add tar export for containerd migration
Add containerd migration test with save and load

Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
Derek McGowan
2024-10-09 15:19:32 -07:00
parent 4b97831992
commit 9f5f4f5a42
4 changed files with 645 additions and 51 deletions

View File

@@ -0,0 +1,159 @@
package daemon // import "github.com/docker/docker/integration/daemon"
import (
"bytes"
"io"
"os"
"runtime"
"testing"
containertypes "github.com/moby/moby/api/types/container"
"github.com/moby/moby/api/types/image"
"github.com/moby/moby/v2/integration/internal/container"
"github.com/moby/moby/v2/testutil"
"github.com/moby/moby/v2/testutil/daemon"
"github.com/moby/moby/v2/testutil/fixtures/load"
"gotest.tools/v3/assert"
"gotest.tools/v3/skip"
)
func TestMigrateOverlaySnapshotter(t *testing.T) {
testMigrateSnapshotter(t, "overlay2", "overlayfs")
}
func TestMigrateNativeSnapshotter(t *testing.T) {
testMigrateSnapshotter(t, "vfs", "native")
}
func testMigrateSnapshotter(t *testing.T, graphdriver, snapshotter string) {
skip.If(t, runtime.GOOS != "linux")
skip.If(t, os.Getenv("TEST_INTEGRATION_USE_SNAPSHOTTER") != "")
ctx := testutil.StartSpan(baseContext, t)
d := daemon.New(t)
defer d.Stop(t)
d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver)
info := d.Info(t)
id := info.ID
assert.Check(t, id != "")
assert.Equal(t, info.Containers, 0)
assert.Equal(t, info.Images, 0)
assert.Equal(t, info.Driver, graphdriver)
load.FrozenImagesLinux(ctx, d.NewClientT(t), "busybox:latest")
info = d.Info(t)
allImages := info.Images
assert.Check(t, allImages > 0)
apiClient := d.NewClientT(t)
containerID := container.Run(ctx, t, apiClient, func(c *container.TestContainerConfig) {
c.Name = "Migration-1-" + snapshotter
c.Config.Image = "busybox:latest"
c.Config.Cmd = []string{"top"}
})
d.Stop(t)
// Start with migration feature but with a container which will prevent migration
d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver, "--feature", "containerd-migration")
info = d.Info(t)
assert.Equal(t, info.ID, id)
assert.Equal(t, info.Driver, graphdriver)
assert.Equal(t, info.Containers, 1)
assert.Equal(t, info.Images, allImages)
container.Remove(ctx, t, apiClient, containerID, containertypes.RemoveOptions{
Force: true,
})
d.Stop(t)
d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver, "--feature", "containerd-migration")
info = d.Info(t)
assert.Equal(t, info.ID, id)
assert.Equal(t, info.Containers, 0)
assert.Equal(t, info.Driver, snapshotter, "expected migrate to switch from %s to %s", graphdriver, snapshotter)
assert.Equal(t, info.Images, allImages)
result := container.RunAttach(ctx, t, apiClient, func(c *container.TestContainerConfig) {
c.Name = "Migration-2-" + snapshotter
c.Config.Image = "busybox:latest"
c.Config.Cmd = []string{"echo", "hello"}
})
assert.Equal(t, result.ExitCode, 0)
container.Remove(ctx, t, apiClient, result.ContainerID, containertypes.RemoveOptions{})
}
func TestMigrateSaveLoad(t *testing.T) {
skip.If(t, runtime.GOOS != "linux")
skip.If(t, os.Getenv("TEST_INTEGRATION_USE_SNAPSHOTTER") != "")
var (
ctx = testutil.StartSpan(baseContext, t)
d = daemon.New(t)
graphdriver = "overlay2"
snapshotter = "overlayfs"
)
defer d.Stop(t)
d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver)
info := d.Info(t)
id := info.ID
assert.Check(t, id != "")
assert.Equal(t, info.Containers, 0)
assert.Equal(t, info.Images, 0)
assert.Equal(t, info.Driver, graphdriver)
load.FrozenImagesLinux(ctx, d.NewClientT(t), "busybox:latest")
info = d.Info(t)
allImages := info.Images
assert.Check(t, allImages > 0)
d.Stop(t)
d.Start(t, "--iptables=false", "--ip6tables=false", "-s", graphdriver, "--feature", "containerd-migration")
info = d.Info(t)
assert.Equal(t, info.ID, id)
assert.Equal(t, info.Containers, 0)
assert.Equal(t, info.Driver, snapshotter, "expected migrate to switch from %s to %s", graphdriver, snapshotter)
assert.Equal(t, info.Images, allImages)
apiClient := d.NewClientT(t)
// Save image to buffer
rdr, err := apiClient.ImageSave(ctx, []string{"busybox:latest"}, image.SaveOptions{})
assert.NilError(t, err)
buf := bytes.NewBuffer(nil)
io.Copy(buf, rdr)
rdr.Close()
// Delete all images
list, err := apiClient.ImageList(ctx, image.ListOptions{})
assert.NilError(t, err)
for _, i := range list {
_, err = apiClient.ImageRemove(ctx, i.ID, image.RemoveOptions{})
assert.NilError(t, err)
}
// Check zero images
info = d.Info(t)
assert.Equal(t, info.Images, 0)
// Import
lr, err := apiClient.ImageLoad(ctx, bytes.NewReader(buf.Bytes()), image.LoadOptions{Quiet: true})
assert.NilError(t, err)
io.Copy(io.Discard, lr.Body)
lr.Body.Close()
result := container.RunAttach(ctx, t, apiClient, func(c *container.TestContainerConfig) {
c.Name = "Migration-save-load-" + snapshotter
c.Config.Image = "busybox:latest"
c.Config.Cmd = []string{"echo", "hello"}
})
assert.Equal(t, result.ExitCode, 0)
container.Remove(ctx, t, apiClient, result.ContainerID, containertypes.RemoveOptions{})
}