1. Mijn server stopt bij elke deployment – wat gaat er mis?



Als je een persoonlijk project runt,obby je al snel tegen omgevingen met beperkte resources aan, zoals de kleinste GCP‑instances of een Raspberry Pi. Ik beheer verschillende machines: van high‑end servers voor AI‑inference en training tot een schetste VM die alleen een namenservice draait. De Raspberry Pi 5 heeft een speciale plaats in mijn toolbox – hij draait 24 uur, kost bijna niets aan stroom en levert solide prestaties.

Maar door de Pi te overladen, kwam ik erachter dat bij elke deployment de CPU 100 % bereikte. De boosdoener? De Celery‑workers. Bij een traditionele Blue‑Green‑deployment worden beide omgevingen tegelijk opgestart, waardoor het aantal workers tijdelijk verdubbelt en het systeem overbelast raakt. Het verminderen van het aantal workers maakte de verwerking trager, maar het laten staan leidde tot crashes – een echte doodlopende situatie.

Illustratie van een automatiseringsscript voor low‑spec pc

Om dit op te lossen heb ik een op maat gemaakt Blue‑Green‑script ontwikkeld dat de resource‑consumptie minimaliseert en toch stabiliteit garandeert.


2. Strategie: Bespaar CPUatie, verhoog betrouwbaarheid

Een eenvoudige Blue‑Green‑deployment draait beide omgevingen tegelijk, maar ik heb de volgende stappen toegevoegd om de CPU‑belasting te verlagen:

  1. Vooraf stoppen van achtergrondservices (Celery): Stop eerst de zware taken van de oude versie (workers, beat) om CPU‑capaciteit vrij te maken voor de nieuwe web‑server.
  2. Gefaseerde opstart: Start niet alles tegelijk; breng eerst Web + Redis online en voer een health‑check uit.
  3. Human‑in‑the‑loop: Na de automatische stappen moet een beheerder visueel bevestigen dat alles in orde is voordat de oude versie definitief wordt verwijderd.

De kern van het probleem lag in de Celery‑workers: zodra ze herstarten, krijgen ze meteen een stapel taken toegewezen, waardoor de CPU direct overbelast raakt. Het verlagen van de concurrency‑instelling zou het probleem oplossen, maar dat zou de asynchrone verwerkingssnelheid tijdens de deployment onacceptabel vertragen.

Daarom bedacht ik een aanpak waarbij de bestaande Celery‑processen tijdelijk worden gepauzeerd, CPU‑capaciteit wordt vrijgemaakt en vervolgens de nieuwe code wordt uitgerold – allemaal zonder downtime.


3. Kerncode in vogelvlucht



De volledige broncode staat in mijn GitHub‑repository. Hieronder enkele belangrijke fragmenten.

① Docker‑Compose voor projectisolatie

Met de docker compose -p‑optie kun je met hetzelfde compose‑bestand twee afzonderlijke projecten (blue en green) creëren.

dc() {
  # Dynamisch project‑naam (-p) voor isolatie
  docker compose -f "$COMPOSE_FILE" "$@"
}

② Strikte health‑check

Verkeer wordt pas omgeschakeld als de nieuwe versie volledig gezond is.

health_check() {
  # Controleer 10 keer of de opgegeven poort 200 OK teruggeeft
  if curl -fsSIL --max-time "$HEALTH_TIMEOUT" "$url"; then
    ok "Health check passed"
    return 0
  fi
}

③ Fallback‑mechanisme bij fouten

Als de nieuwe versie falen vertoont, worden de gestopte services van de oude versie onmiddellijk herstart zodat de gebruiker geen onderbreking merkt. In plaats van rm -f gebruiken we stop om de Celery‑workers en beat snel weer beschikbaar te maken en CPU vrij te houden.


4. Operationele tip: "Controleer voordat je verwijdert"

Het script eindigt niet met een automatische verwijdering van de oude versie, maar toont een bericht aan de beheerder:

"Deployment geslaagd. Controleer handmatig en verwijder de oude versie met het onderstaande commando als alles in orde is."

Deze eenvoudige veiligheidsstap vangt het laatste procentje fouten op dat een geautomatiseerd systeem kan missen.


5. Afsluitende gedachten

Deze scriptbundel bevat alle overwegingen die nodig zijn om het maximale uit een beperkt resource‑budget te halen. Het is bescheiden, maar werkt uitstekend voor mij – en ik denk dat veel andere kleine ontwikkelaars met soortgelijke beperkingen er baat bij zullen hebben.

Gerelateerde links: