Merge pull request #17207 from danishprakash/add-systemd-shm-size

add support for limiting tmpfs size for systemd-specific mnts
This commit is contained in:
OpenShift Merge Robot
2023-02-15 05:53:40 -05:00
committed by GitHub
18 changed files with 118 additions and 3 deletions

View File

@ -638,6 +638,13 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
) )
_ = cmd.RegisterFlagCompletionFunc(shmSizeFlagName, completion.AutocompleteNone) _ = cmd.RegisterFlagCompletionFunc(shmSizeFlagName, completion.AutocompleteNone)
shmSizeSystemdFlagName := "shm-size-systemd"
createFlags.String(
shmSizeSystemdFlagName, "",
"Size of systemd specific tmpfs mounts (/run, /run/lock) "+sizeWithUnitFormat,
)
_ = cmd.RegisterFlagCompletionFunc(shmSizeSystemdFlagName, completion.AutocompleteNone)
sysctlFlagName := "sysctl" sysctlFlagName := "sysctl"
createFlags.StringSliceVar( createFlags.StringSliceVar(
&cf.Sysctl, &cf.Sysctl,

View File

@ -295,6 +295,9 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
if c.Flag("shm-size").Changed { if c.Flag("shm-size").Changed {
vals.ShmSize = c.Flag("shm-size").Value.String() vals.ShmSize = c.Flag("shm-size").Value.String()
} }
if c.Flag("shm-size-systemd").Changed {
vals.ShmSizeSystemd = c.Flag("shm-size-systemd").Value.String()
}
if (c.Flag("dns").Changed || c.Flag("dns-option").Changed || c.Flag("dns-search").Changed) && vals.Net != nil && (vals.Net.Network.NSMode == specgen.NoNetwork || vals.Net.Network.IsContainer()) { if (c.Flag("dns").Changed || c.Flag("dns-option").Changed || c.Flag("dns-search").Changed) && vals.Net != nil && (vals.Net.Network.NSMode == specgen.NoNetwork || vals.Net.Network.IsContainer()) {
return vals, fmt.Errorf("conflicting options: dns and the network mode: " + string(vals.Net.Network.NSMode)) return vals, fmt.Errorf("conflicting options: dns and the network mode: " + string(vals.Net.Network.NSMode))
} }

View File

@ -0,0 +1,10 @@
####> This option file is used in:
####> podman create, pod clone, pod create, run
####> If file is edited, make sure the changes
####> are applicable to all of those.
#### **--shm-size-systemd**=*number[unit]*
Size of systemd-specific tmpfs mounts such as /run, /run/lock, /var/log/journal and /tmp.
A _unit_ can be **b** (bytes), **k** (kibibytes), **m** (mebibytes), or **g** (gibibytes).
If the unit is omitted, the system uses bytes. If the size is omitted, the default is **64m**.
When _size_ is **0**, the usage is limited to 50% of the host's available memory.

View File

@ -328,6 +328,8 @@ Automatically remove the container when it exits. The default is *false*.
@@option shm-size @@option shm-size
@@option shm-size-systemd
@@option stop-signal @@option stop-signal
@@option stop-timeout @@option stop-timeout

View File

@ -71,6 +71,8 @@ Set a custom name for the cloned pod. The default if not specified is of the syn
@@option shm-size @@option shm-size
@@option shm-size-systemd
#### **--start** #### **--start**
When set to true, this flag starts the newly created pod after the When set to true, this flag starts the newly created pod after the

View File

@ -157,6 +157,8 @@ Note: This options conflict with **--share=cgroup** since that would set the pod
@@option shm-size @@option shm-size
@@option shm-size-systemd
@@option subgidname @@option subgidname
@@option subuidname @@option subuidname

View File

@ -358,6 +358,8 @@ container is using it. The default is *false*.
@@option shm-size @@option shm-size
@@option shm-size-systemd
@@option sig-proxy @@option sig-proxy
The default is **true**. The default is **true**.

View File

@ -130,6 +130,8 @@ type ContainerRootFSConfig struct {
// ShmSize is the size of the container's SHM. Only used if ShmDir was // ShmSize is the size of the container's SHM. Only used if ShmDir was
// not set manually at time of creation. // not set manually at time of creation.
ShmSize int64 `json:"shmSize"` ShmSize int64 `json:"shmSize"`
// ShmSizeSystemd is the size of systemd-specific tmpfs mounts
ShmSizeSystemd int64 `json:"shmSizeSystemd"`
// Static directory for container content that will persist across // Static directory for container content that will persist across
// reboot. // reboot.
// StaticDir is a persistent directory for Libpod files that will // StaticDir is a persistent directory for Libpod files that will
@ -443,6 +445,7 @@ type InfraInherit struct {
SelinuxOpts []string `json:"selinux_opts,omitempty"` SelinuxOpts []string `json:"selinux_opts,omitempty"`
Volumes []*specgen.NamedVolume `json:"volumes,omitempty"` Volumes []*specgen.NamedVolume `json:"volumes,omitempty"`
ShmSize *int64 `json:"shm_size"` ShmSize *int64 `json:"shm_size"`
ShmSizeSystemd *int64 `json:"shm_size_systemd"`
} }
// IsDefaultShmSize determines if the user actually set the shm in the parent ctr or if it has been set to the default size // IsDefaultShmSize determines if the user actually set the shm in the parent ctr or if it has been set to the default size

View File

@ -205,6 +205,12 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
if !containerUUIDSet { if !containerUUIDSet {
g.AddProcessEnv("container_uuid", c.ID()[:32]) g.AddProcessEnv("container_uuid", c.ID()[:32])
} }
// limit systemd-specific tmpfs mounts if specified
// while creating a pod or ctr, if not, default back to 50%
var shmSizeSystemdMntOpt string
if c.config.ShmSizeSystemd != 0 {
shmSizeSystemdMntOpt = fmt.Sprintf("size=%d", c.config.ShmSizeSystemd)
}
options := []string{"rw", "rprivate", "nosuid", "nodev"} options := []string{"rw", "rprivate", "nosuid", "nodev"}
for _, dest := range []string{"/run", "/run/lock"} { for _, dest := range []string{"/run", "/run/lock"} {
if MountExists(mounts, dest) { if MountExists(mounts, dest) {
@ -214,7 +220,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
Destination: dest, Destination: dest,
Type: "tmpfs", Type: "tmpfs",
Source: "tmpfs", Source: "tmpfs",
Options: append(options, "tmpcopyup"), Options: append(options, "tmpcopyup", shmSizeSystemdMntOpt),
} }
g.AddMount(tmpfsMnt) g.AddMount(tmpfsMnt)
} }
@ -226,7 +232,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
Destination: dest, Destination: dest,
Type: "tmpfs", Type: "tmpfs",
Source: "tmpfs", Source: "tmpfs",
Options: append(options, "tmpcopyup"), Options: append(options, "tmpcopyup", shmSizeSystemdMntOpt),
} }
g.AddMount(tmpfsMnt) g.AddMount(tmpfsMnt)
} }

