Merge pull request #10567 from adrianreber/2021-06-04-compress

Add support for selectable checkpoint archive compression algorithm
This commit is contained in:
OpenShift Merge Robot
2021-06-07 11:09:43 +02:00
committed by GitHub
8 changed files with 173 additions and 22 deletions

View File

@ -1211,3 +1211,10 @@ func AutocompleteVolumeFilters(cmd *cobra.Command, args []string, toComplete str
}
return completeKeyValues(toComplete, kv)
}
// AutocompleteCheckpointCompressType - Autocomplete checkpoint compress type options.
// -> "gzip", "none", "zstd"
func AutocompleteCheckpointCompressType(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
types := []string{"gzip", "none", "zstd"}
return types, cobra.ShellCompDirectiveNoFileComp
}

View File

@ -3,6 +3,7 @@ package containers
import (
"context"
"fmt"
"strings"
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v3/cmd/podman/common"
@ -11,6 +12,7 @@ import (
"github.com/containers/podman/v3/cmd/podman/validate"
"github.com/containers/podman/v3/pkg/domain/entities"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@ -36,9 +38,7 @@ var (
}
)
var (
checkpointOptions entities.CheckpointOptions
)
var checkpointOptions entities.CheckpointOptions
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
@ -60,11 +60,32 @@ func init() {
flags.BoolVarP(&checkpointOptions.PreCheckPoint, "pre-checkpoint", "P", false, "Dump container's memory information only, leave the container running")
flags.BoolVar(&checkpointOptions.WithPrevious, "with-previous", false, "Checkpoint container with pre-checkpoint images")
flags.StringP("compress", "c", "zstd", "Select compression algorithm (gzip, none, zstd) for checkpoint archive.")
_ = checkpointCommand.RegisterFlagCompletionFunc("compress", common.AutocompleteCheckpointCompressType)
validate.AddLatestFlag(checkpointCommand, &checkpointOptions.Latest)
}
func checkpoint(cmd *cobra.Command, args []string) error {
var errs utils.OutputErrors
if cmd.Flags().Changed("compress") {
if checkpointOptions.Export == "" {
return errors.Errorf("--compress can only be used with --export")
}
compress, _ := cmd.Flags().GetString("compress")
switch strings.ToLower(compress) {
case "none":
checkpointOptions.Compression = archive.Uncompressed
case "gzip":
checkpointOptions.Compression = archive.Gzip
case "zstd":
checkpointOptions.Compression = archive.Zstd
default:
return errors.Errorf("Selected compression algorithm (%q) not supported. Please select one from: gzip, none, zstd", compress)
}
} else {
checkpointOptions.Compression = archive.Zstd
}
if rootless.IsRootless() {
return errors.New("checkpointing a container requires root")
}

View File

@ -10,31 +10,25 @@ podman\-container\-checkpoint - Checkpoints one or more running containers
Checkpoints all the processes in one or more containers. You may use container IDs or names as input.
## OPTIONS
#### **--keep**, **-k**
Keep all temporary log and statistics files created by CRIU during checkpointing. These files
are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these
files are theoretically not needed, but if these files are needed Podman can keep the files
for further analysis.
#### **--all**, **-a**
Checkpoint all running containers.
#### **--latest**, **-l**
#### **--compress**, **-c**
Instead of providing the container name or ID, checkpoint the last created container. (This option is not available with the remote Podman client)
Specify the compression algorithm used for the checkpoint archive created
with the **--export, -e** option. Possible algorithms are *gzip*, *none*
and *zstd*. If no compression algorithm is specified Podman will use
*zstd*.
#### **--leave-running**, **-R**
One possible reason to use *none* is to enable faster creation of checkpoint
archives. Not compressing the checkpoint archive can result in faster checkpoint
archive creation.
Leave the container running after checkpointing instead of stopping it.
#### **--tcp-established**
Checkpoint a container with established TCP connections. If the checkpoint
image contains established TCP connections, this options is required during
restore. Defaults to not checkpointing containers with established TCP
connections.
```
# podman container checkpoint -l --compress=none --export=dump.tar
# podman container checkpoint -l --compress=gzip --export=dump.tar.gz
```
#### **--export**, **-e**
@ -56,11 +50,33 @@ This option must be used in combination with the **--export, -e** option.
When this option is specified, the content of volumes associated with
the container will not be included into the checkpoint tar.gz file.
#### **--keep**, **-k**
Keep all temporary log and statistics files created by CRIU during checkpointing. These files
are not deleted if checkpointing fails for further debugging. If checkpointing succeeds these
files are theoretically not needed, but if these files are needed Podman can keep the files
for further analysis.
#### **--latest**, **-l**
Instead of providing the container name or ID, checkpoint the last created container. (This option is not available with the remote Podman client)
#### **--leave-running**, **-R**
Leave the container running after checkpointing instead of stopping it.
#### **--pre-checkpoint**, **-P**
Dump the container's memory information only, leaving the container running. Later
operations will supersede prior dumps. It only works on runc 1.0-rc3 or higher.
#### **--tcp-established**
Checkpoint a container with established TCP connections. If the checkpoint
image contains established TCP connections, this options is required during
restore. Defaults to not checkpointing containers with established TCP
connections.
#### **--with-previous**
Check out the container with previous criu image files in pre-dump. It only works

View File

@ -12,6 +12,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/signal"
"github.com/containers/storage/pkg/archive"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@ -776,6 +777,9 @@ type ContainerCheckpointOptions struct {
// ImportPrevious tells the API to restore container with two
// images. One is TargetFile, the other is ImportPrevious.
ImportPrevious string
// Compression tells the API which compression to use for
// the exported checkpoint archive.
Compression archive.Compression
}
// Checkpoint checkpoints a container

View File

@ -985,7 +985,7 @@ func (c *Container) exportCheckpoint(options ContainerCheckpointOptions) error {
}
input, err := archive.TarWithOptions(c.bundlePath(), &archive.TarOptions{
Compression: archive.Gzip,
Compression: options.Compression,
IncludeSourceDir: true,
IncludeFiles: includeFiles,
})

View File

@ -9,6 +9,7 @@ import (
"github.com/containers/image/v5/types"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/storage/pkg/archive"
"github.com/cri-o/ocicni/pkg/ocicni"
)
@ -178,6 +179,7 @@ type CheckpointOptions struct {
TCPEstablished bool
PreCheckPoint bool
WithPrevious bool
Compression archive.Compression
}
type CheckpointReport struct {

View File

@ -483,6 +483,7 @@ func (ic *ContainerEngine) ContainerCheckpoint(ctx context.Context, namesOrIds [
KeepRunning: options.LeaveRunning,
PreCheckPoint: options.PreCheckPoint,
WithPrevious: options.WithPrevious,
Compression: options.Compression,
}
if options.All {

View File

@ -425,6 +425,106 @@ var _ = Describe("Podman checkpoint", func() {
// Remove exported checkpoint
os.Remove(fileName)
})
// This test does the same steps which are necessary for migrating
// a container from one host to another
It("podman checkpoint container with export and different compression algorithms", func() {
localRunString := getRunString([]string{"--rm", ALPINE, "top"})
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
cid := session.OutputToString()
fileName := "/tmp/checkpoint-" + cid + ".tar"
// Checkpoint with the default algorithm
result := podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
// Restore container
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the zstd algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "--compress", "zstd"})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
// Restore container
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the none algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "none"})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
// Restore container
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the gzip algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "gzip"})
result.WaitWithDefaultTimeout()
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
// Restore container
result = podmanTest.Podman([]string{"container", "restore", "-i", fileName})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
// Checkpoint with the non-existing algorithm
result = podmanTest.Podman([]string{"container", "checkpoint", "-l", "-e", fileName, "-c", "non-existing"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(125))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
result = podmanTest.Podman([]string{"rm", "-fa"})
result.WaitWithDefaultTimeout()
Expect(result.ExitCode()).To(Equal(0))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
// Remove exported checkpoint
os.Remove(fileName)
})
It("podman checkpoint and restore container with root file-system changes", func() {
// Start the container