cgroups

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2022 License: Apache-2.0 Imports: 20 Imported by: 1,244

README

cgroups

Build Status codecov GoDoc Go Report Card

Go package for creating, managing, inspecting, and destroying cgroups. The resources format for settings on the cgroup uses the OCI runtime-spec found here.

Examples (v1)

Create a new cgroup

This creates a new cgroup using a static path for all subsystems under /test.

  • /sys/fs/cgroup/cpu/test
  • /sys/fs/cgroup/memory/test
  • etc....

It uses a single hierarchy and specifies cpu shares as a resource constraint and uses the v1 implementation of cgroups.

shares := uint64(100)
control, err := cgroups.New(cgroups.V1, cgroups.StaticPath("/test"), &specs.LinuxResources{
    CPU: &specs.LinuxCPU{
        Shares: &shares,
    },
})
defer control.Delete()
Create with systemd slice support
control, err := cgroups.New(cgroups.Systemd, cgroups.Slice("system.slice", "runc-test"), &specs.LinuxResources{
    CPU: &specs.CPU{
        Shares: &shares,
    },
})

Load an existing cgroup
control, err = cgroups.Load(cgroups.V1, cgroups.StaticPath("/test"))
Add a process to the cgroup
if err := control.Add(cgroups.Process{Pid:1234}); err != nil {
}
Update the cgroup

To update the resources applied in the cgroup

shares = uint64(200)
if err := control.Update(&specs.LinuxResources{
    CPU: &specs.LinuxCPU{
        Shares: &shares,
    },
}); err != nil {
}
Freeze and Thaw the cgroup
if err := control.Freeze(); err != nil {
}
if err := control.Thaw(); err != nil {
}
List all processes in the cgroup or recursively
processes, err := control.Processes(cgroups.Devices, recursive)
Get Stats on the cgroup
stats, err := control.Stat()

By adding cgroups.IgnoreNotExist all non-existent files will be ignored, e.g. swap memory stats without swap enabled

stats, err := control.Stat(cgroups.IgnoreNotExist)
Move process across cgroups

This allows you to take processes from one cgroup and move them to another.

err := control.MoveTo(destination)
Create subcgroup
subCgroup, err := control.New("child", resources)
Registering for memory events

This allows you to get notified by an eventfd for v1 memory cgroups events.

event := cgroups.MemoryThresholdEvent(50 * 1024 * 1024, false)
efd, err := control.RegisterMemoryEvent(event)
event := cgroups.MemoryPressureEvent(cgroups.MediumPressure, cgroups.DefaultMode)
efd, err := control.RegisterMemoryEvent(event)
efd, err := control.OOMEventFD()
// or by using RegisterMemoryEvent
event := cgroups.OOMEvent()
efd, err := control.RegisterMemoryEvent(event)

Examples (v2/unified)

Check that the current system is running cgroups v2
var cgroupV2 bool
if cgroups.Mode() == cgroups.Unified {
	cgroupV2 = true
}
Create a new cgroup

This creates a new systemd v2 cgroup slice. Systemd slices consider "-" a special character, so the resulting slice would be located here on disk:

  • /sys/fs/cgroup/my.slice/my-cgroup.slice/my-cgroup-abc.slice
import (
    cgroupsv2 "github.com/containerd/cgroups/v2"
    specs "github.com/opencontainers/runtime-spec/specs-go"
)

res := cgroupsv2.Resources{}
// dummy PID of -1 is used for creating a "general slice" to be used as a parent cgroup.
// see https://github.com/containerd/cgroups/blob/1df78138f1e1e6ee593db155c6b369466f577651/v2/manager.go#L732-L735
m, err := cgroupsv2.NewSystemd("/", "my-cgroup-abc.slice", -1, &res)
if err != nil {
	return err
}
Load an existing cgroup
m, err := cgroupsv2.LoadSystemd("/", "my-cgroup-abc.slice")
if err != nil {
	return err
}
Delete a cgroup
m, err := cgroupsv2.LoadSystemd("/", "my-cgroup-abc.slice")
if err != nil {
	return err
}
err = m.DeleteSystemd()
if err != nil {
	return err
}
Attention

All static path should not include /sys/fs/cgroup/ prefix, it should start with your own cgroups name

Project details

Cgroups is a containerd sub-project, licensed under the Apache 2.0 license. As a containerd sub-project, you will find the:

