Blog

  • Home
  • Posts
docker_load_average

Po přesunu cron úloh do Docker kontejnerů jsme zaznamenali výrazné přetížení serveru. Počet a logika úloh se nezměnily – změnil se jen způsob jejich spouštění. To nás přimělo k hlubšímu zkoumání příčin. 

Hledání příčiny

Nejprve jsme nastavili monitoring spotřeby zdrojů podle procesů. Nasadili jsme process-exporter a připravili samostatný dashboard. Snažili jsme se odlišit zdroje zátěže podle:

  1. Python procesů
  2. docker-compose procesů
  3. Procesů spojených s Docker shim

Data ukázala, že hlavním zdrojem zátěže byly Python procesy. Docker procesy samy o sobě velkou zátěž nevytvářely. Otázka ale zůstávala – proč se přetížení objevilo až po přechodu na Docker-based crony?

Formulace hypotéz

Podezírali jsme dvě hlavní příčiny:

  • process-exporter mohl mít příliš nízkou frekvenci vzorkování, nebo sám vytvářel vysokou zátěž (prochází celý /proc, který během burstů může obsahovat přes 5 000 PIDů)
  • Způsob startu Docker kontejnerů mohl skrývat reálný overhead: kontejner připravuje runc init, následuje řada systémových operací před spuštěním cílového příkazu. Tyto krátkodobé špičky nemusí být běžným monitoringem zachyceny.

Původní cron konfigurace

Před optimalizací byly cron úlohy spouštěny takto:

docker-compose run --rm app python script.py arguments

Každá úloha vytvořila nový kontejner, který byl po dokončení odstraněn.

Optimalizace

Zavedli jsme perzistentní kontejner běžící na pozadí:

docker-compose run --rm -d --name cron-runner app bash -c "while :; do sleep 60; done"

A změnili jsme cron tak, aby spouštěl příkazy přes docker exec do existujícího kontejneru:

docker exec cron-runner python script.py arguments

Výsledky

Průměrné zatížení

Po přechodu na docker exec průměrné zatížení výrazně kleslo. Na grafu z 11. března 2025 (06:00–22:00) je patrný pokles po ~15:50, kdy došlo ke změně.

Využití CPU

Zátěž CPU se změnila z plošné na „pichlavou“ – vyšší, ale krátké špičky namísto širokých, nízkých vln. To znamená efektivnější využití procesoru.

Pokles IO

Také se snížila zátěž na disk v intervalu 14:00–18:00.

Analýza

Overhead nebyl způsoben samotným Dockerem, ale nesprávným použitím. Každý docker-compose run prováděl:

  • nový proces runc
  • vytvoření namespace
  • mount přes overlayfs
  • forkování a konfiguraci
  • spuštění cílového příkazu přes exec

Všechny tyto kroky konzumují systémové prostředky ještě před tím, než dojde ke spuštění samotné úlohy.

Závěr

Pokud zaznamenáte přetížení serveru po dockerizaci cron úloh, zvažte vyhnutí se docker run nebo docker-compose run pro každou jednotlivou úlohu. Místo toho použijte dlouhodobě běžící kontejner a docker exec. Tím se výrazně sníží overhead a zlepší efektivita CPU a IO.

Doporučené čtení