Skip to main content

Wdrożenie bez przestoju

DLA AGENTÓW AIChatGPTClaude

Metodologia i mechanizmy inżynieryjne aktualizacji usług produkcyjnych bez zatrzymywania obsługi użytkowników, zrywania istniejących połączeń TCP oraz generowania błędów HTTP 502/503.

1. Przegląd koncepcji i problem systemowy

Prymitywne aktualizowanie usług poprzez restart procesu (systemctl restart app lub docker restart container) prowadzi do przestoju technologicznego (Downtime). Przez 5–30 sekund, podczas których nowy proces inicjalizuje środowisko wykonania, nawiązuje połączenia z bazami danych i kompiluje kod JIT:

  • Wszystkie bieżące aktywne żądania HTTP są przerywane w połowie transferu danych.
  • Balanser obciążenia lub reverse proxy zwraca użytkownikom błędy 502 Bad Gateway lub 504 Gateway Timeout.
  • Transakcje użytkowników (płatności, zapis stanu, generowanie przez LLM) pozostają w stanie częściowego uszkodzenia.

Zero-Downtime Deployment (Wdrożenie bez przestojów) eliminuje przerwy dzięki orkiestracji cyklu życia procesów. Nowa wersja aplikacji uruchamiana jest równolegle ze starą. Ruch przekazywany jest wyłącznie po tym, gdy nowa instancja pomyślnie odpowiedziała na sondy Health Check, a stara instancja poprawnie zakończyła wszystkie rozpoczęte operacje w trybie Graceful Shutdown.

Faza 1: Aktywna wersja v1.0
[Klienci] ---> [Reverse Proxy / Nginx] ---> [Kontener v1.0 (Aktywny)]

Faza 2: Uruchomienie v1.1 i sprawdzenie stanu (healthcheck)
[Klienci] ---> [Reverse Proxy / Nginx] ---> [Kontener v1.0 (Aktywny)]
                                             [Kontener v1.1 (Uruchamianie... /healthz: 200 OK)]

Faza 3: Przełączenie ruchu i płynne zamknięcie (graceful shutdown) v1.0
[Klienci] ---> [Reverse Proxy / Nginx] ---> [Kontener v1.1 (Aktywny)]
                                       \---> [Kontener v1.0 (Kończenie aktywnych żądań... SIGTERM)]

Faza 4: Zakończenie (v1.0 wyłączony)
[Klienci] ---> [Reverse Proxy / Nginx] ---> [Kontener v1.1 (Aktywny)]

2. Taksonomia architektoniczna i model mentalny

Strategie ciągłego aktualizowania:

  1. Blue/Green Deployment:
    • Pełne podwojenie warstwy infrastrukturalnej.
    • Natychmiastowe, atomowe przełączenie ruchu na poziomie Nginx, Traefik lub DNS/ALB.
    • Najwyższa niezawodność, najprostszy rollback, ale wymaga dwukrotnego zapasu pamięci RAM i zasobów hosta.
  2. Rolling Update (Stopniowa aktualizacja przewijana):
    • Kontenery aktualizowane są sekwencyjnie, pojedynczo lub grupami.
    • Utrzymywana jest stała pojemność klastra (np. minimum 3 repliki robocze z 4).
    • Oszczędność zasobów sprzętowych, domyślny standard w Kubernetes oraz Docker Swarm.
  3. Canary Release (Wdrożenie kanarkowe):
    • Nowa wersja otrzymuje ustalony mikro-procent rzeczywistego ruchu (np. 2–5%) lub użytkowników z określonej grupy wewnętrznej.
    • Monitorowane są metryki systemowe (Error Rate, Latency). Jeśli nie wykryto anomalii, udział ruchu stopniowo zwiększa się do 100%.

3. Pipeline techniczny i mechanika wewnętrzna

Implementacja Graceful Shutdown w Node.js / TypeScript

Proces musi poprawnie przechwytywać sygnały systemu operacyjnego SIGTERM oraz SIGINT:

import express from "express";
import http from "http";

const app = express();
let isShuttingDown = false;

// Healthcheck ендпоінт для оркестратора
app.get("/healthz", (req, res) => {
  if (isShuttingDown) {
    // Сигнал балансувальнику не направляти сюди нові запити
    return res.status(503).json({ status: "shutting_down" });
  }
  return res.status(200).json({ status: "healthy" });
});

const server = http.createServer(app);
server.listen(3000);

