This episode teaches container resource limiting via cgroup2: lxc.cgroup2.memory.max for memory and lxc.cgroup2.cpu.max for CPU, plus verification with lxc-cgroup (legacy) and systemd-cgls on the host.

In episode 6 your container has networking. But what stops one container from consuming all 32 GB of host RAM? The answer: cgroups. In episode 7 we set resource limits via cgroup2 — the concept we introduced in episode 2 — then verify them with LXC's built-in tools and the host system. Without limits, a single memory-leaking application can bring down the entire host.
cgroups are the electricity meter per unit in our building: namespaces limit "what you can see", cgroups limit "what you're allowed to use". Without cgroups, the misbehavior of one container (full CPU loop, memory leak) will disrupt all other tenants. With proper limits:
Modern LXC uses cgroup2, and limits are written directly into the container config with the lxc.cgroup2. prefix. The container config file lives at /var/lib/lxc/<name>/config. Here's a complete example for container c1:
# Memory limit: max 512MB
lxc.cgroup2.memory.max = 512M
# CPU limit: 200000/100000 = 2 full cores
lxc.cgroup2.cpu.max = 200000 100000
# Tell the kernel to keep swappiness low for the container
lxc.cgroup2.memory.swap.max = 0
# I/O priority (0-10000), the smaller the more prioritized
lxc.cgroup2.io.weight = 100Let's break down each line:
lxc.cgroup2.memory.max = 512M — the main memory limit. If the container exceeds it, the kernel will apply pressure or OOM-kill processes inside. Units can be K, M, G, or raw byte numbers.lxc.cgroup2.cpu.max = 200000 100000 — format is <quota> <period> in microseconds. 200000/100000 means 2 cores; 50000/100000 means half a core.lxc.cgroup2.memory.swap.max = 0 — disables swap for the container, making the memory limit stricter.lxc.cgroup2.io.weight = 100 — scale 1-10000; affects how large a share of block I/O bandwidth the container gets relative to other containers.Tip
cgroup2 key names differ from cgroup v1. In v1 you'd write lxc.cgroup.memory.limit_in_bytes; in v2 it becomes lxc.cgroup2.memory.max. On LXC 7.0 with a modern kernel, use the cgroup2 variants — they're cleaner and fully supported by systemd.
After editing the config, restart the container so the limits take effect:
lxc-stop -n c1
lxc-start -n c1The lxc-cgroup tool lets you view and change container cgroup values directly. Read the current values:
lxc-cgroup -n c1 memory.max
lxc-cgroup -n c1 cpu.maxWarning
lxc-cgroup is considered legacy and only recognizes cgroup v1 key names. On LXC 7.0 it still exists for compatibility, but the primary verification below (systemd-cgls) is more accurate and is the standard on cgroup2.
The most reliable way is to view the cgroup hierarchy directly from the host. Find the container in the systemd tree:
systemd-cgls /lxc/c1You can also read the cgroup files directly:
cat /sys/fs/cgroup/lxc/c1/memory.max
cat /sys/fs/cgroup/lxc/c1/cpu.maxIf the numbers read match what you configured, the limits are in effect.
The best proof is an experiment. Enter the container and try to allocate more memory than the limit:
lxc-attach -n c1 -- dd if=/dev/zero of=/dev/null bs=1M count=10000With a 512M limit, this process will be OOM-killed or pressured — while the host stays healthy. On the CPU side:
lxc-attach -n c1 -- sh -c 'while :; do :; done &'Monitor CPU usage from the host with top and systemd-cgtop:
systemd-cgtopThe container's CPU will be locked to its allocation (e.g. 200%), no more.
Warning
Remember to kill the test processes above (lxc-stop -n c1 or kill from inside the container). A CPU-burning process left running will permanently consume the container's CPU quota and can slow down all other workloads in the same container.
Practical planning rules:
cpu.max if workloads are bursty and complementary.500M vs 500m) can produce unexpected numbers.Key takeaways:
lxc.cgroup2.memory.max and lxc.cgroup2.cpu.max are the main keys in the container config.lxc-cgroup is a legacy tool; systemd-cgls, systemd-cgtop, and files in /sys/fs/cgroup are the modern verification.dd for memory, a loop for CPU.In the next episode 8 we'll cover storage: rootfs, images & snapshots — the dir, btrfs, zfs, LVM, and loop backends along with lxc-create --bdev/--fstype, plus the role of the download template, lxc-copy, and lxc-snapshot in image management.