keepalived: оба узла считают себя главным
Оба узла поднимают общий адрес, когда не видят объявлений друг друга. Каждый считает соседа умершим и берёт адрес себе. Сеть получает два ответа на один адрес, соединения рвутся непредсказуемо. Причина почти всегда в блокировке служебного трафика, а не в настройках приоритетов.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Служебный трафик VRRP блокируется
Объявления идут отдельным протоколом на групповой адрес. Брандмауэр по умолчанию его не пропускает, и узлы друг друга не видят.
-
Разные идентификаторы группы или пароли
Узлы с разными идентификаторами группы не считают друг друга участниками одной пары, даже если трафик проходит.
-
Служба запускается раньше готовности сети
Если адрес интерфейса ещё не назначен, служба не может отправлять объявления и уходит в главное состояние по умолчанию.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Переходы между состояниями: видно, когда узел взял адрес.
sudo journalctl -u keepalived -n 30 --no-pagerПоднят ли общий адрес на этом узле прямо сейчас.
ip -brief addr | grep -F "$(grep -A3 virtual_ipaddress /etc/keepalived/keepalived.conf | grep -oE '[0-9.]+/[0-9]+' | head -1)" 2>/dev/null || ip -brief addrИдут ли объявления VRRP — самая прямая проверка.
sudo tcpdump -ni any proto 112 -c 5 2>/dev/nullРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- Объявления идут отдельным протоколом на групповой адрес. Брандмауэр по умолчанию его не пропускает, и узлы друг друга не видят.
- Как проверить
-
Посмотрите состояние узлов и правила брандмауэра.
sudo journalctl -u keepalived -n 20 --no-pager | grep -iE "MASTER|BACKUP" sudo nft list ruleset 2>/dev/null | grep -iE "vrrp|224.0.0.18" || sudo iptables -S | grep -iE "vrrp|224.0.0.18"
- Как исправить
- Разрешите протокол VRRP между узлами и трафик на его групповой адрес. Без этого любые настройки приоритетов бессмысленны.
- Почему происходит
- Узлы с разными идентификаторами группы не считают друг друга участниками одной пары, даже если трафик проходит.
- Как проверить
-
Сравните идентификаторы и аутентификацию на обоих узлах.
grep -iE "virtual_router_id|auth_pass|priority" /etc/keepalived/keepalived.conf
- Как исправить
- Приведите идентификатор группы и пароль к одинаковым значениям на обоих узлах, а приоритеты сделайте разными.
- Почему происходит
- Если адрес интерфейса ещё не назначен, служба не может отправлять объявления и уходит в главное состояние по умолчанию.
- Как проверить
-
Посмотрите порядок запуска и время назначения адресов.
systemctl show keepalived -p After -p Wants journalctl -b --no-pager | grep -iE "keepalived|network-online" | head -10
- Как исправить
-
Добавьте ожидание готовности сети в unit-файл службы и убедитесь, что служба ожидания сети включена.
[Unit] After=network-online.target Wants=network-online.target
Пример вывода
Оба узла перешли в главное состояние. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
keepalived[1300]: (VI_1) Entering MASTER STATE
keepalived[1300]: (VI_1) setting VIPs.
keepalived[1300]: Sending gratuitous ARP on eth0 for 192.0.2.50
# на втором узле в это же время:
keepalived[1290]: (VI_1) Entering MASTER STATE
Связанные ошибки
- Cannot assign requested address при привязке Ошибка 99 при привязке: адрес не принадлежит машине или ещё не поднят. Разбор с network-online.target и ip_nonlocal_bind.
- Цель не достигнута: служба ждёт target, который не наступает Служба не запускается, потому что не достигнута цель из After= или Requires=. Разбор целей multi-user, network-online, graphical.
- Интерфейс не настроен: systemd-networkd не применил описание Сеть не поднимается: файл описания не подхвачен, интерфейс под управлением другой службы, неверное совпадение по имени.
- Address already in use при запуске службы Порт или адрес уже занят: bind() failed (98: Address already in use). Как найти владельца порта и что делать с остатками прежнего процесса.
- Automount: каталог монтируется не вовремя или отваливается Автомонтирование через .automount: как работает TimeoutIdleSec, почему ресурс отваливается и когда лучше обычный .mount.
- Broken pipe в журнале службы Запись в закрытый канал или соединение: клиент отключился, обработчик завершился, конвейер разорван.
- Connection refused в журнале службы Соединение отклонено: служба не может подключиться к базе, кешу или другому сервису. Порядок запуска, адрес, брандмауэр.
- Connection reset by peer в журнале службы Соединение сброшено другой стороной: обрыв клиента, перезапуск сервера, промежуточное устройство.
Источники
- Документация keepalived
-
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено блокировкой протокола VRRP между двумя узлами.