summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcdoern <cdoern@redhat.com>2021-07-07 17:00:30 -0400
committercdoern <cdoern@redhat.com>2021-07-15 10:34:09 -0400
commitf7321681d04d65da3b307d1e5e4ba12c42b5c456 (patch)
tree8479b72f55d61a400a1eef4c3540fdb32d4e64d5
parent1a9cb93f16cf19e14581319e2fd1b60e791f74dd (diff)
downloadpodman-f7321681d04d65da3b307d1e5e4ba12c42b5c456.tar.gz
podman-f7321681d04d65da3b307d1e5e4ba12c42b5c456.tar.bz2
podman-f7321681d04d65da3b307d1e5e4ba12c42b5c456.zip
podman pod create --pid flag
added support for --pid flag. User can specify ns:file, pod, private, or host. container returns an error since you cannot point the ns of the pods infra container to a container outside of the pod. Signed-off-by: cdoern <cdoern@redhat.com>
-rw-r--r--cmd/podman/containers/create.go1
-rw-r--r--cmd/podman/pods/create.go6
-rw-r--r--docs/source/markdown/podman-pod-create.1.md8
-rw-r--r--libpod/define/pod_inspect.go2
-rw-r--r--libpod/options.go20
-rw-r--r--libpod/pod.go7
-rw-r--r--libpod/pod_api.go1
-rw-r--r--libpod/runtime_pod_infra_linux.go12
-rw-r--r--libpod/runtime_pod_linux.go1
-rw-r--r--pkg/domain/entities/pods.go21
-rw-r--r--pkg/specgen/generate/pod_create.go4
-rw-r--r--pkg/specgen/podspecgen.go4
-rw-r--r--test/e2e/pod_create_test.go61
13 files changed, 148 insertions, 0 deletions
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index 1e11c53d5..df0fa6f9d 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -293,6 +293,7 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions
Hostname: s.ContainerBasicConfig.Hostname,
Cpus: cliVals.CPUS,
CpusetCpus: cliVals.CPUSetCPUs,
+ Pid: cliVals.PID,
}
// Unset config values we passed to the pod to prevent them being used twice for the container and pod.
s.ContainerBasicConfig.Hostname = ""
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 03e3ffaa0..0d299bb9c 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -102,6 +102,10 @@ func init() {
flags.StringVarP(&createOptions.Hostname, hostnameFlagName, "", "", "Set a hostname to the pod")
_ = createCommand.RegisterFlagCompletionFunc(hostnameFlagName, completion.AutocompleteNone)
+ pidFlagName := "pid"
+ flags.StringVar(&createOptions.Pid, pidFlagName, "", "PID namespace to use")
+ _ = createCommand.RegisterFlagCompletionFunc(pidFlagName, common.AutocompleteNamespace)
+
podIDFileFlagName := "pod-id-file"
flags.StringVar(&podIDFile, podIDFileFlagName, "", "Write the pod ID to the file")
_ = createCommand.RegisterFlagCompletionFunc(podIDFileFlagName, completion.AutocompleteDefault)
@@ -179,6 +183,8 @@ func create(cmd *cobra.Command, args []string) error {
defer errorhandling.SyncQuiet(podIDFD)
}
+ createOptions.Pid = cmd.Flag("pid").Value.String()
+
createOptions.Net, err = common.NetFlagsToNetOptions(cmd, createOptions.Infra)
if err != nil {
return err
diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md
index 653b0f6f1..fecdd8494 100644
--- a/docs/source/markdown/podman-pod-create.1.md
+++ b/docs/source/markdown/podman-pod-create.1.md
@@ -120,6 +120,14 @@ Add a DNS alias for the container. When the container is joined to a CNI network
Disable creation of /etc/hosts for the pod.
+#### **--pid**=*pid*
+
+Set the PID mode for the pod. The default is to create a private PID namespace for the pod. Requires the PID namespace to be shared via --share.
+
+ host: use the host’s PID namespace for the pod
+ ns: join the specified PID namespace
+ private: create a new namespace for the pod (default)
+
#### **--pod-id-file**=*path*
Write the pod ID to the file.
diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go
index 67f075b3c..a17304875 100644
--- a/libpod/define/pod_inspect.go
+++ b/libpod/define/pod_inspect.go
@@ -103,6 +103,8 @@ type InspectPodInfraConfig struct {
CPUQuota int64 `json:"cpu_quota,omitempty"`
// CPUSetCPUs contains linux specific CPU data for the container
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
+ // Pid is the PID namespace mode of the pod's infra container
+ PidNS string `json:"pid_ns,omitempty"`
}
// InspectPodContainerInfo contains information on a container in a pod.
diff --git a/libpod/options.go b/libpod/options.go
index b12153512..bc563d60c 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -16,6 +16,7 @@ import (
"github.com/containers/podman/v3/libpod/events"
"github.com/containers/podman/v3/pkg/namespaces"
"github.com/containers/podman/v3/pkg/rootless"
+ "github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/util"
"github.com/containers/storage"
"github.com/containers/storage/pkg/idtools"
@@ -2397,3 +2398,22 @@ func WithPodCPUSetCPUs(inp string) PodCreateOption {
return nil
}
}
+
+func WithPodPidNS(inp specgen.Namespace) PodCreateOption {
+ return func(p *Pod) error {
+ if p.valid {
+ return define.ErrPodFinalized
+ }
+ if p.config.UsePodPID {
+ switch inp.NSMode {
+ case "container":
+ return errors.Wrap(define.ErrInvalidArg, "Cannot take container in a different NS as an argument")
+ case "host":
+ p.config.UsePodPID = false
+ }
+ p.config.InfraContainer.PidNS = inp
+ }
+
+ return nil
+ }
+}
diff --git a/libpod/pod.go b/libpod/pod.go
index d7a9b15d9..c03059c82 100644
--- a/libpod/pod.go
+++ b/libpod/pod.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/lock"
+ "github.com/containers/podman/v3/pkg/specgen"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
@@ -97,6 +98,7 @@ type InfraContainerConfig struct {
HasInfraContainer bool `json:"makeInfraContainer"`
NoNetwork bool `json:"noNetwork,omitempty"`
HostNetwork bool `json:"infraHostNetwork,omitempty"`
+ PidNS specgen.Namespace `json:"infraPid,omitempty"`
PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
StaticIP net.IP `json:"staticIP,omitempty"`
StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"`
@@ -170,6 +172,11 @@ func (p *Pod) CPUQuota() int64 {
return 0
}
+// PidMode returns the PID mode given by the user ex: pod, private...
+func (p *Pod) PidMode() string {
+ return string(p.config.InfraContainer.PidNS.NSMode)
+}
+
// Labels returns the pod's labels
func (p *Pod) Labels() map[string]string {
labels := make(map[string]string)
diff --git a/libpod/pod_api.go b/libpod/pod_api.go
index d8f5d15f8..1ab012a8b 100644
--- a/libpod/pod_api.go
+++ b/libpod/pod_api.go
@@ -541,6 +541,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
infraConfig.CPUPeriod = p.CPUPeriod()
infraConfig.CPUQuota = p.CPUQuota()
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
+ infraConfig.PidNS = p.PidMode()
if len(p.config.InfraContainer.DNSServer) > 0 {
infraConfig.DNSServer = make([]string, 0, len(p.config.InfraContainer.DNSServer))
diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go
index 6b002f65a..8342352ec 100644
--- a/libpod/runtime_pod_infra_linux.go
+++ b/libpod/runtime_pod_infra_linux.go
@@ -145,6 +145,18 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
if len(p.config.InfraContainer.ExitCommand) > 0 {
options = append(options, WithExitCommand(p.config.InfraContainer.ExitCommand))
}
+
+ if p.config.UsePodPID && p.config.InfraContainer.PidNS.NSMode != "host" {
+ g.AddOrReplaceLinuxNamespace(string(spec.LinuxNamespaceType("pid")), p.config.InfraContainer.PidNS.Value)
+ } else if p.config.InfraContainer.PidNS.NSMode == "host" {
+ newNS := []spec.LinuxNamespace{}
+ for _, entry := range g.Config.Linux.Namespaces {
+ if entry.Type != spec.LinuxNamespaceType("pid") {
+ newNS = append(newNS, entry)
+ }
+ }
+ g.Config.Linux.Namespaces = newNS
+ }
}
g.SetRootReadonly(true)
g.SetProcessArgs(infraCtrCommand)
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 4ede23cac..fce3f38a7 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -116,6 +116,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
if pod.config.UsePodCgroup {
logrus.Debugf("Got pod cgroup as %s", pod.state.CgroupPath)
}
+
if !pod.HasInfraContainer() && pod.SharesNamespaces() {
return nil, errors.Errorf("Pods must have an infra container to share namespaces")
}
diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go
index 35f940bca..a0a2a1790 100644
--- a/pkg/domain/entities/pods.go
+++ b/pkg/domain/entities/pods.go
@@ -118,6 +118,7 @@ type PodCreateOptions struct {
Name string
Net *NetOptions
Share []string
+ Pid string
Cpus float64
CpusetCpus string
}
@@ -146,6 +147,18 @@ func (p *PodCreateOptions) CPULimits() *specs.LinuxCPU {
return cpu
}
+func setNamespaces(p *PodCreateOptions) ([4]specgen.Namespace, error) {
+ allNS := [4]specgen.Namespace{}
+ if p.Pid != "" {
+ pid, err := specgen.ParseNamespace(p.Pid)
+ if err != nil {
+ return [4]specgen.Namespace{}, err
+ }
+ allNS[0] = pid
+ }
+ return allNS, nil
+}
+
func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
// Basic Config
s.Name = p.Name
@@ -178,6 +191,14 @@ func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
s.NoManageHosts = p.Net.NoHosts
s.HostAdd = p.Net.AddHosts
+ namespaces, err := setNamespaces(p)
+ if err != nil {
+ return err
+ }
+ if !namespaces[0].IsDefault() {
+ s.Pid = namespaces[0]
+ }
+
// Cgroup
s.CgroupParent = p.CGroupParent
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index 023ebb41e..4ffd8a37f 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -102,6 +102,10 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
options = append(options, libpod.WithInfraCommand(p.InfraCommand))
}
+ if !p.Pid.IsDefault() {
+ options = append(options, libpod.WithPodPidNS(p.Pid))
+ }
+
switch p.NetNS.NSMode {
case specgen.Default, "":
if p.NoInfra {
diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go
index 000a787ea..319345c71 100644
--- a/pkg/specgen/podspecgen.go
+++ b/pkg/specgen/podspecgen.go
@@ -57,6 +57,10 @@ type PodBasicConfig struct {
// (e.g. `podman generate systemd --new`).
// Optional.
PodCreateCommand []string `json:"pod_create_command,omitempty"`
+ // Pid sets the process id namespace of the pod
+ // Optional (defaults to private if unset). This sets the PID namespace of the infra container
+ // This configuration will then be shared with the entire pod if PID namespace sharing is enabled via --share
+ Pid Namespace `json:"pid,omitempty:"`
}
// PodNetworkConfig contains networking configuration for a pod.
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index e437c98e6..3d0a87201 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -559,4 +559,65 @@ ENTRYPOINT ["sleep","99999"]
podJSON := podInspect.InspectPodToJSON()
Expect(podJSON.CPUSetCPUs).To(Equal(in))
})
+
+ It("podman pod create --pid", func() {
+ podName := "pidPod"
+ ns := "ns:/proc/self/ns/"
+ podCreate := podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podInspect := podmanTest.Podman([]string{"pod", "inspect", podName})
+ podInspect.WaitWithDefaultTimeout()
+ Expect(podInspect.ExitCode()).To(Equal(0))
+ podJSON := podInspect.InspectPodToJSON()
+ Expect(podJSON.InfraConfig.PidNS).To(Equal("path"))
+
+ podName = "pidPod2"
+ ns = "pod"
+
+ podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podInspect = podmanTest.Podman([]string{"pod", "inspect", podName})
+ podInspect.WaitWithDefaultTimeout()
+ Expect(podInspect.ExitCode()).To(Equal(0))
+ podJSON = podInspect.InspectPodToJSON()
+ Expect(podJSON.InfraConfig.PidNS).To(Equal("pod"))
+
+ podName = "pidPod3"
+ ns = "host"
+
+ podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podInspect = podmanTest.Podman([]string{"pod", "inspect", podName})
+ podInspect.WaitWithDefaultTimeout()
+ Expect(podInspect.ExitCode()).To(Equal(0))
+ podJSON = podInspect.InspectPodToJSON()
+ Expect(podJSON.InfraConfig.PidNS).To(Equal("host"))
+
+ podName = "pidPod4"
+ ns = "private"
+
+ podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate.ExitCode()).To(Equal(0))
+
+ podInspect = podmanTest.Podman([]string{"pod", "inspect", podName})
+ podInspect.WaitWithDefaultTimeout()
+ Expect(podInspect.ExitCode()).To(Equal(0))
+ podJSON = podInspect.InspectPodToJSON()
+ Expect(podJSON.InfraConfig.PidNS).To(Equal("private"))
+
+ podName = "pidPod5"
+ ns = "container:randomfakeid"
+
+ podCreate = podmanTest.Podman([]string{"pod", "create", "--pid", ns, "--name", podName, "--share", "pid"})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate).Should(ExitWithError())
+
+ })
})