Skip to content

Commit 2ccefa6

Browse files
committed
restore: tell CRIU to use existing namespaces
runc already tells CRIU to restore into an existing network or PID namespace if there is a path to a namespace specified in config.json. PID and network have special handling in CRIU using CRIU's inherit_fd interface. For UTS, IPC and MOUNT namespaces CRIU can join those existing namespaces using CRIU's join_ns interface. This is especially interesting for environments where containers are running in a pod which already has running containers (pause for example) with namespaces configured and the restored container needs to join these namespaces. CRIU has no support to join an existing CGROUP namespace (yet?) why restoring a container with a path specified to a CGROUP namespace will be aborted by runc. CRIU would have support to restore a container into an existing time namespace, but runc does not yet seem to support time namespaces. Signed-off-by: Adrian Reber <[email protected]>
1 parent d636ad6 commit 2ccefa6

File tree

1 file changed

+39
-9
lines changed

1 file changed

+39
-9
lines changed

libcontainer/container_linux.go

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,44 @@ func (c *linuxContainer) handleCheckpointingExternalNamespaces(rpcOpts *criurpc.
879879
return nil
880880
}
881881

882+
func (c *linuxContainer) handleRestoringNamespaces(rpcOpts *criurpc.CriuOpts, extraFiles *[]*os.File) error {
883+
for _, ns := range c.config.Namespaces {
884+
switch ns.Type {
885+
case configs.NEWNET, configs.NEWPID:
886+
// If the container is running in a network or PID namespace and has
887+
// a path to the network or PID namespace configured, we will dump
888+
// that network or PID namespace as an external namespace and we
889+
// will expect that the namespace exists during restore.
890+
// This basically means that CRIU will ignore the namespace
891+
// and expect it to be setup correctly.
892+
if err := c.handleRestoringExternalNamespaces(rpcOpts, extraFiles, ns.Type); err != nil {
893+
return err
894+
}
895+
default:
896+
// For all other namespaces except NET and PID CRIU has
897+
// a simpler way of joining the existing namespace if set
898+
nsPath := c.config.Namespaces.PathOf(ns.Type)
899+
if nsPath == "" {
900+
continue
901+
}
902+
if ns.Type == configs.NEWCGROUP {
903+
// CRIU has no code to handle NEWCGROUP
904+
return fmt.Errorf("Do not know how to handle namespace %v", ns.Type)
905+
}
906+
// CRIU has code to handle NEWTIME, but it does not seem to be defined in runc
907+
908+
// CRIU will issue a warning for NEWUSER:
909+
// criu/namespaces.c: 'join-ns with user-namespace is not fully tested and dangerous'
910+
rpcOpts.JoinNs = append(rpcOpts.JoinNs, &criurpc.JoinNamespace{
911+
Ns: proto.String(configs.NsName(ns.Type)),
912+
NsFile: proto.String(nsPath),
913+
})
914+
}
915+
}
916+
917+
return nil
918+
}
919+
882920
func (c *linuxContainer) handleRestoringExternalNamespaces(rpcOpts *criurpc.CriuOpts, extraFiles *[]*os.File, t configs.NamespaceType) error {
883921
if !c.criuSupportsExtNS(t) {
884922
return nil
@@ -1310,15 +1348,7 @@ func (c *linuxContainer) Restore(process *Process, criuOpts *CriuOpts) error {
13101348

13111349
c.handleCriuConfigurationFile(req.Opts)
13121350

1313-
// Same as during checkpointing. If the container has a specific network namespace
1314-
// assigned to it, this now expects that the checkpoint will be restored in a
1315-
// already created network namespace.
1316-
if err := c.handleRestoringExternalNamespaces(req.Opts, &extraFiles, configs.NEWNET); err != nil {
1317-
return err
1318-
}
1319-
1320-
// Same for PID namespaces.
1321-
if err := c.handleRestoringExternalNamespaces(req.Opts, &extraFiles, configs.NEWPID); err != nil {
1351+
if err := c.handleRestoringNamespaces(req.Opts, &extraFiles); err != nil {
13221352
return err
13231353
}
13241354

0 commit comments

Comments
 (0)