cgroups (Control Groups) ermöglichen die Kontrolle von Ressourcen für Prozessgruppen unter Linux. Sie sind die Grundlage für Container-Technologien wie Docker.
Grundlagen
cgroups v1 vs v2
| Feature | v1 | v2 | |---------|----|----| | Hierarchie | Mehrere | Eine einheitliche | | Struktur | Pro Controller | Vereinheitlicht | | Standard | Älter | Modern (ab Kernel 4.5) |
Version prüfen
# v2 wenn unified
mount | grep cgroup
# Oder
cat /proc/filesystems | grep cgroupVerfügbare Controller
# cgroups v2
cat /sys/fs/cgroup/cgroup.controllers
# Ausgabe: cpu io memory pidscgroups v2 - Systemd
Slice-Hierarchie
# Struktur anzeigen
systemd-cgls
# Ausgabe:
# ├─user.slice
# │ └─user-1000.slice
# │ └─session-1.scope
# ├─system.slice
# │ ├─nginx.service
# │ └─mysql.service
# └─init.scopeService-Limits mit Systemd
# /etc/systemd/system/myapp.service.d/limits.conf
[Service]
# CPU: 50% eines Cores
CPUQuota=50%
# Memory: Max 1GB
MemoryMax=1G
MemoryHigh=800M
# I/O: Gewichtung
IOWeight=50
# Prozesse: Max 100
TasksMax=100systemctl daemon-reload
systemctl restart myappTemporäre Limits
# CPU-Limit setzen
systemctl set-property myapp.service CPUQuota=25%
# Memory-Limit setzen
systemctl set-property myapp.service MemoryMax=512M
# Permanent (--runtime für temporär)
systemctl set-property --runtime myapp.service CPUQuota=25%Limits anzeigen
# Service-Limits
systemctl show myapp.service | grep -E "(CPU|Memory|IO|Tasks)"
# cgroup-Pfad
systemctl show -p ControlGroup myapp.serviceManuelle cgroups v2
cgroup erstellen
# Verzeichnis erstellen
mkdir /sys/fs/cgroup/mygroup
# Controller aktivieren
echo "+cpu +memory +io +pids" > /sys/fs/cgroup/cgroup.subtree_controlCPU-Limits
# CPU-Bandwidth (Quota/Period)
# 50% CPU = 50000/100000
echo "50000 100000" > /sys/fs/cgroup/mygroup/cpu.max
# CPU-Gewichtung (1-10000, default 100)
echo 50 > /sys/fs/cgroup/mygroup/cpu.weightMemory-Limits
# Max Memory (Hard Limit)
echo 1073741824 > /sys/fs/cgroup/mygroup/memory.max # 1GB
# High Memory (Soft Limit - Drosselung)
echo 805306368 > /sys/fs/cgroup/mygroup/memory.high # 768MB
# Swap-Limit
echo 0 > /sys/fs/cgroup/mygroup/memory.swap.max
# Aktuelle Nutzung
cat /sys/fs/cgroup/mygroup/memory.currentI/O-Limits
# Device-Nummern finden
lsblk -o NAME,MAJ:MIN
# Read-Limit (Bytes/s) - z.B. 8:0 für /dev/sda
echo "8:0 rbps=10485760" > /sys/fs/cgroup/mygroup/io.max # 10MB/s
# Write-Limit
echo "8:0 wbps=5242880" > /sys/fs/cgroup/mygroup/io.max # 5MB/s
# IOPS-Limit
echo "8:0 riops=1000 wiops=500" > /sys/fs/cgroup/mygroup/io.maxProzess-Limits
# Max Prozesse/Threads
echo 50 > /sys/fs/cgroup/mygroup/pids.max
# Aktuelle Anzahl
cat /sys/fs/cgroup/mygroup/pids.currentProzess zuweisen
# PID zuweisen
echo $PID > /sys/fs/cgroup/mygroup/cgroup.procs
# Prozess mit cgroup starten
cgexec -g cpu,memory:mygroup command
# Oder mit systemd-run
systemd-run --scope -p MemoryMax=500M commandPraktische Beispiele
Datenbank-Server begrenzen
# /etc/systemd/system/mysql.service.d/limits.conf
[Service]
# 4 CPU-Cores
CPUQuota=400%
# 8GB RAM
MemoryMax=8G
MemoryHigh=7G
# Keine Swap-Nutzung
MemorySwapMax=0
# I/O-Priorität
IOWeight=200Web-Worker begrenzen
# /etc/systemd/system/php-fpm.service.d/limits.conf
[Service]
# 2 CPU-Cores
CPUQuota=200%
# 2GB RAM
MemoryMax=2G
# Max 100 Prozesse
TasksMax=100Batch-Job limitieren
#!/bin/bash
# batch-job.sh
# Eigene cgroup erstellen
CGROUP="/sys/fs/cgroup/batch-$$"
mkdir -p $CGROUP
# Limits setzen
echo "25000 100000" > $CGROUP/cpu.max # 25% CPU
echo 536870912 > $CGROUP/memory.max # 512MB RAM
# Prozess zuweisen
echo $$ > $CGROUP/cgroup.procs
# Job ausführen
./heavy-task.sh
# Aufräumen
rmdir $CGROUPMonitoring
cgroup-Statistiken
# CPU-Statistiken
cat /sys/fs/cgroup/mygroup/cpu.stat
# Memory-Statistiken
cat /sys/fs/cgroup/mygroup/memory.stat
# I/O-Statistiken
cat /sys/fs/cgroup/mygroup/io.stat
# Pressure (PSI)
cat /sys/fs/cgroup/mygroup/cpu.pressure
cat /sys/fs/cgroup/mygroup/memory.pressure
cat /sys/fs/cgroup/mygroup/io.pressuresystemd-cgtop
# Echtzeit-Monitoring
systemd-cgtop
# Sortierung ändern (während Lauf: c=CPU, m=Memory, i=I/O)Mit cgget (cgroup-tools)
# Installation
apt install cgroup-tools
# Werte lesen
cgget -g cpu,memory /mygroupContainer-Nutzung
Docker-Limits
# CPU-Limit
docker run --cpus=2 --memory=1g myimage
# CPU-Shares (relative Gewichtung)
docker run --cpu-shares=512 myimage
# Memory mit Swap
docker run --memory=1g --memory-swap=2g myimageLXC/LXD-Limits
# CPU
lxc config set container limits.cpu 2
# Memory
lxc config set container limits.memory 1GBZusammenfassung
| Controller | Datei | Beschreibung | |------------|-------|--------------| | cpu | cpu.max | CPU-Quota | | cpu | cpu.weight | CPU-Gewichtung | | memory | memory.max | Hartes Limit | | memory | memory.high | Weiches Limit | | io | io.max | I/O-Bandbreite | | pids | pids.max | Prozess-Limit |
| Systemd-Option | Beschreibung | |----------------|--------------| | CPUQuota | CPU-Prozent | | MemoryMax | RAM-Limit | | MemoryHigh | RAM-Soft-Limit | | IOWeight | I/O-Priorität | | TasksMax | Prozess-Limit |
| Befehl | Funktion | |--------|----------| | systemd-cgls | Hierarchie anzeigen | | systemd-cgtop | Echtzeit-Monitor | | systemctl set-property | Limits setzen | | cgexec | Prozess mit cgroup starten |
Fazit
cgroups sind fundamental für Ressourcen-Kontrolle unter Linux. Systemd vereinfacht die Nutzung erheblich. Container nutzen cgroups für Isolation. Für produktive Systeme sollten kritische Services Limits haben. Memory-Limits verhindern OOM-Probleme.