information in our containerd/project repository.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidPid               = errors.New("cgroups: pid must be greater than 0")
	ErrMountPointNotExist       = errors.New("cgroups: cgroup mountpoint does not exist")
	ErrInvalidFormat            = errors.New("cgroups: parsing file with invalid format failed")
	ErrFreezerNotSupported      = errors.New("cgroups: freezer cgroup not supported on this system")
	ErrMemoryNotSupported       = errors.New("cgroups: memory cgroup not supported on this system")
	ErrCgroupDeleted            = errors.New("cgroups: cgroup deleted")
	ErrNoCgroupMountDestination = errors.New("cgroups: cannot find cgroup mount destination")
)
View Source
var (
	// ErrIgnoreSubsystem allows the specific subsystem to be skipped
	ErrIgnoreSubsystem = errors.New("skip subsystem")
	// ErrDevicesRequired is returned when the devices subsystem is required but
	// does not exist or is not active
	ErrDevicesRequired = errors.New("devices subsystem is required")
)
View Source
var ErrControllerNotActive = errors.New("controller is not supported")

ErrControllerNotActive is returned when a controller is not supported or enabled

Functions

func AllowAny

func AllowAny(_ Subsystem, _ Path, _ error) error

AllowAny allows any subsystem errors to be skipped

func IgnoreModules

func IgnoreModules(names ...string) func(*memoryController)

IgnoreModules configure the memory controller to not read memory metrics for some module names (e.g. passing "memsw" would avoid all the memory.memsw.* entries)

func IgnoreNotExist

func IgnoreNotExist(err error) error

IgnoreNotExist ignores any errors that are for not existing files

func NewBlkio

func NewBlkio(root string, options ...func(controller *blkioController)) *blkioController

NewBlkio returns a Blkio controller given the root folder of cgroups. It may optionally accept other configuration options, such as ProcRoot(path)

func NewCpu

func NewCpu(root string) *cpuController

func NewCpuacct

func NewCpuacct(root string) *cpuacctController

func NewCpuset

func NewCpuset(root string) *cpusetController

func NewDevices

func NewDevices(root string) *devicesController

func NewFreezer

func NewFreezer(root string) *freezerController

func NewHugetlb

func NewHugetlb(root string) (*hugetlbController, error)

func NewMemory

func NewMemory(root string, options ...func(*memoryController)) *memoryController

NewMemory returns a Memory controller given the root folder of cgroups. It may optionally accept other configuration options, such as IgnoreModules(...)

func NewNamed

func NewNamed(root string, name Name) *namedController

func NewNetCls

func NewNetCls(root string) *netclsController

func NewNetPrio

func NewNetPrio(root string) *netprioController

func NewPids

func NewPids(root string) *pidsController

func NewRdma

func NewRdma(root string) *rdmaController

func OptionalSwap

func OptionalSwap() func(*memoryController)

OptionalSwap allows the memory controller to not fail if cgroups is not accounting Swap memory (there are no memory.memsw.* entries)

func ParseCgroupFile added in v1.0.2

func ParseCgroupFile(path string) (map[string]string, error)

ParseCgroupFile parses the given cgroup file, typically /proc/self/cgroup or /proc/<pid>/cgroup, into a map of subsystems to cgroup paths, e.g.

"cpu": "/user.slice/user-1000.slice"
"pids": "/user.slice/user-1000.slice"

etc.

The resulting map does not have an element for cgroup v2 unified hierarchy. Use ParseCgroupFileUnified to get the unified path.

func ParseCgroupFileUnified added in v1.0.4

func ParseCgroupFileUnified(path string) (map[string]string, string, error)

ParseCgroupFileUnified returns legacy subsystem paths as the first value, and returns the unified path as the second value.

func ProcRoot

func ProcRoot(path string) func(controller *blkioController)

ProcRoot overrides the default location of the "/proc" filesystem

func RequireDevices

func RequireDevices(s Subsystem, _ Path, _ error) error

RequireDevices requires the device subsystem but no others

func RootPath

func RootPath(subsystem Name) (string, error)

func RunningInUserNS

func RunningInUserNS() bool

RunningInUserNS detects whether we are currently running in a user namespace. Copied from github.com/lxc/lxd/shared/util.go

Types

type CGMode

type CGMode int

CGMode is the cgroups mode of the host system

const (
	// Unavailable cgroup mountpoint
	Unavailable CGMode = iota
	// Legacy cgroups v1
	Legacy
	// Hybrid with cgroups v1 and v2 controllers mounted
	Hybrid
	// Unified with only cgroups v2 mounted
	Unified
)

func Mode

func Mode() CGMode

Mode returns the cgroups mode running on the host

type Cgroup

