mirror of
https://github.com/containers/podman.git
synced 2025-05-24 02:27:00 +08:00
Merge pull request #10894 from cdoern/pidPod
podman pod create --pid flag
This commit is contained in:
@ -293,6 +293,7 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions
|
|||||||
Hostname: s.ContainerBasicConfig.Hostname,
|
Hostname: s.ContainerBasicConfig.Hostname,
|
||||||
Cpus: cliVals.CPUS,
|
Cpus: cliVals.CPUS,
|
||||||
CpusetCpus: cliVals.CPUSetCPUs,
|
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.
|
// Unset config values we passed to the pod to prevent them being used twice for the container and pod.
|
||||||
s.ContainerBasicConfig.Hostname = ""
|
s.ContainerBasicConfig.Hostname = ""
|
||||||
|
@ -102,6 +102,10 @@ func init() {
|
|||||||
flags.StringVarP(&createOptions.Hostname, hostnameFlagName, "", "", "Set a hostname to the pod")
|
flags.StringVarP(&createOptions.Hostname, hostnameFlagName, "", "", "Set a hostname to the pod")
|
||||||
_ = createCommand.RegisterFlagCompletionFunc(hostnameFlagName, completion.AutocompleteNone)
|
_ = 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"
|
podIDFileFlagName := "pod-id-file"
|
||||||
flags.StringVar(&podIDFile, podIDFileFlagName, "", "Write the pod ID to the file")
|
flags.StringVar(&podIDFile, podIDFileFlagName, "", "Write the pod ID to the file")
|
||||||
_ = createCommand.RegisterFlagCompletionFunc(podIDFileFlagName, completion.AutocompleteDefault)
|
_ = createCommand.RegisterFlagCompletionFunc(podIDFileFlagName, completion.AutocompleteDefault)
|
||||||
@ -179,6 +183,8 @@ func create(cmd *cobra.Command, args []string) error {
|
|||||||
defer errorhandling.SyncQuiet(podIDFD)
|
defer errorhandling.SyncQuiet(podIDFD)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createOptions.Pid = cmd.Flag("pid").Value.String()
|
||||||
|
|
||||||
createOptions.Net, err = common.NetFlagsToNetOptions(cmd, createOptions.Infra)
|
createOptions.Net, err = common.NetFlagsToNetOptions(cmd, createOptions.Infra)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -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.
|
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*
|
#### **--pod-id-file**=*path*
|
||||||
|
|
||||||
Write the pod ID to the file.
|
Write the pod ID to the file.
|
||||||
|
@ -103,6 +103,8 @@ type InspectPodInfraConfig struct {
|
|||||||
CPUQuota int64 `json:"cpu_quota,omitempty"`
|
CPUQuota int64 `json:"cpu_quota,omitempty"`
|
||||||
// CPUSetCPUs contains linux specific CPU data for the container
|
// CPUSetCPUs contains linux specific CPU data for the container
|
||||||
CPUSetCPUs string `json:"cpuset_cpus,omitempty"`
|
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.
|
// InspectPodContainerInfo contains information on a container in a pod.
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/containers/podman/v3/libpod/events"
|
"github.com/containers/podman/v3/libpod/events"
|
||||||
"github.com/containers/podman/v3/pkg/namespaces"
|
"github.com/containers/podman/v3/pkg/namespaces"
|
||||||
"github.com/containers/podman/v3/pkg/rootless"
|
"github.com/containers/podman/v3/pkg/rootless"
|
||||||
|
"github.com/containers/podman/v3/pkg/specgen"
|
||||||
"github.com/containers/podman/v3/pkg/util"
|
"github.com/containers/podman/v3/pkg/util"
|
||||||
"github.com/containers/storage"
|
"github.com/containers/storage"
|
||||||
"github.com/containers/storage/pkg/idtools"
|
"github.com/containers/storage/pkg/idtools"
|
||||||
@ -2397,3 +2398,22 @@ func WithPodCPUSetCPUs(inp string) PodCreateOption {
|
|||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/containers/podman/v3/libpod/define"
|
"github.com/containers/podman/v3/libpod/define"
|
||||||
"github.com/containers/podman/v3/libpod/lock"
|
"github.com/containers/podman/v3/libpod/lock"
|
||||||
|
"github.com/containers/podman/v3/pkg/specgen"
|
||||||
"github.com/cri-o/ocicni/pkg/ocicni"
|
"github.com/cri-o/ocicni/pkg/ocicni"
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -97,6 +98,7 @@ type InfraContainerConfig struct {
|
|||||||
HasInfraContainer bool `json:"makeInfraContainer"`
|
HasInfraContainer bool `json:"makeInfraContainer"`
|
||||||
NoNetwork bool `json:"noNetwork,omitempty"`
|
NoNetwork bool `json:"noNetwork,omitempty"`
|
||||||
HostNetwork bool `json:"infraHostNetwork,omitempty"`
|
HostNetwork bool `json:"infraHostNetwork,omitempty"`
|
||||||
|
PidNS specgen.Namespace `json:"infraPid,omitempty"`
|
||||||
PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
|
PortBindings []ocicni.PortMapping `json:"infraPortBindings"`
|
||||||
StaticIP net.IP `json:"staticIP,omitempty"`
|
StaticIP net.IP `json:"staticIP,omitempty"`
|
||||||
StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"`
|
StaticMAC net.HardwareAddr `json:"staticMAC,omitempty"`
|
||||||
@ -170,6 +172,11 @@ func (p *Pod) CPUQuota() int64 {
|
|||||||
return 0
|
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
|
// Labels returns the pod's labels
|
||||||
func (p *Pod) Labels() map[string]string {
|
func (p *Pod) Labels() map[string]string {
|
||||||
labels := make(map[string]string)
|
labels := make(map[string]string)
|
||||||
|
@ -541,6 +541,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {
|
|||||||
infraConfig.CPUPeriod = p.CPUPeriod()
|
infraConfig.CPUPeriod = p.CPUPeriod()
|
||||||
infraConfig.CPUQuota = p.CPUQuota()
|
infraConfig.CPUQuota = p.CPUQuota()
|
||||||
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
|
infraConfig.CPUSetCPUs = p.ResourceLim().CPU.Cpus
|
||||||
|
infraConfig.PidNS = p.PidMode()
|
||||||
|
|
||||||
if len(p.config.InfraContainer.DNSServer) > 0 {
|
if len(p.config.InfraContainer.DNSServer) > 0 {
|
||||||
infraConfig.DNSServer = make([]string, 0, len(p.config.InfraContainer.DNSServer))
|
infraConfig.DNSServer = make([]string, 0, len(p.config.InfraContainer.DNSServer))
|
||||||
|
@ -145,6 +145,18 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm
|
|||||||
if len(p.config.InfraContainer.ExitCommand) > 0 {
|
if len(p.config.InfraContainer.ExitCommand) > 0 {
|
||||||
options = append(options, WithExitCommand(p.config.InfraContainer.ExitCommand))
|
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.SetRootReadonly(true)
|
||||||
g.SetProcessArgs(infraCtrCommand)
|
g.SetProcessArgs(infraCtrCommand)
|
||||||
|
@ -116,6 +116,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po
|
|||||||
if pod.config.UsePodCgroup {
|
if pod.config.UsePodCgroup {
|
||||||
logrus.Debugf("Got pod cgroup as %s", pod.state.CgroupPath)
|
logrus.Debugf("Got pod cgroup as %s", pod.state.CgroupPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !pod.HasInfraContainer() && pod.SharesNamespaces() {
|
if !pod.HasInfraContainer() && pod.SharesNamespaces() {
|
||||||
return nil, errors.Errorf("Pods must have an infra container to share namespaces")
|
return nil, errors.Errorf("Pods must have an infra container to share namespaces")
|
||||||
}
|
}
|
||||||
|
@ -118,6 +118,7 @@ type PodCreateOptions struct {
|
|||||||
Name string
|
Name string
|
||||||
Net *NetOptions
|
Net *NetOptions
|
||||||
Share []string
|
Share []string
|
||||||
|
Pid string
|
||||||
Cpus float64
|
Cpus float64
|
||||||
CpusetCpus string
|
CpusetCpus string
|
||||||
}
|
}
|
||||||
@ -146,6 +147,18 @@ func (p *PodCreateOptions) CPULimits() *specs.LinuxCPU {
|
|||||||
return cpu
|
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 {
|
func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
|
||||||
// Basic Config
|
// Basic Config
|
||||||
s.Name = p.Name
|
s.Name = p.Name
|
||||||
@ -178,6 +191,14 @@ func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error {
|
|||||||
s.NoManageHosts = p.Net.NoHosts
|
s.NoManageHosts = p.Net.NoHosts
|
||||||
s.HostAdd = p.Net.AddHosts
|
s.HostAdd = p.Net.AddHosts
|
||||||
|
|
||||||
|
namespaces, err := setNamespaces(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !namespaces[0].IsDefault() {
|
||||||
|
s.Pid = namespaces[0]
|
||||||
|
}
|
||||||
|
|
||||||
// Cgroup
|
// Cgroup
|
||||||
s.CgroupParent = p.CGroupParent
|
s.CgroupParent = p.CGroupParent
|
||||||
|
|
||||||
|
@ -102,6 +102,10 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod
|
|||||||
options = append(options, libpod.WithInfraCommand(p.InfraCommand))
|
options = append(options, libpod.WithInfraCommand(p.InfraCommand))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !p.Pid.IsDefault() {
|
||||||
|
options = append(options, libpod.WithPodPidNS(p.Pid))
|
||||||
|
}
|
||||||
|
|
||||||
switch p.NetNS.NSMode {
|
switch p.NetNS.NSMode {
|
||||||
case specgen.Default, "":
|
case specgen.Default, "":
|
||||||
if p.NoInfra {
|
if p.NoInfra {
|
||||||
|
@ -57,6 +57,10 @@ type PodBasicConfig struct {
|
|||||||
// (e.g. `podman generate systemd --new`).
|
// (e.g. `podman generate systemd --new`).
|
||||||
// Optional.
|
// Optional.
|
||||||
PodCreateCommand []string `json:"pod_create_command,omitempty"`
|
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.
|
// PodNetworkConfig contains networking configuration for a pod.
|
||||||
|
@ -560,4 +560,65 @@ ENTRYPOINT ["sleep","99999"]
|
|||||||
podJSON := podInspect.InspectPodToJSON()
|
podJSON := podInspect.InspectPodToJSON()
|
||||||
Expect(podJSON.CPUSetCPUs).To(Equal(in))
|
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())
|
||||||
|
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user