← К статьям
Бесплатно Настройка

Машина «неактивна», а всё работает: залипший контроллер vast

Редакция Flux · 11 мин

Эта поломка стоила нам одной машины на три часа простоя и просадки рейтинга с 0.99 до 0.79 на другой. Коварна она тем, что не видна ни одной привычной проверкой: канал до биржи идеальный, туннель работает, клиенты крутятся, в логах ни единой ошибки. А машина при этом для биржи мертва.

Ниже — как её распознать, почему обычная диагностика уводит в сторону, и готовый сторож, который ловит и чинит это сам за три минуты.

Как это выглядит

Машина показывается на сайте неактивной. Клиенты её не видят, новые аренды не приходят. Если на ней в этот момент кто-то работает — рейтинг начинает течь вниз, и довольно быстро.

Первое, что показывает API хоста:

полездоровая машинабольная
timeout01000000 либо растёт: 18516 и дальше
listedtruetrue — машина числится в каталоге
verificationverifiedverified — верификация на месте
рейтингстабилентечёт вниз, если есть аренда

То есть машина формально всё ещё в каталоге и верифицирована — просто биржа с ней не разговаривает.

На самом риге картина такая:

что видно в журнале агентаbash
# сколько ответов от биржи за последние 300 строк журнала
tail -300 /var/lib/vastai_kaalia/kaalia.log | grep -c Heartbeat
# 0   <-- вот он, признак

# при этом наши запросы уходят исправно
tail -300 /var/lib/vastai_kaalia/kaalia.log | grep -c keepalive
# 19  <-- агент жив и стучится

# и раз за разом пересоздаёт соединение
grep -ac lmsg_elap /var/lib/vastai_kaalia/kaalia.log
# 127 за сутки

Ключевое сочетание: keepalive уходит, а Heartbeat не приходит. Агент исправно зовёт биржу, биржа молчит. Через 55 секунд молчания агент считает соединение мёртвым, пересоздаёт сокет — и всё повторяется по кругу.

Заодно в системе видны сотни перезапусков службы за сутки. Это не сбой: у vast есть собственный сторож, который ежеминутно проверяет связь и дёргает агента, если её нет. Он честно пытается помочь, но проблема не в агенте, поэтому перезапуски ничего не меняют.

Почему обычная диагностика заводит в тупик

Мы потратили на поиск причины несколько часов, последовательно проверяя всё, что обычно ломается. Все четыре версии оказались ложными.

Канал до биржи? Идеальный. Десять TCP-соединений из десяти, отклик одна миллисекунда. Ни одного провала.

Туннель или VPS? Тоже чисто: ошибок в журнале нет, сервер без нагрузки, выход в интернет отвечает правильным адресом. И главный аргумент — две наши машины сидели на одном VPS, одна была мертва, вторая работала нормально. Сервер тут ни при чём.

Может, порт биржи закрыт? Нет, открыт и отвечает мгновенно. Вот это самая коварная деталь: TCP-порт мёртвого контроллера принимает соединения как ни в чём не бывало. Молчит только служба уровня приложения. Поэтому любая проверка вида «жив ли порт» покажет зелёный свет.

Проблема на риге? Тоже нет: клиенты работают, видеокарты видны, ошибок ядра ноль.

Всё, что обычно указывает на неисправность, показывало норму. Разгадка нашлась только сравнением больной машины со здоровой по одному шаблону команд — и единственным отличием оказался адрес, к которому подключён агент.

Что происходит на самом деле

У биржи не один сервер, а несколько контроллеров. Агент на риге при первом подключении получает адрес одного из них и запоминает его в файле:

кэш адреса контроллераbash
cat /var/lib/vastai_kaalia/controller_connection
# 3.239.230.153:7071

Дальше агент держится за этот адрес намертво. Если контроллер на стороне биржи перестаёт отвечать — риг будет долбиться в него бесконечно, пересоздавая соединение каждую минуту. Сам он другой адрес не выберет.

Это сбой на стороне площадки, а не наша поломка. За одни сутки мы насчитали четыре мёртвых контроллера. И вот что важно понимать:

Список живых контроллеров протухает за часы. Адрес, который утром работал нормально, к обеду умер и утащил с собой машину на три часа простоя. Составлять «белый список» бесполезно — нужно реагировать на симптом, а не на конкретные адреса.

Распределение по контроллерам случайное. Поэтому часть парка может работать прекрасно, пока другая часть лежит — и это сбивает с толку: кажется, что дело в конкретных машинах.

Сколько это стоит

Три реальных случая за один день.

машиначто былоцена
риг с активной арендой залипание замечено спустя часы рейтинг 0.99 → 0.79
риг без аренд три часа молчания, поймано вручную простой, рейтинг почти не тронут
риг с двумя арендами залипал дважды, вылечен автоматически по 48 секунд, потерь нет

