diff --git a/docker-compose.monitoring.yml b/docker-compose.monitoring.yml index 5ab49bb..e4664ed 100644 --- a/docker-compose.monitoring.yml +++ b/docker-compose.monitoring.yml @@ -185,7 +185,7 @@ services: deploy: resources: limits: - memory: ${NETDATA_MEM_LIMIT:-320m} + memory: ${NETDATA_MEM_LIMIT:-768m} cpus: "${NETDATA_CPU_LIMIT:-1.0}" volumes: diff --git a/docs/konfiguracja/limity-zasobow.md b/docs/konfiguracja/limity-zasobow.md index 54d2944..9a0f379 100644 --- a/docs/konfiguracja/limity-zasobow.md +++ b/docs/konfiguracja/limity-zasobow.md @@ -7,10 +7,10 @@ docierają do każdej instalacji przez `${VAR:-default}` w plikach compose, wię out-of-the-box po `git pull && make up`. !!! warning "Minimalne wymagania sprzętowe" - **Minimum: 12 GB RAM. Zalecane: 16 GB+ RAM.** Suma stałych limitów (~3,3 GB) + - minimalne progi usług zmiennych (dbserver/appserver/workery = 6,5 GB) + rezerwa OS - (2 GB) daje ~12 GB. Przy 12 GB wszystko się mieści, ale ciasno (dbserver na minimum, - zerowa nadwyżka). Dopiero od 16 GB nadwyżka realnie zasila bazę, aplikację i workery. + **Minimum: 12 GB RAM. Zalecane: 16 GB+ RAM.** Suma stałych limitów (~4,3 GB) + + minimalne progi usług zmiennych (dbserver/appserver/workerserver = 5 GB) + rezerwa OS + (2 GB) daje ~11,3 GB. Przy 12 GB wszystko się mieści, ale ciasno (usługi zmienne + niemal na minimum, ~0,7 GB nadwyżki). Dopiero od 16 GB nadwyżka realnie zasila bazę, aplikację i workery. Poniżej 12 GB `configure-resources` ostrzega o ryzyku OOM. ## Model: stałe capy + usługi zmienne @@ -49,13 +49,14 @@ Wynik ląduje w `$BPP_CONFIGS_DIR/.env` jako `DBSERVER_MEM_LIMIT`, `REDIS_MEM_LI oraz `REDIS_MAXMEMORY` (≈80% limitu Redisa, żeby eviction `allkeys-lru` wyprzedził OOM kill). `.env` staje się jednym źródłem prawdy dla limitów RAM. CPU jest zapisywane dla 6 usług (3 zmienne + `redis`/`loki`/`netdata`); pozostałe korzystają z CPU z compose. +`netdata` ma minimum **1.0 CPU** — niższej wartości kreator nie przyjmie. ## Usługi ze stałym capem | Serwis | RAM | Uwagi | |---|---|---| | `redis` | 1g | broker + cache + result backend; `REDIS_MAXMEMORY` (`allkeys-lru`) ≈ 80% limitu | -| `netdata` | 320m | dbengine + auto-discovery; patrz uwaga niżej o retencji | +| `netdata` | 768m | dbengine + auto-discovery; **minimum 768m i 1.0 CPU** (podniesione z 320m; `make up` samo podnosi niższe wartości w `.env`) — patrz uwaga niżej o retencji | | `authserver` | 320m | Django + gunicorn (SSO) | | `celerybeat` | 480m | scheduler — pojedynczy proces; podniesione z 320m (Django + broker potrafiły dobić do twardego capu → OOM) | | `denorm-queue` | 320m | most PG `LISTEN` → Celery, pojedynczy proces | @@ -67,8 +68,9 @@ dla 6 usług (3 zmienne + `redis`/`loki`/`netdata`); pozostałe korzystają z CP | `dozzle` | 64m | przeglądarka logów (Go) | | `ofelia` | 64m | scheduler cron (Go) | | `autoheal` | 32m | restart kontenerów po unhealthy | +| `pgbouncer` | 64m | pula połączeń appservera — patrz sekcja pgbouncer niżej | -Razem ≈ **3,8 GB**. Capy te są odejmowane od budżetu, a reszta trafia do usług zmiennych. +Razem ≈ **4,3 GB**. Capy te są odejmowane od budżetu, a reszta trafia do usług zmiennych. ## Usługi zmienne (dzielą pulę) @@ -104,9 +106,11 @@ bo jego realny apetyt na RAM zależy od liczby procesów-dzieci prefork. policzoną — oba usuwają nieużywane `WORKER_GENERAL_*`/`WORKER_DENORM_*`. !!! tip "Netdata: cap kontra retencja" - Cap `netdata` (320m) to limit **twardy**. Jeśli wydłużasz historię metryk przez + Cap `netdata` (768m) to limit **twardy**. Jeśli wydłużasz historię metryk przez `NETDATA_DBENGINE_TIER0_RETENTION_MB` / `NETDATA_DBENGINE_PAGE_CACHE_MB` w `.env`, **podnieś również `NETDATA_MEM_LIMIT`** — inaczej netdata zostanie ubity przez OOM. + Minimum to **768m RAM i 1.0 CPU**: każde `make up` podnosi niższe + `NETDATA_MEM_LIMIT`/`NETDATA_CPU_LIMIT` w `.env` do tego progu (wyższe zostawia). Plik `netdata.conf` jest [force-syncowany](architektura.md#netdataconf-renderowany-host-side) — nie edytuj go ręcznie, używaj knobów `.env`. diff --git a/scripts/configure-resources.sh b/scripts/configure-resources.sh index 3a54c31..2e79cb6 100755 --- a/scripts/configure-resources.sh +++ b/scripts/configure-resources.sh @@ -124,7 +124,7 @@ CPU_BUDGET="$CPU_COUNT" # Format: name:cap_mb. Przypisywane automatycznie (bez pytania). FIXED_MEM=( "redis:1024" - "netdata:320" + "netdata:768" "authserver:320" "celerybeat:480" "denorm-queue:320" @@ -150,7 +150,10 @@ VARIABLE_MEM=( "workerserver:1536:35" ) -# CPU (limit miekki). Format: name:cpu_weight. Sumuja sie do CPU_TOTAL_WEIGHT. +# CPU (limit miekki). Format: name:cpu_weight[:min_cpu]. Wagi sumuja sie do +# CPU_TOTAL_WEIGHT. Opcjonalne min_cpu to minimum uslugi - podnosi default +# i odrzuca nizsza odpowiedz (bez niego obowiazuje MIN_CPU). Netdata ma 1.0: +# przy wadze 5% na malym hoscie dostawala ~0.2 CPU i nie nadazala ze zbieraniem. # Po konsolidacji jeden worker przejmuje wage dwoch poprzednich (25+12.5 # zaokraglone do 30 - reszta puli i tak idzie do dbserver/appserver). CPU_SERVICES=( @@ -159,7 +162,7 @@ CPU_SERVICES=( "workerserver:30" "redis:7.5" "loki:2.5" - "netdata:5" + "netdata:5:1.0" ) # Suma wag CPU_SERVICES - uzywane jako startowa pula w redystrybucji. CPU_TOTAL_WEIGHT=95 @@ -375,8 +378,9 @@ done remaining_cpu=$CPU_BUDGET remaining_cpu_weight=$CPU_TOTAL_WEIGHT for entry in "${CPU_SERVICES[@]}"; do - IFS=: read -r svc cpu_w <<< "$entry" - default_cpu=$(LC_ALL=C awk -v r="$remaining_cpu" -v w="$cpu_w" -v t="$remaining_cpu_weight" -v min="$MIN_CPU" \ + IFS=: read -r svc cpu_w svc_min_cpu <<< "$entry" + svc_min_cpu="${svc_min_cpu:-$MIN_CPU}" + default_cpu=$(LC_ALL=C awk -v r="$remaining_cpu" -v w="$cpu_w" -v t="$remaining_cpu_weight" -v min="$svc_min_cpu" \ 'BEGIN { if (t <= 0) v = min; else v = r * w / t; if (v < min) v = min; printf "%.1f", v }') cpu_answer="" while true; do @@ -386,8 +390,8 @@ for entry in "${CPU_SERVICES[@]}"; do continue fi cpu_answer=$(round1 "$cpu_answer") - if LC_ALL=C awk -v v="$cpu_answer" -v m="$MIN_CPU" 'BEGIN { exit (v < m) ? 0 : 1 }'; then - echo " Blad: minimum to ${MIN_CPU} CPU (Docker odrzuci mniej)." >&2 + if LC_ALL=C awk -v v="$cpu_answer" -v m="$svc_min_cpu" 'BEGIN { exit (v < m) ? 0 : 1 }'; then + echo " Blad: minimum dla $svc to ${svc_min_cpu} CPU." >&2 continue fi break diff --git a/scripts/ensure-config-files.sh b/scripts/ensure-config-files.sh index 46a8048..11ce0f5 100755 --- a/scripts/ensure-config-files.sh +++ b/scripts/ensure-config-files.sh @@ -249,6 +249,53 @@ if [ -f "$_ENV" ]; then _ensure_var LOKI_RETENTION_WEBSERVER "$(_loki_period webserver 4320h)" \ " + dopisano LOKI_RETENTION_WEBSERVER w .env" + # Minimum zasobow netdaty: 768m RAM, 1.0 CPU. `make configure-resources` + # wpisywal wczesniej do .env NETDATA_MEM_LIMIT=320m i NETDATA_CPU_LIMIT + # rzedu 0.2 (5% puli CPU), a Compose default dziala tylko gdy zmiennej + # brak - wiec samo podniesienie defaultow nie dotarloby do istniejacych + # instalacji. Podnosimy WYLACZNIE wartosci ponizej minimum; wyzsze (strojone + # przez operatora, np. pod dluzsza retencje dbengine) zostaja nietkniete. + # Brak zmiennej = nic nie robimy, bo wtedy obowiazuje default z compose. + # Niezrozumiala wartosc -> ostrzezenie, nie ruszamy (nie zgadujemy jednostek). + _set_existing_var() { # $1 = nazwa, $2 = nowa wartosc (zmienna musi istniec) + local _t="$_ENV.tmp.$$" + awk -v k="$1" -v v="$2" 'BEGIN { FS=OFS="=" } $1 == k { print k "=" v; next } { print }' \ + "$_ENV" > "$_t" && mv "$_t" "$_ENV" + } + _mem_to_mb() { # Docker: liczba + opcjonalnie b/k/m/g (+ 'b'); goła liczba = bajty + printf '%s' "$1" | LC_ALL=C awk ' + match(tolower($0), /^[0-9]+(\.[0-9]+)?(b|k|kb|m|mb|g|gb)?$/) { + v = $0 + 0; u = tolower($0); sub(/^[0-9.]+/, "", u) + if (u == "" || u == "b") v = v / 1048576 + else if (u ~ /^k/) v = v / 1024 + else if (u ~ /^g/) v = v * 1024 + printf "%d", v; ok = 1 + } + END { exit ok ? 0 : 1 }' + } + _nd_mem="$(grep -E '^NETDATA_MEM_LIMIT=' "$_ENV" | tail -1 | cut -d= -f2- | tr -d '\r' || true)" + if [ -n "$_nd_mem" ]; then + if _nd_mem_mb="$(_mem_to_mb "$_nd_mem")"; then + if [ "$_nd_mem_mb" -lt 768 ]; then + _set_existing_var NETDATA_MEM_LIMIT 768m + echo " ~ podniesiono NETDATA_MEM_LIMIT z ${_nd_mem} do minimum 768m" + fi + else + echo " ! OSTRZEZENIE: nie rozumiem NETDATA_MEM_LIMIT='${_nd_mem}' w .env - zostawiam (minimum to 768m)" >&2 + fi + fi + _nd_cpu="$(grep -E '^NETDATA_CPU_LIMIT=' "$_ENV" | tail -1 | cut -d= -f2- | tr -d '\r' || true)" + if [ -n "$_nd_cpu" ]; then + if [[ "$_nd_cpu" =~ ^[0-9]+(\.[0-9]+)?$ ]]; then + if LC_ALL=C awk -v v="$_nd_cpu" 'BEGIN { exit (v < 1.0) ? 0 : 1 }'; then + _set_existing_var NETDATA_CPU_LIMIT 1.0 + echo " ~ podniesiono NETDATA_CPU_LIMIT z ${_nd_cpu} do minimum 1.0" + fi + else + echo " ! OSTRZEZENIE: nie rozumiem NETDATA_CPU_LIMIT='${_nd_cpu}' w .env - zostawiam (minimum to 1.0)" >&2 + fi + fi + # BPP_BACKUP_PG_IMAGE nie jest tu juz samouzdrawiana - zmienna jest MARTWA # od 2026-09. Byla potrzebna, gdy backup-runner wspoldzielil obraz Postgresa # z sentinelem trybu external; orkiestrator (docker:cli) obrazu Postgresa diff --git a/tests/test_makefile.sh b/tests/test_makefile.sh index 77e65b9..d1479d1 100755 --- a/tests/test_makefile.sh +++ b/tests/test_makefile.sh @@ -1663,7 +1663,15 @@ test_configure_resources() { assert_file_contains "alloy cap 192m" "ALLOY_MEM_LIMIT=192m" "$cfg/.env" assert_file_contains "loki cap 512m" "LOKI_MEM_LIMIT=512m" "$cfg/.env" assert_file_contains "flower cap 128m" "FLOWER_MEM_LIMIT=128m" "$cfg/.env" - assert_file_contains "netdata cap 320m" "NETDATA_MEM_LIMIT=320m" "$cfg/.env" + assert_file_contains "netdata cap 768m" "NETDATA_MEM_LIMIT=768m" "$cfg/.env" + # CPU netdaty zalezy od liczby rdzeni runnera - sprawdzamy tylko minimum 1.0. + local nd_cpu + nd_cpu=$(grep '^NETDATA_CPU_LIMIT=' "$cfg/.env" | cut -d= -f2 || true) + if [ -n "$nd_cpu" ] && LC_ALL=C awk -v v="$nd_cpu" 'BEGIN { exit (v >= 1.0) ? 0 : 1 }'; then + pass "netdata CPU >= 1.0 ($nd_cpu)" + else + fail "netdata CPU >= 1.0 (jest: '${nd_cpu}')" + fi assert_file_contains "grafana cap 192m" "GRAFANA_MEM_LIMIT=192m" "$cfg/.env" assert_file_contains "dozzle cap 64m" "DOZZLE_MEM_LIMIT=64m" "$cfg/.env" assert_file_contains "pgbouncer cap 64m" "PGBOUNCER_MEM_LIMIT=64m" "$cfg/.env" @@ -2082,6 +2090,45 @@ YAML rm -rf "$cfg" } +test_ensure_config_files_netdata_floor() { + yellow "=== Test: ensure-config-files podnosi limity netdaty do minimum ===" + + local cfg + # Stary .env po configure-resources: 320m / 0.2 -> podniesione do 768m / 1.0. + cfg=$(mktemp -d) + printf 'BPP_CONFIGS_DIR=%s\nNETDATA_MEM_LIMIT=320m\nNETDATA_CPU_LIMIT=0.2\n' "$cfg" > "$cfg/.env" + if ! BPP_CONFIGS_DIR="$cfg" bash "$REPO_DIR/scripts/ensure-config-files.sh" >/dev/null 2>&1; then + fail "ensure-config-files zwrocil blad (netdata ponizej minimum)" + rm -rf "$cfg"; return + fi + assert_file_contains "netdata RAM 320m -> 768m" "^NETDATA_MEM_LIMIT=768m$" "$cfg/.env" + assert_file_contains "netdata CPU 0.2 -> 1.0" "^NETDATA_CPU_LIMIT=1.0$" "$cfg/.env" + if [ "$(grep -c '^NETDATA_MEM_LIMIT=' "$cfg/.env")" = "1" ]; then + pass "NETDATA_MEM_LIMIT wystepuje raz" + else + fail "NETDATA_MEM_LIMIT wystepuje raz" + fi + rm -rf "$cfg" + + # Wartosci powyzej minimum (strojone przez operatora) zostaja nietkniete. + cfg=$(mktemp -d) + printf 'BPP_CONFIGS_DIR=%s\nNETDATA_MEM_LIMIT=1g\nNETDATA_CPU_LIMIT=2.5\n' "$cfg" > "$cfg/.env" + BPP_CONFIGS_DIR="$cfg" bash "$REPO_DIR/scripts/ensure-config-files.sh" >/dev/null 2>&1 \ + || fail "ensure-config-files zwrocil blad (netdata powyzej minimum)" + assert_file_contains "netdata RAM 1g bez zmian" "^NETDATA_MEM_LIMIT=1g$" "$cfg/.env" + assert_file_contains "netdata CPU 2.5 bez zmian" "^NETDATA_CPU_LIMIT=2.5$" "$cfg/.env" + rm -rf "$cfg" + + # Brak zmiennych -> nie dopisujemy (obowiazuje default z compose). + cfg=$(mktemp -d) + printf 'BPP_CONFIGS_DIR=%s\n' "$cfg" > "$cfg/.env" + BPP_CONFIGS_DIR="$cfg" bash "$REPO_DIR/scripts/ensure-config-files.sh" >/dev/null 2>&1 \ + || fail "ensure-config-files zwrocil blad (brak zmiennych netdaty)" + assert_file_not_contains "brak NETDATA_MEM_LIMIT nie jest dopisywany" "NETDATA_MEM_LIMIT=" "$cfg/.env" + assert_file_not_contains "brak NETDATA_CPU_LIMIT nie jest dopisywany" "NETDATA_CPU_LIMIT=" "$cfg/.env" + rm -rf "$cfg" +} + test_ensure_config_files_altcha_selfheal() { yellow "=== Test: ensure-config-files dosypuje ALTCHA do starego .env ===" @@ -2359,6 +2406,7 @@ test_configure_resources_worker_consolidation test_init_configs_generates_altcha test_loki_retention_migration test_ensure_config_files_altcha_selfheal +test_ensure_config_files_netdata_floor test_init_configs_path_validation test_install_docker_windows test_rclone_single_source_of_truth