Harden frr_anycast against unattended-upgrade-triggered route flush

Prod-инцидент: apt-daily-upgrade обновил libc6 -> postinst вызвал
рестарт зависимых юнитов -> перезапустился systemd-networkd -> он
вычистил из ядра BGP-маршруты zebra (KeepConfiguration не был задан,
networkd по умолчанию удаляет "чужие" маршруты при старте). Zebra не
знала о вычистке, трафик встал до ручного restart frr. Повторилось
10 сентября с обновлением systemd, но было замаскировано плейбуком.

Роль frr_anycast теперь защищает от этого класса сбоя безусловно:
- отключены apt-daily/apt-daily-upgrade (20auto-upgrades + маскирование
  таймеров и сервисов) - обновления пакетов только вручную;
- systemd-networkd получает drop-in KeepConfiguration=yes - устраняет
  сам механизм вычистки маршрутов при любом будущем рестарте networkd,
  не только от конкретного пакета-триггера;
- новый handler Restart systemd-networkd между Apply netplan и Restart
  frr (networkd должен переустановить владение интерфейсами до того,
  как zebra переустановит маршруты).

Шаблоны FRR/nftables не затронуты: render-check.sh 6/6,
render-check-cloud.sh 84/84, без изменений.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Bc3HkMiDwooSyLBLoMKNyF
This commit is contained in:
ayurishchevandClaude Sonnet 5 committed 2026-09-11 13:09:17 +03:00
1 parent 804fee4ffa
commit 72367682b5
5 files changed
+122 -1

No files matched your search

+9
View File
@@ -165,3 +165,12 @@ ansible/tests/render-check-cloud.sh # 4 соседа, prepend только н
`render-check-cloud.sh` проверяет: у каждого из 4 узлов ровно 4 `neighbor ... remote-as`, outbound `route-map` навешан на всех — `RM-OUT-PREPEND` (фильтр + `set as-path prepend 65200 65200 65200`) на 2×65103, `RM-OUT` (только фильтр) на 2×65104, `nftables.conf` содержит DNAT (`dnat to 95.163.53.117`) и `masquerade` на заданном внешнем интерфейсе, а также (если `nft` доступен на control node) валидирует синтаксис каждого `nftables.conf` через `nft -c -f`.
Детали и разбор диаграммы: [docs/2026-09-09-ansible-site-cloud-plan.md](docs/2026-09-09-ansible-site-cloud-plan.md) / [docs/2026-09-09-ansible-site-cloud-summary.md](docs/2026-09-09-ansible-site-cloud-summary.md).
## Защита от auto-update-триггеров и networkd route-flush
Прод-инцидент: `apt-daily-upgrade` обновил `libc6` → postinst вызвал рестарт зависимых юнитов → перезапустился `systemd-networkd` → он вычистил из ядра BGP-маршруты zebra (не «свои» для него) → трафик встал до ручного `systemctl restart frr`. Роль `frr_anycast` теперь защищает от этого класса сбоя безусловно, на всех узлах обеих сред:
- **Обновления только по требованию администратора**: `/etc/apt/apt.conf.d/20auto-upgrades` отключает периодические `apt update`/unattended-upgrade, дополнительно замаскированы `apt-daily.timer`/`apt-daily-upgrade.timer` и их `.service`. `apt upgrade` по-прежнему доступен вручную.
- **`systemd-networkd` не вычищает чужие маршруты**: drop-in `/etc/systemd/networkd.conf.d/99-keep-configuration.conf` (`KeepConfiguration=yes`) — защита не от конкретного пакета-триггера, а от самого механизма, на случай **любого** будущего рестарта networkd.
Не влияет на рендер `frr.conf`/`daemons`/`nftables.conf` — `render-check.sh`/`render-check-cloud.sh` проходят без изменений. Детали: [docs/2026-09-11-system-hardening-plan.md](docs/2026-09-11-system-hardening-plan.md) / [docs/2026-09-11-system-hardening-summary.md](docs/2026-09-11-system-hardening-summary.md).