Разница между первой и третьей строкой — только в том, что на третьей машине уже стоял сторож. Он поймал оба залипания и переподключил риг раньше, чем это успело сказаться на деньгах.

Лечение вручную

Само лечение простое: стереть кэш и дать агенту выбрать контроллер заново. Контейнеры клиентов при этом не затрагиваются — проверено на машинах с активными арендами.

сброс залипшего контроллераbash
systemctl stop vastai
sleep 3
mv /var/lib/vastai_kaalia/controller_connection \
   /var/lib/vastai_kaalia/controller_connection.bak.$(date +%s)
systemctl start vastai
sleep 45

# проверяем результат
echo "новый контроллер: $(cat /var/lib/vastai_kaalia/controller_connection)"
echo "heartbeat: $(tail -150 /var/lib/vastai_kaalia/kaalia.log | grep -c Heartbeat)"

Адрес должен смениться, а счётчик heartbeat — стать больше нуля. В поле timeout у машины обнуляется в течение пары минут, и она снова появляется в каталоге.

Проверять надо все риги разом, а не по одному. Распределение по контроллерам случайное: часть парка может быть здорова и маскировать проблему. Сравнение больной машины со здоровой по одному шаблону — самый быстрый путь к причине.

Сторож, который делает это сам

Ловить такое вручную бессмысленно: залипание случается в произвольный момент, а замечаешь его, когда уже потерял деньги. Ниже — служба, которая следит за признаком и лечит сама.

Логика простая: раз в полминуты смотрим, когда биржа отвечала последний раз. Если она молчит дольше двух с половиной минут, но наши запросы при этом уходят — значит это именно залипание, и надо сбросить кэш. Второе условие важно: если не уходят и запросы, проблема другая, и вмешиваться нельзя.

установка сторожаbash
cat > /usr/local/bin/vast-controller-watchdog.sh <<'EOF'
#!/bin/bash
# Ловит залипший контроллер биржи: агент шлёт запросы, а ответов нет.
# Лечение — сброс кэша адреса. Контейнеры клиентов не трогает.

K=/var/lib/vastai_kaalia/kaalia.log
CC=/var/lib/vastai_kaalia/controller_connection
LOG=/var/log/vast-controller-watchdog.log

CHECK=30          # как часто смотреть, секунд
STALE=150         # столько секунд молчания биржи = залипание
COOLDOWN=1800     # не лечить чаще раза в 30 минут

last_fix=0

log(){ echo "$(date -u "+%F %T") $*" >> "$LOG"; }

last_hb(){
  local t
  t=$(grep -a "handle_message mtype: Heartbeat" "$K" 2>/dev/null | tail -1 \
      | grep -oE "^\[[0-9-]+ [0-9:]+" | tr -d "[")
  [ -z "$t" ] && { echo 0; return; }
  date -u -d "$t" +%s 2>/dev/null || echo 0
}

log "=== СТАРТ. Текущий контроллер: $(cat $CC 2>/dev/null) ==="

while true; do
  sleep $CHECK
  now=$(date -u +%s)
  hb=$(last_hb)
  [ "$hb" = "0" ] && continue
  age=$(( now - hb ))
  [ $age -lt $STALE ] && continue

  # если и наши запросы не уходят — случай другой, не вмешиваемся
  ka=$(tail -300 "$K" | grep -c keepalive)
  if [ "$ka" -eq 0 ]; then
    log "биржа молчит $age с, но и keepalive не идёт — случай не наш"
    continue
  fi

  if [ $(( now - last_fix )) -lt $COOLDOWN ]; then
    log "залипание ($age с), но лечили недавно — жду окончания паузы"
    continue
  fi

  old=$(cat "$CC" 2>/dev/null)
  log "ЗАЛИПАНИЕ: биржа молчит $age с, контроллер $old — сбрасываю кэш"
  systemctl stop vastai
  sleep 3
  mv "$CC" "$CC.bak.$now" 2>/dev/null
  systemctl start vastai
  sleep 45
  new=$(cat "$CC" 2>/dev/null)
  hb2=$(tail -150 "$K" | grep -c Heartbeat)
  if [ "$hb2" -gt 0 ]; then
    log "  ВЫЛЕЧЕНО: $old -> $new, heartbeat=$hb2"
  else
    log "  ВНИМАНИЕ: $old -> $new, но heartbeat всё ещё 0 — нужен ручной разбор"
  fi
  last_fix=$(date -u +%s)
done
EOF

chmod +x /usr/local/bin/vast-controller-watchdog.sh
bash -n /usr/local/bin/vast-controller-watchdog.sh || echo "СИНТАКСИС СЛОМАН"

cat > /etc/systemd/system/vast-controller-watchdog.service <<'UNIT'
[Unit]
Description=Watchdog for stuck vast controller
After=network-online.target vastai.service

