MongoDB RS0 — Heartbeat DROP Block (iptables przed UFW)
Symptom
- bms-3 logs:
Heartbeat failed after max retries, NetworkInterfaceExceededTimeLimit, target=bms-2:27017 ufw statuspokazuje ALLOW dla bms-3 — UFW wygląda poprawnienc / curl telnet://bms-2:27017z bms-3 = timeout (TCP SYN nie odpowiada)- bms-3 replication lag rośnie → po ~10h SECONDARY STARTUP2/stale
Przyczyna
Manualna reguła iptables INPUT DROP dodana przed regułami UFW:
Chain INPUT (policy DROP):
num 1 66553 packets DROP tcp src=51.68.155.224 dpt=27017
num 2 ... ufw-before-logging-input ...
Reguła nie jest widoczna przez ufw status. Nie jest w /etc/iptables/rules.v4 — zniknie po reboot. Może być dodana przez skrypt security isolation lub ręcznie.
Diagnoza (5 minut)
# 1. Sprawdź runtime iptables (NIE ufw status) — szukaj DROP przed ufw-before
ssh root@145.239.133.104 "iptables -L INPUT -n -v --line-numbers | head -10"
ssh root@54.36.123.110 "iptables -L INPUT -n -v --line-numbers | head -10"
# Sygnał: wysoka liczba packets przy DROP src=51.68.155.224
# 2. Potwierdź TCP fail z rescue/bms-3
curl -v telnet://145.239.133.104:27017 # timeout = DROP aktywnyNaprawa
# Na bms-2 (PRIMARY):
ssh root@145.239.133.104 "iptables -D INPUT -s 51.68.155.224 -p tcp --dport 27017 -j DROP"
# Na bms-4 (ARBITER):
ssh root@54.36.123.110 "iptables -D INPUT -s 51.68.155.224 -p tcp --dport 27017 -j DROP"
# Weryfikacja — rule 1 powinna być ufw-before-logging-input, nie DROP:
ssh root@145.239.133.104 "iptables -L INPUT -n -v --line-numbers | head -5"Po usunięciu DROP: bms-3 powinno samo się połączyć i rozpocząć sync w ciągu ~30s.
Recovery RS0 po długim lag
Jeśli bms-3 jest w STARTUP2 lub oplog lag > 1h:
// Step 1: Sprawdź lag i czy bms-3 synchronizuje
rs.status().members.forEach(m => print(m.name, m.stateStr, m.syncSourceHost||'none'))
// Step 2: Jeśli lag < 126 dni (oplog window bms-2) — poczekaj na oplog sync
// Jeśli bms-3 ma priority:0, votes:0 — po sync przywróć:
var cfg = rs.conf();
cfg.members[2].priority = 1;
cfg.members[2].votes = 1;
rs.reconfigForPSASet(2, cfg); // wymagane dla PSA topology
// Step 3: Przywróć write concern (jeśli był zmieniony na {w:1}):
db.adminCommand({setDefaultRWConcern:1, defaultWriteConcern:{w:'majority', wtimeout:5000}})Escalation
Jeśli po usunięciu DROP bms-3 nie łączy się w ciągu 2 minut:
- Sprawdź czy mongod jest aktywny:
systemctl status mongod - Sprawdź keyFile:
md5sum /etc/mongodb-keyfile— powinno być identyczne na bms-2 i bms-3 - Sprawdź logi:
tail -50 /var/log/mongodb/mongod.log | grep -v Heartbeat
Prevention
- Monitoring runtime iptables — ✅ ZAIMPLEMENTOWANE (#2471).
scripts/mongodb-rs0-drop-detector.shuruchamiany co 1 min przezp24-rs0-drop-detector.timerna bms-2 i bms-4. Skanuje surowyiptables-save(nieufw status) w poszukiwaniu regułDROP/REJECTdla IP członków rs0 i wysyła alert Discord (+ GH issue) w ciągu ~1 min; self-resolves po usunięciu reguły. Deploy:docs/mongodb-rs0-drop-detector-operations.md. - Cross-server TCP health check — Prometheus probe: bms-3 → bms-2:27017, bms-3 → bms-4:27017
- Nigdy nie używać
iptables -I INPUT 1 -j DROPdla IP RS members bez dokumentowania i TTL
Incident reference
- 2026-07-01: #2392 — DROP na bms-2 (66553 pkt) i bms-4 (66655 pkt), przyczyna nieznana
- 2026-07-01: #2471 — detektor iptables DROP (ten playbook +
scripts/mongodb-rs0-drop-detector.sh) - Powiązane: #2376 (w4 auth hang), playbook
mongodb-write-concern-auth-hang.md
Audit Log — Log to infra_operations
After this operation completes, log it to the infra_operations audit table.
Python (Linux server — bms-4, vps-i1, vps-h1, or similar):
import sys
sys.path.insert(0, '/opt/p24-infra')
from scripts.lib.log_op import log_op
log_op(
actor="claude", # "radieu" for manual human ops, "claude" for agent
op_type="config_change",
resource="mongodb-rs0",
result="success", # "success" | "failed" | "skipped"
detail="MongoDB rs0 heartbeat block resolved — network/firewall rule adjusted",
env="bms-2",
gh_issue=2730,
)PowerShell (Windows dev machine):
$env:SUPABASE_URL = (Get-Content "C:\code_2026\p24-infra\.env.local" | Select-String "^SUPABASE_URL=").ToString().Split("=",2)[1].Trim()
$env:SUPABASE_SERVICE_KEY = (Get-Content "C:\code_2026\p24-infra\.env.local" | Select-String "^SUPABASE_SERVICE_KEY=").ToString().Split("=",2)[1].Trim()
python -c "
import os, sys
sys.path.insert(0, 'C:/code_2026/p24-infra')
from scripts.lib.log_op import log_op
log_op('claude', 'config_change', 'mongodb-rs0', 'success', 'MongoDB rs0 heartbeat block resolved — network/firewall rule adjusted', 'bms-2')
"
$env:SUPABASE_URL = ''; $env:SUPABASE_SERVICE_KEY = ''