type Cgroup interface {
	// New creates a new cgroup under the calling cgroup
	New(string, *specs.LinuxResources) (Cgroup, error)
	// Add adds a process to the cgroup (cgroup.procs). Without additional arguments,
	// the process is added to all the cgroup subsystems. When giving Add a list of
	// subsystem names, the process is only added to those subsystems, provided that
	// they are active in the targeted cgroup.
	Add(Process, ...Name) error
	// AddProc adds the process with the given id to the cgroup (cgroup.procs).
	// Without additional arguments, the process with the given id is added to all
	// the cgroup subsystems. When giving AddProc a list of subsystem names, the process
	// id is only added to those subsystems, provided that they are active in the targeted
	// cgroup.
	AddProc(uint64, ...Name) error
	// AddTask adds a process to the cgroup (tasks). Without additional arguments, the
	// task is added to all the cgroup subsystems. When giving AddTask a list of subsystem
	// names, the task is only added to those subsystems, provided that they are active in
	// the targeted cgroup.
	AddTask(Process, ...Name) error
	// Delete removes the cgroup as a whole
	Delete() error
	// MoveTo moves all the processes under the calling cgroup to the provided one
	// subsystems are moved one at a time
	MoveTo(Cgroup) error
	// Stat returns the stats for all subsystems in the cgroup
	Stat(...ErrorHandler) (*v1.Metrics, error)
	// Update updates all the subsystems with the provided resource changes
	Update(resources *specs.LinuxResources) error
	// Processes returns all the processes in a select subsystem for the cgroup
	Processes(Name, bool) ([]Process, error)
	// Tasks returns all the tasks in a select subsystem for the cgroup
	Tasks(Name, bool) ([]Task, error)
	// Freeze freezes or pauses all processes inside the cgroup
	Freeze() error
	// Thaw thaw or resumes all processes inside the cgroup
	Thaw() error
	// OOMEventFD returns the memory subsystem's event fd for OOM events
	OOMEventFD() (uintptr, error)
	// RegisterMemoryEvent returns the memory subsystems event fd for whatever memory event was
	// registered for. Can alternatively register for the oom event with this method.
	RegisterMemoryEvent(MemoryEvent) (uintptr, error)
	// State returns the cgroups current state
	State() State
	// Subsystems returns all the subsystems in the cgroup
	Subsystems() []Subsystem
}

Cgroup handles interactions with the individual groups to perform actions on them as them main interface to this cgroup package

func Load

func Load(hierarchy Hierarchy, path Path, opts ...InitOpts) (Cgroup, error)

Load will load an existing cgroup and allow it to be controlled All static path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name

func New

func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources, opts ...InitOpts) (Cgroup, error)

New returns a new control via the cgroup cgroups interface

type ErrorHandler

type ErrorHandler func(err error) error

ErrorHandler is a function that handles and acts on errors

type EventNotificationMode

type EventNotificationMode string

EventNotificationMode corresponds to the notification modes for the memory cgroups pressure level notifications.

const (
	DefaultMode   EventNotificationMode = "default"
	LocalMode     EventNotificationMode = "local"
	HierarchyMode EventNotificationMode = "hierarchy"
)

There are three optional modes that specify different propagation behavior:

  • "default": this is the default behavior specified above. This mode is the same as omitting the optional mode parameter, preserved by backwards compatibility.
  • "hierarchy": events always propagate up to the root, similar to the default behavior, except that propagation continues regardless of whether there are event listeners at each level, with the "hierarchy" mode. In the above example, groups A, B, and C will receive notification of memory pressure.
  • "local": events are pass-through, i.e. they only receive notifications when memory pressure is experienced in the memcg for which the notification is registered. In the above example, group C will receive notification if registered for "local" notification and the group experiences memory pressure. However, group B will never receive notification, regardless if there is an event listener for group C or not, if group B is registered for local notification. "https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt" Section 11

type Hierarchy

type Hierarchy func() ([]Subsystem, error)

Hierarchy enables both unified and split hierarchy for cgroups

func SingleSubsystem

func SingleSubsystem(baseHierarchy Hierarchy, subsystem Name) Hierarchy

SingleSubsystem returns a single cgroup subsystem within the base Hierarchy

type InitCheck

type InitCheck func(Subsystem, Path, error) error

InitCheck allows subsystems errors to be checked when initialized or loaded

type InitConfig

type InitConfig struct {
	// InitCheck can be used to check initialization errors from the subsystem
	InitCheck InitCheck
}

InitConfig provides configuration options for the creation or loading of a cgroup and its subsystems

type InitOpts

type InitOpts func(*InitConfig) error

InitOpts allows configuration for the creation or loading of a cgroup

type MemoryEvent

type MemoryEvent interface {
	Arg() string
	EventFile() string
}

MemoryEvent is an interface that V1 memory Cgroup notifications implement. Arg returns the file name whose fd should be written to "cgroups.event_control". EventFile returns the name of the file that supports the notification api e.g. "memory.usage_in_bytes".

func MemoryPressureEvent

