Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for limiting tmpfs size for systemd-specific mnts #17207

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cmd/podman/common/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,13 @@ func DefineCreateFlags(cmd *cobra.Command, cf *entities.ContainerCreateOptions,
)
_ = 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"
createFlags.StringSliceVar(
&cf.Sysctl,
Expand Down
3 changes: 3 additions & 0 deletions cmd/podman/containers/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
if c.Flag("shm-size").Changed {
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()) {
return vals, fmt.Errorf("conflicting options: dns and the network mode: " + string(vals.Net.Network.NSMode))
}
Expand Down
10 changes: 10 additions & 0 deletions docs/source/markdown/options/shm-size-systemd.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-create.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,8 @@ Automatically remove the container when it exits. The default is *false*.

@@option shm-size

@@option shm-size-systemd

@@option stop-signal

@@option stop-timeout
Expand Down
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-pod-clone.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -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-systemd

#### **--start**

When set to true, this flag starts the newly created pod after the
Expand Down
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-pod-create.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ Note: This options conflict with **--share=cgroup** since that would set the pod

@@option shm-size

@@option shm-size-systemd

@@option subgidname

@@option subuidname
Expand Down
2 changes: 2 additions & 0 deletions docs/source/markdown/podman-run.1.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,8 @@ container is using it. The default is *false*.

@@option shm-size

@@option shm-size-systemd

@@option sig-proxy

The default is **true**.
Expand Down
3 changes: 3 additions & 0 deletions libpod/container_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ type ContainerRootFSConfig struct {
// ShmSize is the size of the container's SHM. Only used if ShmDir was
// not set manually at time of creation.
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
// reboot.
// StaticDir is a persistent directory for Libpod files that will
Expand Down Expand Up @@ -443,6 +445,7 @@ type InfraInherit struct {
SelinuxOpts []string `json:"selinux_opts,omitempty"`
Volumes []*specgen.NamedVolume `json:"volumes,omitempty"`
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
Expand Down
10 changes: 8 additions & 2 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
if !containerUUIDSet {
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"}
for _, dest := range []string{"/run", "/run/lock"} {
if MountExists(mounts, dest) {
Expand All @@ -214,7 +220,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
Destination: dest,
Type: "tmpfs",
Source: "tmpfs",
Options: append(options, "tmpcopyup"),
Options: append(options, "tmpcopyup", shmSizeSystemdMntOpt),
}
g.AddMount(tmpfsMnt)
}
Expand All @@ -226,7 +232,7 @@ func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) erro
Destination: dest,
Type: "tmpfs",
Source: "tmpfs",
Options: append(options, "tmpcopyup"),
Options: append(options, "tmpcopyup", shmSizeSystemdMntOpt),
}
g.AddMount(tmpfsMnt)
}
Expand Down
17 changes: 17 additions & 0 deletions libpod/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
func WithPrivileged(privileged bool) CtrCreateOption {
return func(ctr *Container) error {
Expand Down
3 changes: 2 additions & 1 deletion pkg/domain/entities/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ type ContainerCreateOptions struct {
SecurityOpt []string `json:"security_opt,omitempty"`
SdNotifyMode string
ShmSize string
ShmSizeSystemd string
SignaturePolicy string
StartupHCCmd string
StartupHCInterval string
Expand All @@ -269,8 +270,8 @@ type ContainerCreateOptions struct {
StopSignal string
StopTimeout uint
StorageOpts []string
SubUIDName string
SubGIDName string
SubUIDName string
Sysctl []string `json:"sysctl,omitempty"`
Systemd string
Timeout uint
Expand Down
1 change: 1 addition & 0 deletions pkg/specgen/generate/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ func ConfigToSpec(rt *libpod.Runtime, specg *specgen.SpecGenerator, containerID
specg.HostDeviceList = conf.DeviceHostSrc
specg.Networks = conf.Networks
specg.ShmSize = &conf.ShmSize
specg.ShmSizeSystemd = &conf.ShmSizeSystemd

mapSecurityConfig(conf, specg)

Expand Down
3 changes: 3 additions & 0 deletions pkg/specgen/generate/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,9 @@ func createContainerOptions(rt *libpod.Runtime, s *specgen.SpecGenerator, pod *l
if s.ShmSize != nil {
options = append(options, libpod.WithShmSize(*s.ShmSize))
}
if s.ShmSizeSystemd != nil {
options = append(options, libpod.WithShmSizeSystemd(*s.ShmSizeSystemd))
}
if s.Rootfs != "" {
options = append(options, libpod.WithRootFS(s.Rootfs, s.RootfsOverlay, s.RootfsMapping))
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/specgen/podspecgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,10 @@ type PodStorageConfig struct {
// Conflicts with ShmSize if IpcNS is not private.
// Optional.
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.
Expand Down
4 changes: 4 additions & 0 deletions pkg/specgen/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,10 @@ type ContainerStorageConfig struct {
// Conflicts with ShmSize if IpcNS is not private.
// Optional.
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.
// If unset, the default, /, will be used.
// Optional.
Expand Down
10 changes: 10 additions & 0 deletions pkg/specgenutil/specgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,16 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *entities.ContainerCreateOptions
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 {
s.Networks = c.Net.Networks
}
Expand Down
20 changes: 20 additions & 0 deletions test/e2e/pod_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1193,4 +1193,24 @@ ENTRYPOINT ["sleep","99999"]
podJSON := podInspect.InspectPodToJSON()
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"))
})

})
18 changes: 18 additions & 0 deletions test/e2e/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2053,4 +2053,22 @@ WORKDIR /madethis`, BB)
Expect(session).Should(Exit(0))
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"))
})
})