// Перехоплення сигналу завершення від Docker / systemd
process.on("SIGTERM", () => {
  console.log("SIGTERM received. Starting graceful shutdown...");
  isShuttingDown = true;

  // 1. Припиняємо прийом нових HTTP-з'єднань
  server.close(async () => {
    console.log("Closed all remaining HTTP connections.");

    try {
      // 2. Закриваємо пули з'єднань з базами даних та Redis
      await dbPool.end();
      await redisClient.quit();
      console.log("Infrastructure connections closed. Exiting process.");
      process.exit(0);
    } catch (err) {
      console.error("Error during teardown:", err);
      process.exit(1);
    }
  });

  // 3. Запобіжник (Fail-safe): примусове завершення при зависанні сокетів
  setTimeout(() => {
    console.error("Forced termination: active connections timed out.");
    process.exit(1);
  }, 20000); // 20 секунд ліміту
});

Konfiguracja Healthcheck w Docker Compose

Aby zapewnić przełączanie ruchu przez orkiestrator, konfiguruje się parametr sprawdzania kondycji:

services:
  api:
    image: my-company/api:v1.2.0
    restart: always
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/healthz"]
      interval: 5s
      timeout: 3s
      retries: 3
      start_period: 10s
    stop_grace_period: 30s # Час на виконання Graceful Shutdown

4. Praktyczne scenariusze inżynierskie w środowisku produkcyjnym

01. Wdrożenie przez Coolify bez przerywania ruchu

Platforma Coolify wykorzystuje wbudowany reverse proxy Traefik. Podczas kliknięcia Deploy buduje ona nowy obraz Docker, uruchamia nowy kontener na losowym porcie, odpytuje jego endpoint healthcheck i dopiero po potwierdzeniu sprawności dynamicznie rekonfiguruje routing Traefika, po czym wysyła sygnał SIGTERM do starej repliki.

02. Hot Configuration Reload w Nginx (nginx -s reload)

Przy aktualizacji certyfikatów SSL lub dodawaniu nowych konfiguracji upstream, proces master Nginx uruchamia nowy zestaw procesów worker z nową konfiguracją. Stare workery przestają przyjmować nowe połączenia, kończą transfer aktywnych plików dla bieżących klientów i dopiero wtedy samolikwidują się bez utraty ani jednego pakietu.

03. Wdrażanie migracji bazy danych bez blokowania tabel w PostgreSQL

Przy dodawaniu indeksów do dużych tabel (miliony wierszy) standardowe polecenie CREATE INDEX blokuje tabelę dla zapisu (EXCLUSIVE LOCK), co prowadzi do zawieszenia kolejki zapytań. Inżynierowie korzystają z opcji CREATE INDEX CONCURRENTLY, która buduje indeks w tle, nie blokując równoległych operacji odczytu i zapisu.


5. Pułapki, typowe błędy i bezpieczeństwo

  1. Brak stop_grace_period w Dockerze: Domyślnie Docker daje kontenerowi tylko 10 sekund na obsługę SIGTERM, po czym wysyła śmiertelny SIGKILL (natychmiastowe zabicie procesu). Jeśli długotrwałe zapytanie do LLM lub webhook płatniczy trwa 12 sekund, operacja zostanie przerwana z uszkodzeniem danych. Zwiększaj limit do 30–60 sekund.
  2. Niezgodność wersji kodu z bazą danych: Próba zmiany nazwy kolumny w tabeli (ALTER TABLE users RENAME COLUMN email TO contact_email) natychmiast łamie starą wersję kodu, która nadal działa równolegle podczas wdrożenia. Zawsze stosuj wzorzec Expand-and-Contract w dwóch osobnych release’ach.
  3. Fałszywie dodatnie endpointy Health Check: Jeśli endpoint /healthz sprawdza dostępność wszystkich zewnętrznych API stron trzecich (np. OpenAI lub Twitter API) i te chwilowo zwalniają, orkiestrator uzna własną usługę za martwą i wpadnie w nieskończoną pętlę restartów (CrashLoopBackOff / Healthcheck Storm), niszcząc działający system produkcyjny. Sonda liveness powinna sprawdzać wyłącznie lokalny proces.
/ Najczęściej zadawane pytaniaSchema.org FAQPage

FAQ: Wdrożenie bez przestoju

Wdrożenie Blue-Green zakłada utworzenie drugiej, całkowicie izolowanej kopii całego środowiska (Green) obok działającego (Blue). Po przejściu testów ruch jest natychmiast przełączany na poziomie load balancera (z 0% na 100%), a rollback polega na odwrotnym przełączeniu w ciągu 1 sekundy. Rolling Update aktualizuje kontenery/instancje stopniowo partiami (np. po 25%), oszczędzając zasoby sprzętowe, ale wymaga zachowania kompatybilności wstecznej wersji podczas fazy koegzystencji.
/ Linki wewnętrzne
Wszystkie hasła