Nasazení bez výpadku s Nginx a Systemd
Průvodce krok za krokem k dosažení skutečného nasazení bez výpadku pomocí přepínání upstream v Nginx a socket aktivace systemd – bez Kubernetes.
Nasazení bez výpadku jsou často prezentována jako schopnost výhradně pro Kubernetes. Nejsou. S Nginx jako reverzním proxy a socket aktivací systemd můžete dosáhnout skutečných aktualizací aplikací bez výpadku na jednom serveru bez orchestrátoru kontejnerů – a přesně pochopit, co se děje v každém kroku.
Základní myšlenka
Strategie má dvě části: (1) spustit dvě verze vaší aplikace současně po krátkou dobu během nasazení a (2) použít Nginx k atomickému přesunu provozu ze staré verze na novou. Socket aktivace systemd zajišťuje, že nová připojení jsou pozastavena – ne zahozena – během přepínání.
Krok 1: Socket aktivace Systemd
Socket aktivace umožňuje systemd vlastnit naslouchající socket. Když se vaše aplikace restartuje, socket zůstane otevřený – příchozí připojení se řadí do fronty v jádře – a jsou předána novému procesu, jakmile je připraven. Žádná připojení nejsou odmítnuta.
# /etc/systemd/system/myapp.socket
[Unit]
Description=MyApp socket
[Socket]
ListenStream=127.0.0.1:3000
Accept=no
[Install]
WantedBy=sockets.target# /etc/systemd/system/myapp.service
[Unit]
Description=MyApp application server
Requires=myapp.socket
After=myapp.socket
[Service]
ExecStart=/usr/bin/node /srv/myapp/current/server.js
WorkingDirectory=/srv/myapp/current
User=myapp
Group=myapp
Restart=on-failure
# Tell the service to use the socket passed by systemd
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.targetKrok 2: Konfigurace Nginx upstream
# /etc/nginx/conf.d/myapp.conf
upstream myapp {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://myapp;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Allow Nginx to hold connections briefly during restart
proxy_next_upstream error timeout;
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
}
}Krok 3: Deployment skript
#!/bin/bash
# deploy.sh — zero-downtime deployment
set -euo pipefail
APP_DIR=/srv/myapp
RELEASE=$(date +%Y%m%d%H%M%S)
RELEASE_DIR="$APP_DIR/releases/$RELEASE"
echo "==> Creating release directory: $RELEASE_DIR"
mkdir -p "$RELEASE_DIR"
echo "==> Pulling latest code"
git clone --depth 1 git@github.com:yourorg/myapp.git "$RELEASE_DIR"
echo "==> Installing dependencies"
cd "$RELEASE_DIR"
npm ci --production
echo "==> Running database migrations"
npm run migrate
echo "==> Switching symlink atomically"
ln -sfn "$RELEASE_DIR" "$APP_DIR/current"
echo "==> Reloading application (socket remains open)"
# systemd will restart the service while keeping the socket alive
systemctl reload-or-restart myapp.service
echo "==> Verifying health check"
sleep 2
curl -sf http://127.0.0.1:3000/health || { echo "Health check failed!"; exit 1; }
echo "==> Cleaning up old releases (keeping last 5)"
ls -dt "$APP_DIR/releases"/* | tail -n +6 | xargs rm -rf
echo "==> Deployment complete: $RELEASE"Klíčem je ln -sfn, který atomicky nahrazuje symbolický odkaz. Od okamžiku změny symbolického odkazu budou všechny nové worker procesy spuštěné systemd obsluhovat nový kód. Stávající požadavky v průběhu zpracování pokračují na starých workerech, dokud neskončí.
Krok 4: Ověření nulového výpadku
# Run this in a second terminal while deploying
# It will report immediately if any request fails
while true; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://example.com/health)
echo "$(date +%H:%M:%S) — HTTP $STATUS"
sleep 0.2
doneMěli byste vidět nepřetržitý proud řádků „HTTP 200" – i během nasazení. Pokud uvidíte 502 nebo 503, zkontrolujte nastavení proxy_next_upstream a ujistěte se, že vaše aplikace začne rychle přijímat připojení (v rámci okna proxy_connect_timeout).
Kdy přejít na Kubernetes
Tento přístup funguje výborně pro týmy provozující jeden až několik serverů s jednou aplikací. Když potřebujete multi-node nasazení, automatické horizontální škálování nebo komplexní service meshe, Kubernetes si svoji komplexnost zaslouží. Do té doby je Nginx + systemd jednodušší, rychlejší pro ladění a nevyžaduje žádný cluster k údržbě.