Merge pull request #1650 from rhatdan/systemd

Mount proper cgroup for systemd to manage inside of the container.
This commit is contained in:
Matthew Heon 2018-10-16 13:26:20 -04:00 committed by GitHub
commit a2266c63b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 72 additions and 50 deletions

View file

@ -346,6 +346,9 @@ type ContainerConfig struct {
// IsInfra is a bool indicating whether this container is an infra container used for
// sharing kernel namespaces in a pod
IsInfra bool `json:"pause"`
// Systemd tells libpod to setup the container in systemd mode
Systemd bool `json:"systemd"`
}
// ContainerStatus returns a string representation for users

View file

@ -1682,6 +1682,8 @@ func easyjson1dbef17bDecodeGithubComContainersLibpodLibpod2(in *jlexer.Lexer, ou
}
case "pause":
out.IsInfra = bool(in.Bool())
case "systemd":
out.Systemd = bool(in.Bool())
default:
in.SkipRecursive()
}
@ -2344,6 +2346,16 @@ func easyjson1dbef17bEncodeGithubComContainersLibpodLibpod2(out *jwriter.Writer,
}
out.Bool(bool(in.IsInfra))
}
{
const prefix string = ",\"systemd\":"
if first {
first = false
out.RawString(prefix[1:])
} else {
out.RawString(prefix)
}
out.Bool(bool(in.Systemd))
}
out.RawByte('}')
}

View file

@ -188,6 +188,10 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
}
}
if c.config.Systemd {
c.setupSystemd(g.Mounts(), g)
}
// Look up and add groups the user belongs to, if a group wasn't directly specified
if !rootless.IsRootless() && !strings.Contains(c.config.User, ":") {
groups, err := chrootuser.GetAdditionalGroupsForUser(c.state.Mountpoint, uint64(g.Config.Process.User.UID))
@ -294,6 +298,43 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
return g.Config, nil
}
// systemd expects to have /run, /run/lock and /tmp on tmpfs
// It also expects to be able to write to /sys/fs/cgroup/systemd and /var/log/journal
func (c *Container) setupSystemd(mounts []spec.Mount, g generate.Generator) {
options := []string{"rw", "rprivate", "noexec", "nosuid", "nodev"}
for _, dest := range []string{"/run", "/run/lock"} {
if MountExists(mounts, dest) {
continue
}
tmpfsMnt := spec.Mount{
Destination: dest,
Type: "tmpfs",
Source: "tmpfs",
Options: append(options, "tmpcopyup", "size=65536k"),
}
g.AddMount(tmpfsMnt)
}
for _, dest := range []string{"/tmp", "/var/log/journal"} {
if MountExists(mounts, dest) {
continue
}
tmpfsMnt := spec.Mount{
Destination: dest,
Type: "tmpfs",
Source: "tmpfs",
Options: append(options, "tmpcopyup"),
}
g.AddMount(tmpfsMnt)
}
systemdMnt := spec.Mount{
Destination: "/sys/fs/cgroup/systemd",
Type: "bind",
Source: fmt.Sprintf("/sys/fs/cgroup/systemd%s/libpod-%s", CgroupfsDefaultCgroupParent, c.ID()),
Options: []string{"bind", "private"},
}
g.AddMount(systemdMnt)
}
// Add an existing container's namespace to the spec
func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr string, specNS string) error {
nsCtr, err := c.runtime.state.Container(ctr)

View file

@ -349,6 +349,18 @@ func WithShmDir(dir string) CtrCreateOption {
}
}
// WithSystemd turns on systemd mode in the container
func WithSystemd() CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
}
ctr.config.Systemd = true
return nil
}
}
// WithShmSize sets the size of /dev/shm tmpfs mount.
func WithShmSize(size int64) CtrCreateOption {
return func(ctr *Container) error {

View file

@ -319,6 +319,10 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib
if c.Interactive {
options = append(options, libpod.WithStdin())
}
if c.Systemd && (strings.HasSuffix(c.Command[0], "init") ||
strings.HasSuffix(c.Command[0], "systemd")) {
options = append(options, libpod.WithSystemd())
}
if c.Name != "" {
logrus.Debugf("appending name %s", c.Name)
options = append(options, libpod.WithName(c.Name))

View file

@ -5,7 +5,6 @@ import (
"path"
"strings"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
"github.com/docker/docker/daemon/caps"
"github.com/docker/docker/pkg/mount"
@ -261,12 +260,6 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint
addedResources = true
}
if config.Systemd && (strings.HasSuffix(config.Command[0], "init") ||
strings.HasSuffix(config.Command[0], "systemd")) {
if err := setupSystemd(config, &g); err != nil {
return nil, errors.Wrap(err, "failed to setup systemd")
}
}
for _, i := range config.Tmpfs {
// Default options if nothing passed
options := []string{"rw", "rprivate", "noexec", "nosuid", "nodev", "size=65536k"}
@ -408,49 +401,6 @@ func blockAccessToKernelFilesystems(config *CreateConfig, g *generate.Generator)
}
}
// systemd expects to have /run, /run/lock and /tmp on tmpfs
// It also expects to be able to write to /sys/fs/cgroup/systemd and /var/log/journal
func setupSystemd(config *CreateConfig, g *generate.Generator) error {
mounts, err := config.GetVolumeMounts([]spec.Mount{})
if err != nil {
return err
}
options := []string{"rw", "rprivate", "noexec", "nosuid", "nodev"}
for _, dest := range []string{"/run", "/run/lock"} {
if libpod.MountExists(mounts, dest) {
continue
}
tmpfsMnt := spec.Mount{
Destination: dest,
Type: "tmpfs",
Source: "tmpfs",
Options: append(options, "tmpcopyup", "size=65536k"),
}
g.AddMount(tmpfsMnt)
}
for _, dest := range []string{"/tmp", "/var/log/journal"} {
if libpod.MountExists(mounts, dest) {
continue
}
tmpfsMnt := spec.Mount{
Destination: dest,
Type: "tmpfs",
Source: "tmpfs",
Options: append(options, "tmpcopyup"),
}
g.AddMount(tmpfsMnt)
}
tmpfsMnt := spec.Mount{
Destination: "/sys/fs/cgroup/systemd",
Type: "tmpfs",
Source: "tmpfs",
Options: append(options, "size=65536k"),
}
g.AddMount(tmpfsMnt)
return nil
}
func addPidNS(config *CreateConfig, g *generate.Generator) error {
pidMode := config.PidMode
if IsNS(string(pidMode)) {