Add a way to disable port reservation

We've increased the default rlimits to allow Podman to hold many
ports open without hitting limits and crashing, but this doesn't
solve the amount of memory that holding open potentially
thousands of ports will use. Offer a switch to optionally disable
port reservation for performance- and memory-constrained use
cases.

Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
This commit is contained in:
Matthew Heon 2018-09-13 14:42:47 -04:00
parent 61eda671ec
commit 95a374100b
3 changed files with 42 additions and 20 deletions

View File

@ -80,3 +80,11 @@ pause_image = "k8s.gcr.io/pause:3.1"
# Default command to run the pause container
pause_command = "/pause"
# Determines whether libpod will reserve ports on the host when they are
# forwarded to containers. When enabled, when ports are forwarded to containers,
# they are held open by conmon as long as the container is running, ensuring that
# they cannot be reused by other programs on the host. However, this can cause
# significant memory usage if a container has many ports forwarded to it.
# Disabling this can save memory.
#enable_port_reservation = true

View File

@ -66,6 +66,7 @@ type OCIRuntime struct {
socketsDir string
logSizeMax int64
noPivot bool
reservePorts bool
}
// syncInfo is used to return data from monitor process to daemon
@ -75,7 +76,7 @@ type syncInfo struct {
}
// Make a new OCI runtime with provided options
func newOCIRuntime(name string, path string, conmonPath string, conmonEnv []string, cgroupManager string, tmpDir string, logSizeMax int64, noPivotRoot bool) (*OCIRuntime, error) {
func newOCIRuntime(name string, path string, conmonPath string, conmonEnv []string, cgroupManager string, tmpDir string, logSizeMax int64, noPivotRoot bool, reservePorts bool) (*OCIRuntime, error) {
runtime := new(OCIRuntime)
runtime.name = name
runtime.path = path
@ -85,6 +86,7 @@ func newOCIRuntime(name string, path string, conmonPath string, conmonEnv []stri
runtime.tmpDir = tmpDir
runtime.logSizeMax = logSizeMax
runtime.noPivot = noPivotRoot
runtime.reservePorts = reservePorts
runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits")
runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket")
@ -311,15 +313,17 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string) (er
cmd.Env = append(cmd.Env, fmt.Sprintf("_OCI_STARTPIPE=%d", 4))
cmd.Env = append(cmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir))
ports, err := bindPorts(ctr.config.PortMappings)
if err != nil {
return err
}
if r.reservePorts {
ports, err := bindPorts(ctr.config.PortMappings)
if err != nil {
return err
}
// Leak the port we bound in the conmon process. These fd's won't be used
// by the container and conmon will keep the ports busy so that another
// process cannot use them.
cmd.ExtraFiles = append(cmd.ExtraFiles, ports...)
// Leak the port we bound in the conmon process. These fd's won't be used
// by the container and conmon will keep the ports busy so that another
// process cannot use them.
cmd.ExtraFiles = append(cmd.ExtraFiles, ports...)
}
if rootless.IsRootless() {
ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe()

View File

@ -164,6 +164,14 @@ type RuntimeConfig struct {
InfraImage string `toml:"infra_image"`
// InfraCommand is the command run to start up a pod infra container
InfraCommand string `toml:"infra_command"`
// EnablePortReservation determines whether libpod will reserve ports on
// the host when they are forwarded to containers.
// When enabled, when ports are forwarded to containers, they are
// held open by conmon as long as the container is running, ensuring
// that they cannot be reused by other programs on the host.
// However, this can cause significant memory usage if a container has
// many ports forwarded to it. Disabling this can save memory.
EnablePortReservation bool `toml:"enable_port_reservation"`
}
var (
@ -190,16 +198,17 @@ var (
ConmonEnvVars: []string{
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
},
CgroupManager: SystemdCgroupsManager,
HooksDir: hooks.DefaultDir,
StaticDir: filepath.Join(storage.DefaultStoreOptions.GraphRoot, "libpod"),
TmpDir: "",
MaxLogSize: -1,
NoPivotRoot: false,
CNIConfigDir: "/etc/cni/net.d/",
CNIPluginDir: []string{"/usr/libexec/cni", "/usr/lib/cni", "/opt/cni/bin"},
InfraCommand: DefaultInfraCommand,
InfraImage: DefaultInfraImage,
CgroupManager: SystemdCgroupsManager,
HooksDir: hooks.DefaultDir,
StaticDir: filepath.Join(storage.DefaultStoreOptions.GraphRoot, "libpod"),
TmpDir: "",
MaxLogSize: -1,
NoPivotRoot: false,
CNIConfigDir: "/etc/cni/net.d/",
CNIPluginDir: []string{"/usr/libexec/cni", "/usr/lib/cni", "/opt/cni/bin"},
InfraCommand: DefaultInfraCommand,
InfraImage: DefaultInfraImage,
EnablePortReservation: true,
}
)
@ -467,7 +476,8 @@ func makeRuntime(runtime *Runtime) (err error) {
ociRuntime, err := newOCIRuntime("runc", runtime.ociRuntimePath,
runtime.conmonPath, runtime.config.ConmonEnvVars,
runtime.config.CgroupManager, runtime.config.TmpDir,
runtime.config.MaxLogSize, runtime.config.NoPivotRoot)
runtime.config.MaxLogSize, runtime.config.NoPivotRoot,
runtime.config.EnablePortReservation)
if err != nil {
return err
}