View File

@ -671,6 +671,23 @@ func WithShmSize(size int64) CtrCreateOption {
} }
} }
// WithShmSizeSystemd sets the size of systemd-specific mounts:
//
// /run
// /run/lock
// /var/log/journal
// /tmp
func WithShmSizeSystemd(size int64) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return define.ErrCtrFinalized
}
ctr.config.ShmSizeSystemd = size
return nil
}
}
// WithPrivileged sets the privileged flag in the container runtime. // WithPrivileged sets the privileged flag in the container runtime.
func WithPrivileged(privileged bool) CtrCreateOption { func WithPrivileged(privileged bool) CtrCreateOption {
return func(ctr *Container) error { return func(ctr *Container) error {

View File

@ -260,6 +260,7 @@ type ContainerCreateOptions struct {
SecurityOpt []string `json:"security_opt,omitempty"` SecurityOpt []string `json:"security_opt,omitempty"`
SdNotifyMode string SdNotifyMode string
ShmSize string ShmSize string
ShmSizeSystemd string
SignaturePolicy string SignaturePolicy string
StartupHCCmd string StartupHCCmd string
StartupHCInterval string StartupHCInterval string
@ -269,8 +270,8 @@ type ContainerCreateOptions struct {
StopSignal string StopSignal string
StopTimeout uint StopTimeout uint
StorageOpts []string StorageOpts []string
SubUIDName string
SubGIDName string SubGIDName string
SubUIDName string
Sysctl []string `json:"sysctl,omitempty"` Sysctl []string `json:"sysctl,omitempty"`
Systemd string Systemd string
Timeout uint Timeout uint

View File

@ -478,6 +478,7 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID
specg.HostDeviceList = conf.DeviceHostSrc specg.HostDeviceList = conf.DeviceHostSrc
specg.Networks = conf.Networks specg.Networks = conf.Networks
specg.ShmSize = &conf.ShmSize specg.ShmSize = &conf.ShmSize
specg.ShmSizeSystemd = &conf.ShmSizeSystemd
mapSecurityConfig(conf, specg) mapSecurityConfig(conf, specg)

View File

@ -512,6 +512,9 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
if s.ShmSize != nil { if s.ShmSize != nil {
options = append(options, libpod.WithShmSize(*s.ShmSize)) options = append(options, libpod.WithShmSize(*s.ShmSize))
} }
if s.ShmSizeSystemd != nil {
options = append(options, libpod.WithShmSizeSystemd(*s.ShmSizeSystemd))
}
if s.Rootfs != "" { if s.Rootfs != "" {
options = append(options, libpod.WithRootFS(s.Rootfs, s.RootfsOverlay, s.RootfsMapping)) options = append(options, libpod.WithRootFS(s.Rootfs, s.RootfsOverlay, s.RootfsMapping))
} }

View File

@ -192,6 +192,10 @@ type PodStorageConfig struct {
// Conflicts with ShmSize if IpcNS is not private. // Conflicts with ShmSize if IpcNS is not private.
// Optional. // Optional.
ShmSize *int64 `json:"shm_size,omitempty"` ShmSize *int64 `json:"shm_size,omitempty"`
// ShmSizeSystemd is the size of systemd-specific tmpfs mounts
// specifically /run, /run/lock, /var/log/journal and /tmp.
// Optional
ShmSizeSystemd *int64 `json:"shm_size_systemd,omitempty"`
} }
// PodCgroupConfig contains configuration options about a pod's cgroups. // PodCgroupConfig contains configuration options about a pod's cgroups.

View File

@ -295,6 +295,10 @@ type ContainerStorageConfig struct {
// Conflicts with ShmSize if IpcNS is not private. // Conflicts with ShmSize if IpcNS is not private.
// Optional. // Optional.
ShmSize *int64 `json:"shm_size,omitempty"` ShmSize *int64 `json:"shm_size,omitempty"`
// ShmSizeSystemd is the size of systemd-specific tmpfs mounts
// specifically /run, /run/lock, /var/log/journal and /tmp.
// Optional
ShmSizeSystemd *int64 `json:"shm_size_systemd,omitempty"`
// WorkDir is the container's working directory. // WorkDir is the container's working directory.
// If unset, the default, /, will be used. // If unset, the default, /, will be used.
// Optional. // Optional.

View File

@ -488,6 +488,16 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
s.ShmSize = &val s.ShmSize = &val
} }
// SHM Size Systemd
if c.ShmSizeSystemd != "" {
val, err := units.RAMInBytes(c.ShmSizeSystemd)
if err != nil {
return fmt.Errorf("unable to translate --shm-size-systemd: %w", err)
}
s.ShmSizeSystemd = &val
}
if c.Net != nil { if c.Net != nil {
s.Networks = c.Net.Networks s.Networks = c.Net.Networks
} }

View File

@ -1193,4 +1193,24 @@ ENTRYPOINT ["sleep","99999"]
podJSON := podInspect.InspectPodToJSON() podJSON := podInspect.InspectPodToJSON()
Expect(podJSON.InfraConfig).To(HaveField("UtsNS", ns)) Expect(podJSON.InfraConfig).To(HaveField("UtsNS", ns))
}) })
It("podman pod create --shm-size-systemd", func() {
podName := "testShmSizeSystemd"
session := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--shm-size-systemd", "10mb"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
// add container to pod
ctrRun := podmanTest.Podman([]string{"run", "-d", "--pod", podName, SYSTEMD_IMAGE, "/sbin/init"})
ctrRun.WaitWithDefaultTimeout()
Expect(ctrRun).Should(Exit(0))
run := podmanTest.Podman([]string{"exec", ctrRun.OutputToString(), "mount"})
run.WaitWithDefaultTimeout()
Expect(run).Should(Exit(0))
t, strings := run.GrepString("tmpfs on /run/lock")
Expect(t).To(BeTrue())
Expect(strings[0]).Should(ContainSubstring("size=10240k"))
})
}) })

View File

@ -2053,4 +2053,22 @@ WORKDIR /madethis`, BB)
Expect(session).Should(Exit(0)) Expect(session).Should(Exit(0))
Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull")) Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull"))
}) })
It("podman run --shm-size-systemd", func() {
ctrName := "testShmSizeSystemd"
run := podmanTest.Podman([]string{"run", "--name", ctrName, "--shm-size-systemd", "10mb", "-d", SYSTEMD_IMAGE, "/sbin/init"})
run.WaitWithDefaultTimeout()
Expect(run).Should(Exit(0))
logs := podmanTest.Podman([]string{"logs", ctrName})
logs.WaitWithDefaultTimeout()
Expect(logs).Should(Exit(0))
mount := podmanTest.Podman([]string{"exec", ctrName, "mount"})
mount.WaitWithDefaultTimeout()
Expect(mount).Should(Exit(0))
t, strings := mount.GrepString("tmpfs on /run/lock")
Expect(t).To(BeTrue())
Expect(strings[0]).Should(ContainSubstring("size=10240k"))
})
}) })