VPN Config Service — проблемы с worker¶
Worker (vpn-config-worker) — отдельный процесс, который синхронизирует конфиги с VPN-серверов по SSH. При зависании или падении клиенты не получают обновлённые конфиги, трафик перестаёт считаться.
Симптомы¶
- Grafana алерт «Worker Unhealthy» / heartbeat не обновляется
docker logs vpn-config-workerне показывает «Online sync done» каждые ~60 сек- SSH cascade timeout: в логах много
SSH: Connection timed outподряд fill_configsзависает более 10 минут (обычно завершается за 2-4 мин)- Config pipeline не двигается: один и тот же сервер в логах сотни раз подряд
Диагностика¶
1. Проверить состояние контейнеров VCS¶
Ожидается: vpn-config-service (Up), vpn-config-worker (Up), vpn-config-postgres (Up), vpn-config-redis (Up).
2. Проверить heartbeat worker¶
./scripts/ssh-internal.sh 10.99.87.249 \
"stat /tmp/worker_heartbeat/heartbeat 2>/dev/null || echo 'NO HEARTBEAT'"
Heartbeat обновляется каждые ~60 сек (online sync cycle). Если файл старше 5 мин — worker завис.
3. Проверить health endpoint VCS API¶
Ожидается: {"status": "ok", ...}. Если API не отвечает — упал контейнер vpn-config-service.
4. Нормальное время выполнения health_check¶
Health_check при 50+ серверах может занимать до 240 секунд — это нормально.
| Параметр | Значение |
|---|---|
| Таймаут на сервер | 90s |
| Общий таймаут (основной цикл) | 240s |
| Таймаут перезапуска проб | 120s |
| Внешний safety timeout worker'а | 270s |
Если health_check превышает 270s, worker принудительно завершает задачу и вызывает flush_dead() для очистки мёртвых SSH-соединений.
5. Хвост логов worker¶
Смотреть:
- Online sync done in Xs: N sessions — нормальный ритм
- SSH: Connection timed out — мёртвые SSH-соединения в пуле
- fill_configs started без fill_configs done — fill завис
- flush_dead — worker сам обнаружил и почистил мёртвые соединения
6. Статистика SSH-пула через API¶
./scripts/ssh-internal.sh 10.99.87.249 \
"curl -s http://localhost:8000/api/v1/stats \
-H 'X-API-Key: VazVBGPEBLTG7qNVOQQu4xR21DWTBi4_fodUjuEojnE' | python3 -m json.tool"
Поля ssh_pool_active и ssh_pool_in_use: если in_use близко к active и не меняется — пул заблокирован мёртвыми соединениями.
7. Проверить PostgreSQL VCS¶
./scripts/ssh-internal.sh 10.99.87.249 \
"docker exec vpn-config-postgres psql -U vpnconfig vpnconfig \
-c 'SELECT COUNT(*) FROM servers WHERE is_active = true;'"
Если возвращает 0 — servers не загружены из MySQL (нужен mysql_sync).
Причины и решения¶
| Симптом | Причина | Решение |
|---|---|---|
| Cascade SSH timeouts | SSH pool забит мёртвыми conn | Перезапустить worker (flush_dead) |
| fill_configs завис | Один из серверов не отвечает | Перезапустить worker |
servers = 0 в stats |
MySQL sync не прошёл | POST /api/v1/sync/mysql-servers |
| Worker exited (код != 0) | OOM или необработанное исключение | docker logs, перезапустить |
| Config pipeline одни ошибки | Множество серверов down | Проверить SSH с backend на эти IP |
Исправление¶
Перезапустить worker (основное действие)¶
./scripts/ssh-internal.sh 10.99.87.249 \
"cd /opt/vpn-config-service && \
docker compose -f docker-compose.prod.yml restart vpn-config-worker"
После перезапуска в логах должно появиться fill_configs started через ~3 мин (стартап stagger), затем Online sync done.
Принудительный mysql_sync (если нет серверов в PostgreSQL)¶
./scripts/ssh-internal.sh 10.99.87.249 \
"curl -sX POST http://localhost:8000/api/v1/sync/mysql-servers \
-H 'X-API-Key: VazVBGPEBLTG7qNVOQQu4xR21DWTBi4_fodUjuEojnE'"
Проверить SSH-доступность с backend на проблемный сервер¶
./scripts/ssh-internal.sh 10.99.87.249 \
"timeout 10 ssh -i /opt/vpn-config-service/ssh/id_ed25519_vpn_config_service \
-o StrictHostKeyChecking=no -o ConnectTimeout=5 \
root@SERVER_IP 'echo ok' 2>&1"
Перезапустить весь VCS стек (крайняя мера)¶
./scripts/ssh-internal.sh 10.99.87.249 \
"cd /opt/vpn-config-service && \
docker compose -f docker-compose.prod.yml down && \
docker compose -f docker-compose.prod.yml up -d"
Затем применить миграции и загрузить серверы:
./scripts/ssh-internal.sh 10.99.87.249 \
"docker exec vpn-config-service alembic upgrade head && \
curl -sX POST http://localhost:8000/api/v1/sync/mysql-servers \
-H 'X-API-Key: VazVBGPEBLTG7qNVOQQu4xR21DWTBi4_fodUjuEojnE'"
Проверить DB lock в PostgreSQL VCS¶
./scripts/ssh-internal.sh 10.99.87.249 \
"docker exec vpn-config-postgres psql -U vpnconfig vpnconfig \
-c 'SELECT pid, state, wait_event_type, query FROM pg_stat_activity WHERE state != '\''idle'\'';'"
Если есть транзакции в состоянии idle in transaction — worker завис с незакрытой транзакцией. Решение: перезапустить worker.
Эскалация¶
- Если перезапуск worker не помогает — деплоить новую версию через CI/CD (GitLab pipeline проект 55)
- Если падает PostgreSQL VCS — проверить дисковое пространство:
df -hна10.99.87.249 - При подозрении на баг в коде — задокументировать инцидент (monorepo:
incidents/VCS-WORKER-NAME-YYYY-MM-DD.md)
См. также: VPN Config Service · Runbooks · DevOps скрипты · Репозитории