Im ersten Teil dieser Serie haben wir erklärt, warum wir die Leerlaufkapazität unseres Entwicklungsservers für BOINC nutzen – und welche Projekte wir damit unterstützen. Dieser Teil ist das technische Gegenstück: wie die Einrichtung am Webserver konkret aussieht, welche Konfigurationsentscheidungen wir getroffen haben – und was schiefgelaufen ist, bevor das Setup wirklich stabil war.
Der Server
Wir arbeiten auf einem Server mit 8 vCPU, 16 GB RAM, Ubuntu 24.04 Noble. Der Server ist ausschließlich für interne Web-Entwicklung im Einsatz (Plesk-Oberfläche, hauptsächlich WordPress-Entwicklung) – kein Kundenproduktivbetrieb. Das ist die Voraussetzung dafür, dass BOINC überhaupt in Frage kommt: Ressourcen, die wir freigeben, müssen jederzeit wieder vollständig für Entwicklungsaufgaben verfügbar sein.
Installation
BOINC ist in den Ubuntu-Paketquellen verfügbar:
sudo apt update
sudo apt install boinc-client
Der Dienst startet danach automatisch. Projekte werden über die Weboberfläche der jeweiligen Plattform verwaltet: Account anlegen, Account-Key erhalten, Client verbinden:
boinccmd --project_attach https://climateprediction.net
Aktuell laufen bei uns vier Projekte: Climate Prediction, World Community Grid (Projekt MCM1, Krebsforschung), Rosetta@home und Einstein@home. Im Vergleich zum ersten Teil ist Rosetta@home neu dazugekommen.
Das Ressourcenproblem
BOINC hat eigene Konfigurationsmöglichkeiten für CPU- und RAM-Nutzung, aber die Standardwerte sind für einen Server im Entwicklungsbetrieb nicht geeignet. Ohne Einschränkungen würde BOINC alle verfügbaren Ressourcen nutzen – das ist das Designziel für Desktop-Systeme, auf einem geteilten Server aber inakzeptabel.
Unsere Anforderung: BOINC darf tagsüber an Werktagen nur wenig CPU nutzen, nachts und am Wochenende deutlich mehr – aber nie so viel, dass der Server bei einer plötzlichen Entwicklungsaufgabe ins Stocken gerät. Dafür braucht es zwei Dinge: BOINC-eigene Prefs, die der Software mitteilen, wie viel sie beanspruchen darf, und ein systemd-cgroup-Limit als hartes Sicherheitsnetz darunter.
Schicht 1: BOINC-Prefs und Zeitprofile
BOINC liest seine Ressourcenlimits aus einer XML-Datei (global_prefs_override.xml) im Datenverzeichnis. Wir pflegen drei solche Dateien in /etc/boinc-prefs/ und tauschen sie automatisch per Cron-Script.
Tagesprofil (Mo–Fr, 07–21 Uhr)
/etc/boinc-prefs/prefs-day.xml:
<global_preferences>
<max_ncpus_pct>25.000000</max_ncpus_pct>
<cpu_usage_limit>75.000000</cpu_usage_limit>
<suspend_cpu_usage>30.000000</suspend_cpu_usage>
<ram_max_used_busy_frac>0.03</ram_max_used_busy_frac>
<ram_max_used_idle_frac>0.06</ram_max_used_idle_frac>
<disk_max_used_gb>10.000000</disk_max_used_gb>
<disk_min_free_gb>20.000000</disk_min_free_gb>
<max_bytes_sec_up>500000</max_bytes_sec_up>
<max_bytes_sec_down>500000</max_bytes_sec_down>
</global_preferences>
max_ncpus_pct=25 entspricht bei acht Kernen etwa zwei Kernen. suspend_cpu_usage=30 sorgt dafür, dass BOINC pausiert, sobald der Server insgesamt über 30 % Last hat – ein weiterer Puffer gegen unerwartete Konkurrenz.
Nacht- und Wochendprofil
/etc/boinc-prefs/prefs-night.xml und prefs-weekend.xml sind identisch:
<global_preferences>
<max_ncpus_pct>70.000000</max_ncpus_pct>
<cpu_usage_limit>75.000000</cpu_usage_limit>
<suspend_cpu_usage>30.000000</suspend_cpu_usage>
<ram_max_used_busy_frac>0.06</ram_max_used_busy_frac>
<ram_max_used_idle_frac>0.12</ram_max_used_idle_frac>
<disk_max_used_gb>10.000000</disk_max_used_gb>
<disk_min_free_gb>20.000000</disk_min_free_gb>
<max_bytes_sec_up>500000</max_bytes_sec_up>
<max_bytes_sec_down>500000</max_bytes_sec_down>
</global_preferences>
70 % von acht Kernen sind knapp 5,5 Kerne – deutlich mehr Rechenkapazität für die Projekte, wenn niemand aktiv am Server arbeitet.
Das Switch-Script
Der Wechsel zwischen den Profilen übernimmt /usr/local/bin/boinc-switch-prefs.sh:
#!/bin/bash
BOINC_DIR="/var/lib/boinc-client"
PREFS_DIR="/etc/boinc-prefs"
HOUR=$(date +%H)
DAY=$(date +%u) # 1=Mo, 7=So
if [ "$DAY" -ge 6 ]; then
SRC="weekend"
elif [ "$HOUR" -ge 21 ] || [ "$HOUR" -lt 7 ]; then
SRC="night"
else
SRC="day"
fi
cp "$PREFS_DIR/prefs-$SRC.xml" "$BOINC_DIR/global_prefs_override.xml"
chown boinc:boinc "$BOINC_DIR/global_prefs_override.xml"
boinccmd --read_global_prefs_override
Das Script ermittelt den aktuellen Zeitkontext, kopiert die passende Prefs-Datei und weist BOINC an, sie sofort einzulesen. Ausgelöst wird es per Cron:
0 7 * * 1-5 /usr/local/bin/boinc-switch-prefs.sh # Mo–Fr Tagprofil
0 21 * * 1-5 /usr/local/bin/boinc-switch-prefs.sh # Mo–Fr Nachtprofil
0 0 * * 6 /usr/local/bin/boinc-switch-prefs.sh # Sa 00:00 Wochenende
0 7 * * 1 /usr/local/bin/boinc-switch-prefs.sh # Mo 07:00 zurück auf Tag
Schicht 2: systemd cgroup als hartes Limit
Die BOINC-Prefs sind eine Kooperationsabsprache: BOINC hält sich daran, solange die Software korrekt funktioniert. Als harte Grenze, die unabhängig vom Verhalten des BOINC-Clients greift, haben wir ein systemd-Drop-in eingerichtet.
/etc/systemd/system/boinc-client.service.d/limits.conf:
[Service]
CPUQuota=75%
MemoryMax=8G
IOWeight=10
CPUQuota=75% entspricht maximal 6 der 8 Kerne, unabhängig davon, was BOINC intern berechnet. MemoryMax=8G ist das Speicherlimit auf cgroup-Ebene – der Kernel beendet BOINC-Prozesse, bevor sie diese Grenze überschreiten. IOWeight=10 gibt dem Dienst sehr niedrige I/O-Priorität, sodass Festplattenzugriffe durch Deployments oder Datenbankoperationen nie durch BOINC blockiert werden.
Nach Änderungen an dieser Datei:
sudo systemctl daemon-reload
sudo systemctl restart boinc-client
Ein Fallstrick mit RAM-Fraktionen
Bevor das Setup stabil lief, hatten wir Probleme mit OOM-Kills: Einstein@home wurde mitten in der Nacht vom Kernel beendet. Die Konfiguration schien korrekt zu sein – der Fehler lag tiefer.
ram_max_used_busy_frac und ram_max_used_idle_frac in den BOINC-Prefs sind keine absoluten Megabyte-Werte. Sie sind Bruchteile des Gesamt-RAMs des Systems. Bei 16 GB und einem zu hoch angesetzten Wert hatte BOINC sich selbst ein Working Set von knapp 4 GB erlaubt – mehr als das damalige cgroup-Limit hergab. Der Kernel hat den Prozess gekillt.
Die Lösung hat zwei Teile: MemoryMax auf 8G angehoben, und die ram_max_used_*_frac-Werte konservativ gesetzt – niedrig genug, dass BOINC sich selbst weniger erlaubt als das cgroup-Limit hergibt.
Die Prefs sind die erste Schicht: BOINC soll gar nicht erst versuchen, mehr RAM zu nutzen als vorgesehen. Das cgroup-Limit ist die zweite: Wenn BOINC sich durch ein Update, einen Konfigurationsfehler oder eine unerwartet speicherhungrige Work-Unit trotzdem mehr nimmt, greift der Kernel ein, bevor der Rest des Servers betroffen ist.
Zum Anschauungsbeispiel mit den aktuellen Werten: Bei 16 GB Gesamt-RAM und ram_max_used_idle_frac=0.06 erlaubt BOINC sich im Leerlauf maximal 0,06 × 16.384 MB = ~983 MB. Mit ram_max_used_busy_frac=0.03 sind es unter Last ~491 MB. Beides liegt deutlich unter dem cgroup-Limit von 8G – und genau das ist der Punkt.
Das Setup läuft seitdem ohne Probleme. BOINC wechselt automatisch zwischen den Profilen, die systemd cgroup verhindert unkontrolliertes Speicherwachstum, und die Ressourcen für Entwicklungsaufgaben bleiben unangetastet.