func MemoryPressureEvent(pressureLevel MemoryPressureLevel, hierarchy EventNotificationMode) MemoryEvent

MemoryPressureEvent returns a new memory pressure event to be used with RegisterMemoryEvent.

func MemoryThresholdEvent

func MemoryThresholdEvent(threshold uint64, swap bool) MemoryEvent

MemoryThresholdEvent returns a new memory threshold event to be used with RegisterMemoryEvent. If swap is true, the event will be registered using memory.memsw.usage_in_bytes

func OOMEvent

func OOMEvent() MemoryEvent

OOMEvent returns a new oom event to be used with RegisterMemoryEvent.

type MemoryPressureLevel

type MemoryPressureLevel string

MemoryPressureLevel corresponds to the memory pressure levels defined for memory cgroups.

const (
	LowPressure      MemoryPressureLevel = "low"
	MediumPressure   MemoryPressureLevel = "medium"
	CriticalPressure MemoryPressureLevel = "critical"
)

The three memory pressure levels are as follows.

  • The "low" level means that the system is reclaiming memory for new allocations. Monitoring this reclaiming activity might be useful for maintaining cache level. Upon notification, the program (typically "Activity Manager") might analyze vmstat and act in advance (i.e. prematurely shutdown unimportant services).
  • The "medium" level means that the system is experiencing medium memory pressure, the system might be making swap, paging out active file caches, etc. Upon this event applications may decide to further analyze vmstat/zoneinfo/memcg or internal memory usage statistics and free any resources that can be easily reconstructed or re-read from a disk.
  • The "critical" level means that the system is actively thrashing, it is about to out of memory (OOM) or even the in-kernel OOM killer is on its way to trigger. Applications should do whatever they can to help the system. It might be too late to consult with vmstat or any other statistics, so it is advisable to take an immediate action. "https://www.kernel.org/doc/Documentation/cgroup-v1/memory.txt" Section 11

type Name

type Name string

Name is a typed name for a cgroup subsystem

const (
	Devices   Name = "devices"
	Hugetlb   Name = "hugetlb"
	Freezer   Name = "freezer"
	Pids      Name = "pids"
	NetCLS    Name = "net_cls"
	NetPrio   Name = "net_prio"
	PerfEvent Name = "perf_event"
	Cpuset    Name = "cpuset"
	Cpu       Name = "cpu"
	Cpuacct   Name = "cpuacct"
	Memory    Name = "memory"
	Blkio     Name = "blkio"
	Rdma      Name = "rdma"
)
const (
	SystemdDbus Name = "systemd"
)

func Subsystems

func Subsystems() []Name

Subsystems returns a complete list of the default cgroups available on most linux systems

type Path

type Path func(subsystem Name) (string, error)

func NestedPath

func NestedPath(suffix string) Path

NestedPath will nest the cgroups based on the calling processes cgroup placing its child processes inside its own path

func PidPath

func PidPath(pid int) Path

PidPath will return the correct cgroup paths for an existing process running inside a cgroup This is commonly used for the Load function to restore an existing container

func Slice

func Slice(slice, name string) Path

func StaticPath

func StaticPath(path string) Path

StaticPath returns a static path to use for all cgroups

type PerfEventController

type PerfEventController struct {
	// contains filtered or unexported fields
}

func NewPerfEvent

func NewPerfEvent(root string) *PerfEventController

func (*PerfEventController) Name

func (p *PerfEventController) Name() Name

func (*PerfEventController) Path

func (p *PerfEventController) Path(path string) string

type Process

type Process struct {
	// Subsystem is the name of the subsystem that the process / task is in.
	Subsystem Name
	// Pid is the process id of the process / task.
	Pid int
	// Path is the full path of the subsystem and location that the process / task is in.
	Path string
}

type State

type State string

State is a type that represents the state of the current cgroup

const (
	Unknown  State = ""
	Thawed   State = "thawed"
	Frozen   State = "frozen"
	Freezing State = "freezing"
	Deleted  State = "deleted"
)

type Subsystem

type Subsystem interface {
	Name() Name
}

func Systemd

func Systemd() ([]Subsystem, error)

func V1

func V1() ([]Subsystem, error)

V1 returns all the groups in the default cgroups mountpoint in a single hierarchy

type SystemdController

type SystemdController struct {
	// contains filtered or unexported fields
}

func NewSystemd

func NewSystemd(root string) (*SystemdController, error)

func (*SystemdController) Create

func (s *SystemdController) Create(path string, _ *specs.LinuxResources) error

func (*SystemdController) Delete

func (s *SystemdController) Delete(path string) error

func (*SystemdController) Name

func (s *SystemdController) Name() Name

type Task

type Task = Process

Directories

Path Synopsis
cmd module
stats
v1
v2

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL