mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-09-11 01:57:53 +00:00
The initial version of libimage changed the order of layers which has now been restored to remain backwards compatible. Further changes: * Fix a bug in the journald logging which requires to strip trailing new lines from the message. The system tests did not pass due to empty new lines. Triggered by changing the default logger to journald in containers/common. * Fix another bug in the journald logging which embedded the container ID inside the message rather than the specifid field. That surfaced in a preceeding whitespace of each log line which broke the system tests. * Alter the system tests to make sure that the k8s-file and the journald logging drivers are executed. * A number of e2e tests have been changed to force the k8s-file driver to make them pass when running inside a root container. * Increase the timeout in a kill test which seems to take longer now. Reasons are unknown. Tests passed earlier and no signal-related changes happend. It may be CI VM flake since some system tests but other flaked. Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
546 lines
16 KiB
Go
546 lines
16 KiB
Go
package config
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"regexp"
|
|
"strconv"
|
|
|
|
"github.com/containers/common/pkg/apparmor"
|
|
"github.com/containers/common/pkg/cgroupv2"
|
|
"github.com/containers/storage/pkg/homedir"
|
|
"github.com/containers/storage/pkg/unshare"
|
|
"github.com/containers/storage/types"
|
|
"github.com/opencontainers/selinux/go-selinux"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
// _conmonMinMajorVersion is the major version required for conmon.
|
|
_conmonMinMajorVersion = 2
|
|
|
|
// _conmonMinMinorVersion is the minor version required for conmon.
|
|
_conmonMinMinorVersion = 0
|
|
|
|
// _conmonMinPatchVersion is the sub-minor version required for conmon.
|
|
_conmonMinPatchVersion = 1
|
|
|
|
// _conmonVersionFormatErr is used when the expected versio-format of conmon
|
|
// has changed.
|
|
_conmonVersionFormatErr = "conmon version changed format"
|
|
|
|
// _defaultGraphRoot points to the default path of the graph root.
|
|
_defaultGraphRoot = "/var/lib/containers/storage"
|
|
|
|
// _defaultTransport is a prefix that we apply to an image name to check
|
|
// docker hub first for the image.
|
|
_defaultTransport = "docker://"
|
|
)
|
|
|
|
var (
|
|
// DefaultInitPath is the default path to the container-init binary
|
|
DefaultInitPath = "/usr/libexec/podman/catatonit"
|
|
// DefaultInfraImage to use for infra container
|
|
DefaultInfraImage = "k8s.gcr.io/pause:3.5"
|
|
// DefaultRootlessSHMLockPath is the default path for rootless SHM locks
|
|
DefaultRootlessSHMLockPath = "/libpod_rootless_lock"
|
|
// DefaultDetachKeys is the default keys sequence for detaching a
|
|
// container
|
|
DefaultDetachKeys = "ctrl-p,ctrl-q"
|
|
// ErrConmonOutdated indicates the version of conmon found (whether via the configuration or $PATH)
|
|
// is out of date for the current podman version
|
|
ErrConmonOutdated = errors.New("outdated conmon version")
|
|
// ErrInvalidArg indicates that an invalid argument was passed
|
|
ErrInvalidArg = errors.New("invalid argument")
|
|
// DefaultHooksDirs defines the default hooks directory
|
|
DefaultHooksDirs = []string{"/usr/share/containers/oci/hooks.d"}
|
|
// DefaultCapabilities for the default_capabilities option in the containers.conf file
|
|
DefaultCapabilities = []string{
|
|
"CAP_AUDIT_WRITE",
|
|
"CAP_CHOWN",
|
|
"CAP_DAC_OVERRIDE",
|
|
"CAP_FOWNER",
|
|
"CAP_FSETID",
|
|
"CAP_KILL",
|
|
"CAP_MKNOD",
|
|
"CAP_NET_BIND_SERVICE",
|
|
"CAP_NET_RAW",
|
|
"CAP_SETFCAP",
|
|
"CAP_SETGID",
|
|
"CAP_SETPCAP",
|
|
"CAP_SETUID",
|
|
"CAP_SYS_CHROOT",
|
|
}
|
|
|
|
cniBinDir = []string{
|
|
"/usr/libexec/cni",
|
|
"/usr/lib/cni",
|
|
"/usr/local/lib/cni",
|
|
"/opt/cni/bin",
|
|
}
|
|
)
|
|
|
|
const (
|
|
// _etcDir is the sysconfdir where podman should look for system config files.
|
|
// It can be overridden at build time.
|
|
_etcDir = "/etc"
|
|
// InstallPrefix is the prefix where podman will be installed.
|
|
// It can be overridden at build time.
|
|
_installPrefix = "/usr"
|
|
// _cniConfigDir is the directory where cni configuration is found
|
|
_cniConfigDir = "/etc/cni/net.d/"
|
|
// _cniConfigDirRootless is the directory in XDG_CONFIG_HOME for cni plugins
|
|
_cniConfigDirRootless = "cni/net.d/"
|
|
// CgroupfsCgroupsManager represents cgroupfs native cgroup manager
|
|
CgroupfsCgroupsManager = "cgroupfs"
|
|
// DefaultApparmorProfile specifies the default apparmor profile for the container.
|
|
DefaultApparmorProfile = apparmor.Profile
|
|
// SystemdCgroupsManager represents systemd native cgroup manager
|
|
SystemdCgroupsManager = "systemd"
|
|
// DefaultLogDriver is the default type of log files
|
|
DefaultLogDriver = "journald"
|
|
// DefaultLogSizeMax is the default value for the maximum log size
|
|
// allowed for a container. Negative values mean that no limit is imposed.
|
|
DefaultLogSizeMax = -1
|
|
// DefaultPidsLimit is the default value for maximum number of processes
|
|
// allowed inside a container
|
|
DefaultPidsLimit = 2048
|
|
// DefaultPullPolicy pulls the image if it does not exist locally
|
|
DefaultPullPolicy = "missing"
|
|
// DefaultSignaturePolicyPath is the default value for the
|
|
// policy.json file.
|
|
DefaultSignaturePolicyPath = "/etc/containers/policy.json"
|
|
// DefaultSubnet is the subnet that will be used for the default CNI
|
|
// network.
|
|
DefaultSubnet = "10.88.0.0/16"
|
|
// DefaultRootlessSignaturePolicyPath is the location within
|
|
// XDG_CONFIG_HOME of the rootless policy.json file.
|
|
DefaultRootlessSignaturePolicyPath = "containers/policy.json"
|
|
// DefaultShmSize default value
|
|
DefaultShmSize = "65536k"
|
|
// DefaultUserNSSize default value
|
|
DefaultUserNSSize = 65536
|
|
// OCIBufSize limits maximum LogSizeMax
|
|
OCIBufSize = 8192
|
|
// SeccompOverridePath if this exists it overrides the default seccomp path.
|
|
SeccompOverridePath = _etcDir + "/containers/seccomp.json"
|
|
// SeccompDefaultPath defines the default seccomp path.
|
|
SeccompDefaultPath = _installPrefix + "/share/containers/seccomp.json"
|
|
)
|
|
|
|
// DefaultConfig defines the default values from containers.conf
|
|
func DefaultConfig() (*Config, error) {
|
|
|
|
defaultEngineConfig, err := defaultConfigFromMemory()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
netns := "bridge"
|
|
|
|
cniConfig := _cniConfigDir
|
|
|
|
defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath
|
|
if unshare.IsRootless() {
|
|
configHome, err := homedir.GetConfigHome()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sigPath := filepath.Join(configHome, DefaultRootlessSignaturePolicyPath)
|
|
defaultEngineConfig.SignaturePolicyPath = sigPath
|
|
if _, err := os.Stat(sigPath); err != nil {
|
|
if _, err := os.Stat(DefaultSignaturePolicyPath); err == nil {
|
|
defaultEngineConfig.SignaturePolicyPath = DefaultSignaturePolicyPath
|
|
}
|
|
}
|
|
netns = "slirp4netns"
|
|
cniConfig = filepath.Join(configHome, _cniConfigDirRootless)
|
|
}
|
|
|
|
cgroupNS := "host"
|
|
if cgroup2, _ := cgroupv2.Enabled(); cgroup2 {
|
|
cgroupNS = "private"
|
|
}
|
|
|
|
return &Config{
|
|
Containers: ContainersConfig{
|
|
Devices: []string{},
|
|
Volumes: []string{},
|
|
Annotations: []string{},
|
|
ApparmorProfile: DefaultApparmorProfile,
|
|
CgroupNS: cgroupNS,
|
|
Cgroups: "enabled",
|
|
DefaultCapabilities: DefaultCapabilities,
|
|
DefaultSysctls: []string{},
|
|
DefaultUlimits: getDefaultProcessLimits(),
|
|
DNSServers: []string{},
|
|
DNSOptions: []string{},
|
|
DNSSearches: []string{},
|
|
EnableKeyring: true,
|
|
EnableLabeling: selinuxEnabled(),
|
|
Env: []string{
|
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
"TERM=xterm",
|
|
},
|
|
EnvHost: false,
|
|
HTTPProxy: true,
|
|
Init: false,
|
|
InitPath: "",
|
|
IPCNS: "private",
|
|
LogDriver: DefaultLogDriver,
|
|
LogSizeMax: DefaultLogSizeMax,
|
|
NetNS: netns,
|
|
NoHosts: false,
|
|
PidsLimit: DefaultPidsLimit,
|
|
PidNS: "private",
|
|
SeccompProfile: SeccompDefaultPath,
|
|
ShmSize: DefaultShmSize,
|
|
TZ: "",
|
|
Umask: "0022",
|
|
UTSNS: "private",
|
|
UserNS: "host",
|
|
UserNSSize: DefaultUserNSSize,
|
|
},
|
|
Network: NetworkConfig{
|
|
DefaultNetwork: "podman",
|
|
DefaultSubnet: DefaultSubnet,
|
|
NetworkConfigDir: cniConfig,
|
|
CNIPluginDirs: cniBinDir,
|
|
},
|
|
Engine: *defaultEngineConfig,
|
|
}, nil
|
|
}
|
|
|
|
// defaultConfigFromMemory returns a default engine configuration. Note that the
|
|
// config is different for root and rootless. It also parses the storage.conf.
|
|
func defaultConfigFromMemory() (*EngineConfig, error) {
|
|
c := new(EngineConfig)
|
|
tmp, err := defaultTmpDir()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
c.TmpDir = tmp
|
|
|
|
c.EventsLogFilePath = filepath.Join(c.TmpDir, "events", "events.log")
|
|
|
|
if path, ok := os.LookupEnv("CONTAINERS_STORAGE_CONF"); ok {
|
|
types.SetDefaultConfigFilePath(path)
|
|
}
|
|
storeOpts, err := types.DefaultStoreOptions(unshare.IsRootless(), unshare.GetRootlessUID())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if storeOpts.GraphRoot == "" {
|
|
logrus.Warnf("Storage configuration is unset - using hardcoded default graph root %q", _defaultGraphRoot)
|
|
storeOpts.GraphRoot = _defaultGraphRoot
|
|
}
|
|
c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod")
|
|
c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes")
|
|
|
|
c.HooksDir = DefaultHooksDirs
|
|
c.ImageDefaultTransport = _defaultTransport
|
|
c.StateType = BoltDBStateStore
|
|
|
|
c.ImageBuildFormat = "oci"
|
|
|
|
c.CgroupManager = defaultCgroupManager()
|
|
c.StopTimeout = uint(10)
|
|
|
|
c.Remote = isRemote()
|
|
c.OCIRuntimes = map[string][]string{
|
|
"crun": {
|
|
"/usr/bin/crun",
|
|
"/usr/sbin/crun",
|
|
"/usr/local/bin/crun",
|
|
"/usr/local/sbin/crun",
|
|
"/sbin/crun",
|
|
"/bin/crun",
|
|
"/run/current-system/sw/bin/crun",
|
|
},
|
|
"runc": {
|
|
"/usr/bin/runc",
|
|
"/usr/sbin/runc",
|
|
"/usr/local/bin/runc",
|
|
"/usr/local/sbin/runc",
|
|
"/sbin/runc",
|
|
"/bin/runc",
|
|
"/usr/lib/cri-o-runc/sbin/runc",
|
|
"/run/current-system/sw/bin/runc",
|
|
},
|
|
"kata": {
|
|
"/usr/bin/kata-runtime",
|
|
"/usr/sbin/kata-runtime",
|
|
"/usr/local/bin/kata-runtime",
|
|
"/usr/local/sbin/kata-runtime",
|
|
"/sbin/kata-runtime",
|
|
"/bin/kata-runtime",
|
|
"/usr/bin/kata-qemu",
|
|
"/usr/bin/kata-fc",
|
|
},
|
|
"runsc": {
|
|
"/usr/bin/runsc",
|
|
"/usr/sbin/runsc",
|
|
"/usr/local/bin/runsc",
|
|
"/usr/local/sbin/runsc",
|
|
"/bin/runsc",
|
|
"/sbin/runsc",
|
|
"/run/current-system/sw/bin/runsc",
|
|
},
|
|
}
|
|
// Needs to be called after populating c.OCIRuntimes
|
|
c.OCIRuntime = c.findRuntime()
|
|
|
|
c.ConmonEnvVars = []string{
|
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
|
}
|
|
c.ConmonPath = []string{
|
|
"/usr/libexec/podman/conmon",
|
|
"/usr/local/libexec/podman/conmon",
|
|
"/usr/local/lib/podman/conmon",
|
|
"/usr/bin/conmon",
|
|
"/usr/sbin/conmon",
|
|
"/usr/local/bin/conmon",
|
|
"/usr/local/sbin/conmon",
|
|
"/run/current-system/sw/bin/conmon",
|
|
}
|
|
c.PullPolicy = DefaultPullPolicy
|
|
c.RuntimeSupportsJSON = []string{
|
|
"crun",
|
|
"runc",
|
|
"kata",
|
|
"runsc",
|
|
}
|
|
c.RuntimeSupportsNoCgroups = []string{"crun"}
|
|
c.RuntimeSupportsKVM = []string{"kata", "kata-runtime", "kata-qemu", "kata-fc"}
|
|
c.InitPath = DefaultInitPath
|
|
c.NoPivotRoot = false
|
|
|
|
c.InfraImage = DefaultInfraImage
|
|
c.EnablePortReservation = true
|
|
c.NumLocks = 2048
|
|
c.EventsLogger = defaultEventsLogger()
|
|
c.DetachKeys = DefaultDetachKeys
|
|
c.SDNotify = false
|
|
// TODO - ideally we should expose a `type LockType string` along with
|
|
// constants.
|
|
c.LockType = "shm"
|
|
c.MachineEnabled = false
|
|
|
|
return c, nil
|
|
}
|
|
|
|
func defaultTmpDir() (string, error) {
|
|
if !unshare.IsRootless() {
|
|
return "/run/libpod", nil
|
|
}
|
|
|
|
runtimeDir, err := getRuntimeDir()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
libpodRuntimeDir := filepath.Join(runtimeDir, "libpod")
|
|
|
|
if err := os.Mkdir(libpodRuntimeDir, 0700|os.ModeSticky); err != nil {
|
|
if !os.IsExist(err) {
|
|
return "", err
|
|
} else if err := os.Chmod(libpodRuntimeDir, 0700|os.ModeSticky); err != nil {
|
|
// The directory already exist, just set the sticky bit
|
|
return "", errors.Wrap(err, "set sticky bit on")
|
|
}
|
|
}
|
|
return filepath.Join(libpodRuntimeDir, "tmp"), nil
|
|
}
|
|
|
|
// probeConmon calls conmon --version and verifies it is a new enough version for
|
|
// the runtime expectations the container engine currently has.
|
|
func probeConmon(conmonBinary string) error {
|
|
cmd := exec.Command(conmonBinary, "--version")
|
|
var out bytes.Buffer
|
|
cmd.Stdout = &out
|
|
err := cmd.Run()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`)
|
|
|
|
matches := r.FindStringSubmatch(out.String())
|
|
if len(matches) != 4 {
|
|
return errors.Wrap(err, _conmonVersionFormatErr)
|
|
}
|
|
major, err := strconv.Atoi(matches[1])
|
|
if err != nil {
|
|
return errors.Wrap(err, _conmonVersionFormatErr)
|
|
}
|
|
if major < _conmonMinMajorVersion {
|
|
return ErrConmonOutdated
|
|
}
|
|
if major > _conmonMinMajorVersion {
|
|
return nil
|
|
}
|
|
|
|
minor, err := strconv.Atoi(matches[2])
|
|
if err != nil {
|
|
return errors.Wrap(err, _conmonVersionFormatErr)
|
|
}
|
|
if minor < _conmonMinMinorVersion {
|
|
return ErrConmonOutdated
|
|
}
|
|
if minor > _conmonMinMinorVersion {
|
|
return nil
|
|
}
|
|
|
|
patch, err := strconv.Atoi(matches[3])
|
|
if err != nil {
|
|
return errors.Wrap(err, _conmonVersionFormatErr)
|
|
}
|
|
if patch < _conmonMinPatchVersion {
|
|
return ErrConmonOutdated
|
|
}
|
|
if patch > _conmonMinPatchVersion {
|
|
return nil
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// NetNS returns the default network namespace
|
|
func (c *Config) NetNS() string {
|
|
if c.Containers.NetNS == "private" && unshare.IsRootless() {
|
|
return "slirp4netns"
|
|
}
|
|
return c.Containers.NetNS
|
|
}
|
|
|
|
// SecurityOptions returns the default security options
|
|
func (c *Config) SecurityOptions() []string {
|
|
securityOpts := []string{}
|
|
if c.Containers.SeccompProfile != "" && c.Containers.SeccompProfile != SeccompDefaultPath {
|
|
securityOpts = append(securityOpts, fmt.Sprintf("seccomp=%s", c.Containers.SeccompProfile))
|
|
}
|
|
if apparmor.IsEnabled() && c.Containers.ApparmorProfile != "" {
|
|
securityOpts = append(securityOpts, fmt.Sprintf("apparmor=%s", c.Containers.ApparmorProfile))
|
|
}
|
|
if selinux.GetEnabled() && !c.Containers.EnableLabeling {
|
|
securityOpts = append(securityOpts, fmt.Sprintf("label=%s", selinux.DisableSecOpt()[0]))
|
|
}
|
|
return securityOpts
|
|
}
|
|
|
|
// Sysctls returns the default sysctls
|
|
func (c *Config) Sysctls() []string {
|
|
return c.Containers.DefaultSysctls
|
|
}
|
|
|
|
// Volumes returns the default additional volumes for containersvolumes
|
|
func (c *Config) Volumes() []string {
|
|
return c.Containers.Volumes
|
|
}
|
|
|
|
// Devices returns the default additional devices for containers
|
|
func (c *Config) Devices() []string {
|
|
return c.Containers.Devices
|
|
}
|
|
|
|
// DNSServers returns the default DNS servers to add to resolv.conf in containers
|
|
func (c *Config) DNSServers() []string {
|
|
return c.Containers.DNSServers
|
|
}
|
|
|
|
// DNSSerches returns the default DNS searches to add to resolv.conf in containers
|
|
func (c *Config) DNSSearches() []string {
|
|
return c.Containers.DNSSearches
|
|
}
|
|
|
|
// DNSOptions returns the default DNS options to add to resolv.conf in containers
|
|
func (c *Config) DNSOptions() []string {
|
|
return c.Containers.DNSOptions
|
|
}
|
|
|
|
// Env returns the default additional environment variables to add to containers
|
|
func (c *Config) Env() []string {
|
|
return c.Containers.Env
|
|
}
|
|
|
|
// InitPath returns the default init path to add to containers
|
|
func (c *Config) InitPath() string {
|
|
return c.Containers.InitPath
|
|
}
|
|
|
|
// IPCNS returns the default IPC Namespace configuration to run containers with
|
|
func (c *Config) IPCNS() string {
|
|
return c.Containers.IPCNS
|
|
}
|
|
|
|
// PIDNS returns the default PID Namespace configuration to run containers with
|
|
func (c *Config) PidNS() string {
|
|
return c.Containers.PidNS
|
|
}
|
|
|
|
// CgroupNS returns the default Cgroup Namespace configuration to run containers with
|
|
func (c *Config) CgroupNS() string {
|
|
return c.Containers.CgroupNS
|
|
}
|
|
|
|
// Cgroups returns whether to containers with cgroup confinement
|
|
func (c *Config) Cgroups() string {
|
|
return c.Containers.Cgroups
|
|
}
|
|
|
|
// UTSNS returns the default UTS Namespace configuration to run containers with
|
|
func (c *Config) UTSNS() string {
|
|
return c.Containers.UTSNS
|
|
}
|
|
|
|
// ShmSize returns the default size for temporary file systems to use in containers
|
|
func (c *Config) ShmSize() string {
|
|
return c.Containers.ShmSize
|
|
}
|
|
|
|
// Ulimits returns the default ulimits to use in containers
|
|
func (c *Config) Ulimits() []string {
|
|
return c.Containers.DefaultUlimits
|
|
}
|
|
|
|
// PidsLimit returns the default maximum number of pids to use in containers
|
|
func (c *Config) PidsLimit() int64 {
|
|
if unshare.IsRootless() {
|
|
if c.Engine.CgroupManager != SystemdCgroupsManager {
|
|
return 0
|
|
}
|
|
cgroup2, _ := cgroupv2.Enabled()
|
|
if !cgroup2 {
|
|
return 0
|
|
}
|
|
}
|
|
|
|
return c.Containers.PidsLimit
|
|
}
|
|
|
|
// DetachKeys returns the default detach keys to detach from a container
|
|
func (c *Config) DetachKeys() string {
|
|
return c.Engine.DetachKeys
|
|
}
|
|
|
|
// Tz returns the timezone in the container
|
|
func (c *Config) TZ() string {
|
|
return c.Containers.TZ
|
|
}
|
|
|
|
func (c *Config) Umask() string {
|
|
return c.Containers.Umask
|
|
}
|
|
|
|
// LogDriver returns the logging driver to be used
|
|
// currently k8s-file or journald
|
|
func (c *Config) LogDriver() string {
|
|
return c.Containers.LogDriver
|
|
}
|
|
|
|
func (c *Config) MachineEnabled() bool {
|
|
return c.Engine.MachineEnabled
|
|
}
|