diff options
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/container_internal.go | 22 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 5 | ||||
-rw-r--r-- | libpod/container_log_linux.go | 33 | ||||
-rw-r--r-- | libpod/info.go | 2 | ||||
-rw-r--r-- | libpod/kube.go | 15 | ||||
-rw-r--r-- | libpod/network/cni/cni_types.go | 2 | ||||
-rw-r--r-- | libpod/network/cni/run.go | 6 | ||||
-rw-r--r-- | libpod/networking_slirp4netns.go | 39 | ||||
-rw-r--r-- | libpod/options.go | 2 | ||||
-rw-r--r-- | libpod/runtime.go | 6 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 2 |
11 files changed, 101 insertions, 33 deletions
diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 994ffeec7..b9805faa3 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -457,10 +457,12 @@ func (c *Container) setupStorage(ctx context.Context) error { options.StorageOpt[split2[0]] = split2[1] } } - if c.restoreFromCheckpoint && !c.config.Privileged { - // If restoring from a checkpoint, the root file-system - // needs to be mounted with the same SELinux labels as - // it was mounted previously. + if c.restoreFromCheckpoint && c.config.ProcessLabel != "" && c.config.MountLabel != "" { + // If restoring from a checkpoint, the root file-system needs + // to be mounted with the same SELinux labels as it was mounted + // previously. But only if both labels have been set. For + // privileged containers or '--ipc host' only ProcessLabel will + // be set and so we will skip it for cases like that. if options.Flags == nil { options.Flags = make(map[string]interface{}) } @@ -1511,8 +1513,8 @@ func (c *Container) mountStorage() (_ string, deferredErr error) { mountPoint := c.config.Rootfs // Check if overlay has to be created on top of Rootfs if c.config.RootfsOverlay { - overlayDest := c.runtime.store.GraphRoot() - contentDir, err := overlay.GenerateStructure(c.runtime.store.GraphRoot(), c.ID(), "rootfs", c.RootUID(), c.RootGID()) + overlayDest := c.runtime.RunRoot() + contentDir, err := overlay.GenerateStructure(overlayDest, c.ID(), "rootfs", c.RootUID(), c.RootGID()) if err != nil { return "", errors.Wrapf(err, "rootfs-overlay: failed to create TempDir in the %s directory", overlayDest) } @@ -1737,11 +1739,11 @@ func (c *Container) cleanupStorage() error { // umount rootfs overlay if it was created if c.config.RootfsOverlay { - overlayBasePath := filepath.Dir(c.config.StaticDir) - overlayBasePath = filepath.Join(overlayBasePath, "rootfs") + overlayBasePath := filepath.Dir(c.state.Mountpoint) if err := overlay.Unmount(overlayBasePath); err != nil { - // If the container can't remove content report the error - logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err) + if cleanupErr != nil { + logrus.Errorf("Failed to cleanup overlay mounts for %s: %v", c.ID(), err) + } cleanupErr = err } } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 27cc318b4..d3151f7e0 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -322,7 +322,7 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) { return nil, err } - g := generate.Generator{Config: c.config.Spec} + g := generate.NewFromSpec(c.config.Spec) // If network namespace was requested, add it now if c.config.CreateNetNS { @@ -1219,7 +1219,8 @@ func (c *Container) importCheckpoint(input string) error { } // Make sure the newly created config.json exists on disk - g := generate.Generator{Config: c.config.Spec} + g := generate.NewFromSpec(c.config.Spec) + if err := c.saveSpec(g.Config); err != nil { return errors.Wrap(err, "saving imported container specification for restore failed") } diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go index 562169ce2..4029d0af7 100644 --- a/libpod/container_log_linux.go +++ b/libpod/container_log_linux.go @@ -121,7 +121,24 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption }() tailQueue := []*logs.LogLine{} // needed for options.Tail - doTail := options.Tail > 0 + doTail := options.Tail >= 0 + doTailFunc := func() { + // Flush *once* we hit the end of the journal. + startIndex := int64(len(tailQueue)) + outputLines := int64(0) + for startIndex > 0 && outputLines < options.Tail { + startIndex-- + for startIndex > 0 && tailQueue[startIndex].Partial() { + startIndex-- + } + outputLines++ + } + for i := startIndex; i < int64(len(tailQueue)); i++ { + logChannel <- tailQueue[i] + } + tailQueue = nil + doTail = false + } lastReadCursor := "" for { select { @@ -152,16 +169,7 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption // Hit the end of the journal (so far?). if cursor == lastReadCursor { if doTail { - // Flush *once* we hit the end of the journal. - startIndex := int64(len(tailQueue)-1) - options.Tail - if startIndex < 0 { - startIndex = 0 - } - for i := startIndex; i < int64(len(tailQueue)); i++ { - logChannel <- tailQueue[i] - } - tailQueue = nil - doTail = false + doTailFunc() } // Unless we follow, quit. if !options.Follow { @@ -194,6 +202,9 @@ func (c *Container) readFromJournal(ctx context.Context, options *logs.LogOption return } if status == events.Exited { + if doTail { + doTailFunc() + } return } continue diff --git a/libpod/info.go b/libpod/info.go index a2fd18491..8d0b19f23 100644 --- a/libpod/info.go +++ b/libpod/info.go @@ -332,7 +332,7 @@ func readKernelVersion() (string, error) { return "", err } f := bytes.Fields(buf) - if len(f) < 2 { + if len(f) < 3 { return string(bytes.TrimSpace(buf)), nil } return string(f[2]), nil diff --git a/libpod/kube.go b/libpod/kube.go index 02ac8ed98..ad5acea78 100644 --- a/libpod/kube.go +++ b/libpod/kube.go @@ -11,6 +11,7 @@ import ( "strings" "time" + "github.com/containers/common/pkg/config" "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/libpod/network/types" "github.com/containers/podman/v3/pkg/env" @@ -468,11 +469,23 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, [] kubeContainer.Name = removeUnderscores(c.Name()) _, image := c.Image() + + // The infra container may have been created with an overlay root FS + // instead of an infra image. If so, set the imageto the default K8s + // pause one and make sure it's in the storage by pulling it down if + // missing. + if image == "" && c.IsInfra() { + image = config.DefaultInfraImage + if _, err := c.runtime.libimageRuntime.Pull(ctx, image, config.PullPolicyMissing, nil); err != nil { + return kubeContainer, nil, nil, nil, err + } + } + kubeContainer.Image = image kubeContainer.Stdin = c.Stdin() img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil) if err != nil { - return kubeContainer, kubeVolumes, nil, annotations, err + return kubeContainer, kubeVolumes, nil, annotations, fmt.Errorf("looking up image %q of container %q: %w", image, c.ID(), err) } imgData, err := img.Inspect(ctx, nil) if err != nil { diff --git a/libpod/network/cni/cni_types.go b/libpod/network/cni/cni_types.go index 87beceff3..c70cb92b6 100644 --- a/libpod/network/cni/cni_types.go +++ b/libpod/network/cni/cni_types.go @@ -176,7 +176,7 @@ func newIPAMLocalHostRange(subnet types.IPNet, leaseRange *types.LeaseRange, gw Subnet: subnet.String(), } - // an user provided a range, we add it here + // a user provided a range, we add it here if leaseRange != nil { if leaseRange.StartIP != nil { hostRange.RangeStart = leaseRange.StartIP.String() diff --git a/libpod/network/cni/run.go b/libpod/network/cni/run.go index bd873f89b..99b2adce5 100644 --- a/libpod/network/cni/run.go +++ b/libpod/network/cni/run.go @@ -196,10 +196,8 @@ func getRuntimeConfig(netns, conName, conID, networkName string, ports []cniPort IfName: opts.InterfaceName, Args: [][2]string{ {"IgnoreUnknown", "1"}, - // FIXME: Should we set the K8S args? - //{"K8S_POD_NAMESPACE", conName}, - //{"K8S_POD_INFRA_CONTAINER_ID", conID}, - // K8S_POD_NAME is used by dnsname to get the container name + // Do not set the K8S env vars, see https://github.com/containers/podman/issues/12083. + // Only K8S_POD_NAME is used by dnsname to get the container name. {"K8S_POD_NAME", conName}, }, CapabilityArgs: map[string]interface{}{}, diff --git a/libpod/networking_slirp4netns.go b/libpod/networking_slirp4netns.go index ffd53ec2b..56e8eca99 100644 --- a/libpod/networking_slirp4netns.go +++ b/libpod/networking_slirp4netns.go @@ -16,6 +16,7 @@ import ( "syscall" "time" + "github.com/containernetworking/plugins/pkg/ns" "github.com/containers/podman/v3/pkg/errorhandling" "github.com/containers/podman/v3/pkg/rootless" "github.com/containers/podman/v3/pkg/rootlessport" @@ -58,6 +59,8 @@ type slirp4netnsNetworkOptions struct { outboundAddr6 string } +const ipv6ConfDefaultAcceptDadSysctl = "/proc/sys/net/ipv6/conf/default/accept_dad" + func checkSlirpFlags(path string) (*slirpFeatures, error) { cmd := exec.Command(path, "--help") out, err := cmd.CombinedOutput() @@ -297,6 +300,39 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error { } cmd.Stdout = logFile cmd.Stderr = logFile + + var slirpReadyChan (chan struct{}) + + if netOptions.enableIPv6 { + slirpReadyChan = make(chan struct{}) + defer close(slirpReadyChan) + go func() { + err := ns.WithNetNSPath(netnsPath, func(_ ns.NetNS) error { + // Duplicate Address Detection slows the ipv6 setup down for 1-2 seconds. + // Since slirp4netns is run it is own namespace and not directly routed + // we can skip this to make the ipv6 address immediately available. + // We change the default to make sure the slirp tap interface gets the + // correct value assigned so DAD is disabled for it + // Also make sure to change this value back to the original after slirp4netns + // is ready in case users rely on this sysctl. + orgValue, err := ioutil.ReadFile(ipv6ConfDefaultAcceptDadSysctl) + if err != nil { + return err + } + err = ioutil.WriteFile(ipv6ConfDefaultAcceptDadSysctl, []byte("0"), 0644) + if err != nil { + return err + } + // wait for slirp to finish setup + <-slirpReadyChan + return ioutil.WriteFile(ipv6ConfDefaultAcceptDadSysctl, orgValue, 0644) + }) + if err != nil { + logrus.Warnf("failed to set net.ipv6.conf.default.accept_dad sysctl: %v", err) + } + }() + } + if err := cmd.Start(); err != nil { return errors.Wrapf(err, "failed to start slirp4netns process") } @@ -310,6 +346,9 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error { if err := waitForSync(syncR, cmd, logFile, 1*time.Second); err != nil { return err } + if slirpReadyChan != nil { + slirpReadyChan <- struct{}{} + } // Set a default slirp subnet. Parsing a string with the net helper is easier than building the struct myself _, ctr.slirp4netnsSubnet, _ = net.ParseCIDR(defaultSlirp4netnsSubnet) diff --git a/libpod/options.go b/libpod/options.go index 9762de67e..135b2f363 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -969,7 +969,7 @@ func WithUserNSFrom(nsCtr *Container) CtrCreateOption { if err := JSONDeepCopy(nsCtr.IDMappings(), &ctr.config.IDMappings); err != nil { return err } - g := generate.Generator{Config: ctr.config.Spec} + g := generate.NewFromSpec(ctr.config.Spec) g.ClearLinuxUIDMappings() for _, uidmap := range nsCtr.config.IDMappings.UIDMap { diff --git a/libpod/runtime.go b/libpod/runtime.go index 855f3a9f9..950ac65eb 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -543,7 +543,11 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (retErr error) { return err } if became { - utils.MovePauseProcessToScope(pausePid) + // Check if the pause process was created. If it was created, then + // move it to its own systemd scope. + if _, err = os.Stat(pausePid); err == nil { + utils.MovePauseProcessToScope(pausePid) + } os.Exit(ret) } } diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 2256ba57c..0a7db33f1 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -389,7 +389,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai if ctr.restoreFromCheckpoint { // Remove information about bind mount // for new container from imported checkpoint - g := generate.Generator{Config: ctr.config.Spec} + g := generate.NewFromSpec(ctr.config.Spec) g.RemoveMount("/dev/shm") ctr.config.ShmDir = "" g.RemoveMount("/etc/resolv.conf") |