[Service]
Type=simple
ExecStart=/usr/local/bin/vast-controller-watchdog.sh
Restart=always
RestartSec=30

[Install]
WantedBy=multi-user.target
UNIT

systemctl daemon-reload
systemctl enable --now vast-controller-watchdog
sleep 3
echo "служба: $(systemctl is-active vast-controller-watchdog)"
tail -2 /var/log/vast-controller-watchdog.log

В конце вывода должно быть служба: active и запись о старте с текущим адресом контроллера.

Почему порог именно две с половиной минуты

Соблазн поставить меньше велик — хочется реагировать за полминуты. Так делать нельзя, и вот почему.

Агент биржи сам считает соединение мёртвым, когда она молчит 55 секунд, и пересоздаёт сокет. Это его штатная реакция на сетевую заминку, и с короткими перебоями он справляется без посторонней помощи. Порог в 150 секунд даёт ему две-три такие попытки.

Поставьте меньше — и сторож начнёт вмешиваться там, где всё починилось бы само: перезапускать службу на ровном месте и менять исправно работающий контроллер на случайный другой. Лечение станет вреднее болезни.

параметрзначениесмысл
CHECK30 скак часто смотреть журнал
STALE150 смолчание дольше этого = залипание
COOLDOWN1800 сзащита от цикла: не лечить чаще раза в полчаса

С такими настройками полный цикл — от начала залипания до восстановленной связи — занимает около трёх с половиной минут.

Как убедиться, что сторож работает

Не стоит верить механизму, который ни разу не срабатывал. Проверить его можно честно: подсунуть заведомо мёртвый адрес и посмотреть, поймает ли.

Делать это надо только на машине без аренд — на несколько минут она реально пропадёт из каталога.

проверка сторожа (только на пустой машине!)bash
CC=/var/lib/vastai_kaalia/controller_connection
echo "было: $(cat $CC)"

systemctl stop vastai
sleep 2
cp -a $CC $CC.before_test
echo -n "192.0.2.1:7071" > $CC        # адрес из документационного диапазона
systemctl start vastai

echo "подсунут нерабочий адрес, ждём срабатывания 3-4 минуты"
echo "смотреть: tail -f /var/log/vast-controller-watchdog.log"

В журнале должно появиться две записи: обнаружение залипания с указанием, сколько секунд молчит биржа, и результат лечения с новым адресом. У нас это выглядело так:

журнал сторожа при проверкеlog
11:09:29 ЗАЛИПАНИЕ: биржа молчит 347 с, контроллер 3.239.230.153:7071 — сбрасываю кэш
11:10:17   ВЫЛЕЧЕНО: 3.239.230.153:7071 -> 34.226.220.129:7071, heartbeat=6

А вот записи с боевого срабатывания на машине с двумя активными арендами — в тот же день, без нашего участия:

боевые срабатыванияlog
13:11:20 ЗАЛИПАНИЕ: биржа молчит 168 с — сбрасываю кэш
13:12:08   ВЫЛЕЧЕНО: heartbeat=6
17:48:52 ЗАЛИПАНИЕ: биржа молчит 178 с — сбрасываю кэш
17:49:40   ВЫЛЕЧЕНО: heartbeat=5

Сорок восемь секунд на лечение, обе аренды продолжили работать. Хозяин узнал об этом только из журнала.

Быстрая проверка вручную

Если хочется просто посмотреть, всё ли в порядке прямо сейчас — три строки:

состояние связи с биржейbash
echo "контроллер: $(cat /var/lib/vastai_kaalia/controller_connection)"
echo "heartbeat:  $(tail -300 /var/lib/vastai_kaalia/kaalia.log | grep -c Heartbeat)"
echo "keepalive:  $(tail -300 /var/lib/vastai_kaalia/kaalia.log | grep -c keepalive)"

Heartbeat больше нуля — связь есть, всё хорошо. Heartbeat ноль при живом keepalive — залипание, сторож должен сработать в ближайшие минуты.

Коротко

  • Машина может числиться в каталоге, быть верифицированной и при этом не отвечать бирже — признак один: heartbeat ноль при живом keepalive
  • Ни канал, ни туннель, ни VPS тут ни при чём: открытый порт контроллера ничего не доказывает, молчит служба уровня приложения
  • Причина — агент запомнил адрес контроллера и держится за него, даже когда тот умер
  • Лечение занимает секунды: стереть кэш и перезапустить агента, клиенты не страдают
  • Списки живых адресов бесполезны — они меняются за часы; реагировать надо на симптом
  • Сторож окупается с первого срабатывания: у нас он дважды за день спас машину с двумя арендами

Нужна помощь с переходом?

Сделаем настройку под ключ с гарантией запуска.

Смотреть услуги