Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Resource Capping

A misbehaving application should not be able to take a node down with it. The agent puts every object it starts in its own cgroup, and the pg_* keywords turn that into a limit.

The slice an object runs in

Starting an instance builds a hierarchy under opensvc.slice, one level per scope:

opensvc.slice
└ opensvc-ns.<namespace>.slice
  └ opensvc-ns.<namespace>-svc.<name>.slice
    └ opensvc-ns.<namespace>-svc.<name>-app.1.slice

A resource’s processes live in its own leaf, inside its object, inside its namespace. That nesting is what makes a limit set at any level apply to everything below it.

Capping an object

[DEFAULT]
pg_cpus = 0
pg_mem_limit = 256m

Starting the instance logs what it applied:

INF myapp: applied pg /opensvc.slice/...-svc.myapp.slice: cpus=0 mem_limit=256m
INF myapp: app#1: run: om exec --pg /opensvc.slice/...-svc.myapp-app.1.slice -- ...

And the kernel agrees:

$ cat /sys/fs/cgroup/opensvc.slice/.../opensvc-svc.myapp.slice/memory.max
268435456
$ cat /sys/fs/cgroup/opensvc.slice/.../opensvc-svc.myapp.slice/cpuset.cpus
0

The keywords are the usual cgroup controls:

KeywordCaps
pg_cpusthe cpus the object may run on, as a list or range: 0,1,2 or 0-2
pg_memsthe memory nodes it may allocate from, same syntax
pg_cpu_sharesits share of cpu when the node is cpu-bound, relative to other objects
pg_cpu_quotaits cpu time whether or not the node is busy: 50%, 50%@all, 10%@2
pg_cpu_coresa guaranteed cpu time reservation, in ms per period
pg_mem_limitresident memory, in bytes. Exceeding it wakes the OOM killer
pg_vmem_limitmemory plus swap
pg_mem_oom_control0 lets the OOM killer run, 1 freezes the group instead
pg_mem_swappinesshow readily its pages are swapped
pg_blkio_weightits share of block io, between 10 and 1000

pg_cpu_shares and pg_cpu_quota are the pair worth telling apart: shares only arbitrate a contended cpu, whereas a quota caps the group on an idle node too.

Capping a resource

The same keywords set on a resource cap that resource alone, which is how a sidecar is kept from starving the process it assists:

[app#1]
type = simple
start = /opt/myapp/bin/server

[app#2]
type = simple
start = /opt/myapp/bin/indexer
pg_cpu_shares = 128

Capping a namespace

An nscfg object holds the defaults of its namespace, the pg_* keywords among them:

om test/nscfg/namespace create --kw pg_mem_limit=4g

Every object in test is then capped by it, no matter who created it, which is how a namespace is handed to a team without handing them the node.

Turning it off

[DEFAULT]
create_pg = false

Grouping is on by default. Turning it off leaves the processes ungrouped and uncapped, and is worth doing only where the cgroup itself causes the problem.

➡️ See Also