ftops.space
84 subscribers
555 photos
98 videos
33 files
278 links
ftops.space
Сервера на linux, FreeBSD, сети на микротик и сиськах.
Download Telegram
🧭 Навигатор по материалам канала

Используйте теги для быстрого поиска нужной фактуры:

#постмортем — Разборы реальных аварий
Анатомия сбоев по единому стандарту: Симптом ➔ Ложная гипотеза ➔ Что показал tcpdump/dmesg ➔ Архитектурное исправление.
— Как Happy Eyeballs (RFC 6555) и чистый Go-резолвер уронили кластерный инференс AI.
— BGP-петля транзитного оператора на 450 мс, которую мониторинг принял за OOM Killer.
— Паника Kubelet ImageGC при пороге 80% на VPS с диском 20 ГБ.
— Залипание WireGuard-пиров после смены NAT и лечение через FDB.

#архитектура — Схемы сетей, оверлеи и отказоустойчивость
Чертежи межсерверного взаимодействия, маршрутизация и обход сетевых аномалий.
— Двуххабовая топология AmneziaWG (Forest ➔ Failover Hub Pumpkin) с обходом блокировок UDP.
— Policy routing, fwmark и чистый европейский egress через туннели awg-goog.
— DNAT-трансляция устаревших подсетей внутри Cloudflare Zero Trust туннелей.
— Разделение control-plane и worker-нод в условиях жесткого DPI.

#экономика — Трезвая математика TCO (Bare-Metal vs Cloud)
Реальные расчеты расходов, скрытые налоги облачных провайдеров и границы применимости.
— 17 нод на K3s за €48/мес против аналогичного сетапа в AWS EKS за $540.
— «Налог на лень»: сколько на самом деле стоят AWS NAT Gateway и межзональный трафик.
— Инженерный налог: почему дешевое железо требует строгих сторожевых таймеров (watchdogs).

#паттерны — Конфиги, проверенные в продакшене
Готовые сниппеты, systemd-юниты, скрипты гигиены и правила фильтрации.
— Юнит аварийного блокирования неотфильтрованного IPv6 для Go-бинарников.
— Blackhole для QUIC (UDP/443) в Xray и Hysteria2 для спасения длинных gRPC-сессий.
— Автоматический watchdog туннелей с pre-armed rollback таймерами.
— Сжатие ротированных логов (gzip -9) и чистка containerd без простоя подов.
──────
ftops.space pinned «🧭 Навигатор по материалам канала …»
Ошибочная вера в скорость современных NVMe-накопителей заставляет системных инженеров включать привычный swap-файл на диске для страховки от OOM. На распределенных нодах K3s это приводит к деградации: при всплеске нагрузки kswapd начинает сбрасывать неактивные анонимные страницы на диск. Даже при микронных задержках NVMe очередь блокировок в block layer ядра моментально возрастает. Поток direct reclaim замораживает системные вызовы, контейнерный рантайм пропускает heartbeat, а Kubernetes помечает рабочий узел как NotReady. Отказ от дискового свопа в пользу Zram кардинально меняет механики ядра Linux. Zram создает виртуальное сжатое блочное устройство непосредственно в RAM, используя алгоритмы LZ4 или ZSTD. При сбросе страниц ядро выполняет сжатие памяти в CPU за единицы микросекунд, избегая обращения к дисковой шине и физическим накопителям. В результате пропадает I/O wait, а подсистема управления памятью продолжает работать с детерминированной задержкой. Конфигурация Zram требует пере...
Ошибочная вера в скорость современных NVMe-накопителей заставляет системных инженеров включать привычный swap-файл на диске для страховки от OOM. На распределенных нодах K3s это приводит к деградации: при всплеске нагрузки kswapd начинает сбрасывать неактивные анонимные страницы на диск. Даже при микронных задержках NVMe очередь блокировок в block layer ядра моментально возрастает. Поток direct reclaim замораживает системные вызовы, контейнерный рантайм пропускает heartbeat, а Kubernetes помечает рабочий узел как NotReady. Отказ от дискового свопа в пользу Zram кардинально меняет механики ядра Linux. Zram создает виртуальное сжатое блочное устройство непосредственно в RAM, используя алгоритмы LZ4 или ZSTD. При сбросе страниц ядро выполняет сжатие памяти в CPU за единицы микросекунд, избегая обращения к дисковой шине и физическим накопителям. В результате пропадает I/O wait, а подсистема управления памятью продолжает работать с детерминированной задержкой. Конфигурация Zram требует пересмотра классического тюнинга ядра: - vm.swappiness установите в значение 180 или 200. Это заставляет ядро агрессивно вытеснять анонимную память в сжатый Zram, освобождая несжатую RAM под кеши файловой системы. - vm.watermarkboostfactor сбросьте в 0 для предотвращения ухода ядра в глубокую рекультивацию страниц при кратковременных спайках. - Алгоритм сжатия выбирайте LZ4 для минимальной нагрузки на vCPU или ZSTD для максимальной плотности упакованной памяти. Полный отказ от физических дисков в цепочке своппинга переводит управление дефицитом памяти из области медленного storage I/O в область быстрых процессоров. Тюнинг bare-metal инфраструктуры и сетевого стека ядра разбираем на https://ftops.space.
TCP BBR vs Cubic: почему алгоритм перегрузки решает больше, чем железо

Cubic управляет окном перегрузки по потерям пакетов. В датацентре это терпимо: потери редки, round-trip time предсказуем. На WAN-линках с буферизацией на транзитных узлах (bufferbloat) Cubic раздувает окно до потерь, потом резко режет его вдвое. Итог: пилообразный throughput и латентность, которая прыгает в 3-5 раз от базовой.

BBR строит модель канала иначе. Он оценивает максимальную пропускную способность (BtlBw) и минимальный RTT, и удерживает окно ровно там, где канал заполнен без очереди. Потери для него — шум, а не сигнал. На линках с 1% случайных потерь BBR даёт в 2-25 раз больший throughput, чем Cubic, в зависимости от RTT и глубины буфера на пути.

Включается в одну строку:

sysctl -w net.ipv4.tcpcongestioncontrol=bbr
sysctl -w net.core.defaultqdisc=fq

fq (fair queue) обязателен: без него BBR не может корректно зондировать канал. Дополнительно для высоконагруженного шлюза:

net.core.rmem
ma...
TCP BBR vs Cubic: почему алгоритм перегрузки решает больше, чем железо

Cubic управляет окном перегрузки по потерям пакетов. В датацентре это терпимо: потери редки, round-trip time предсказуем. На WAN-линках с буферизацией на транзитных узлах (bufferbloat) Cubic раздувает окно до потерь, потом резко режет его вдвое. Итог: пилообразный throughput и латентность, которая прыгает в 3-5 раз от базовой.

BBR строит модель канала иначе. Он оценивает максимальную пропускную способность (BtlBw) и минимальный RTT, и удерживает окно ровно там, где канал заполнен без очереди. Потери для него — шум, а не сигнал. На линках с 1% случайных потерь BBR даёт в 2-25 раз больший throughput, чем Cubic, в зависимости от RTT и глубины буфера на пути.

Включается в одну строку:

sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl -w net.core.default_qdisc=fq

fq (fair queue) обязателен: без него BBR не может корректно зондировать канал. Дополнительно для высоконагруженного шлюза:

net.core.rmem_max = 134217728
net.core.wmem_max = 134217728
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
net.ipv4.tcp_fastopen = 3

Отдельная история — ethtool и прерывания. ethtool -G ethX rx 4096 увеличивает ring buffer, снижая потери при burst-трафике. Но ethtool -s ethX speed 1000 duplex full autoneg off на живом порту может мгновенно сбросить линк — интерфейс уходит в re-negotiation. На production это означает потерю сессий. Всегда проверяй, что autoneg на обоих концах ведёт себя одинаково, прежде чем трогать скорость вручную.

eBPF и XDP добавляют ещё один уровень: с XDP_DROP на входе NIC ты фильтруешь мусор до аллокации skb. На 10G линке это разница между 14 Mpps wire rate и провалом в kernel stack, который упирается в ~3-4 Mpps на ядро без DPDK.

https://ftops.space
Воскресенье. Самое честное время недели.

Можно строить планы на бумаге, а потом смотреть как реальность их аккуратно переписывает.

На эту неделю у меня:

- Миграция одного из сервисов iris-loyalty на свежую ноду в K3s кластере. Там накопился технический долг, который уже начинает мешать.
- Longhorn snapshots — надо нормально настроить ротацию, сейчас руками слежу что само по себе плохая практика.
- AmneziaWG mesh — документация. Да, я тот человек который сначала строит, потом пишет про это. Живая инфра важнее wiki.
- femida-tech.ru — там ждут несколько задач по AI-пайплайну. Два с половиной года проекту, и каждую неделю что-то новое.

Пятница покажет сколько из этого реально закрылось.

ftops.space — там пишу про инфру когда нахожу время между инцидентами.
Pedit COW (CVE-2026-46331) наглядно разделяет два понятия: изоляция процесса и безопасность ядра. chroot скрывает дерево файлов, cgroups v2 режут CPU и память, seccomp сокращает набор syscall — но все контейнеры по-прежнему используют один kernel image. Опасная цепочка на узлах K3s выглядит так: - unprivileged user namespace включён; - внутри namespace появляется CAPNETADMIN; - доступен netlink и traffic control; - ошибка в actpedit превращается в запись в page cache. Минимальный регламент для bare-metal: - обновить kernel до версии с исправлением CVE-2026-46331; - проверить user.maxusernamespaces и отключить unshare там, где он не нужен; - запускать workload с seccomp-профилем без socket, bpf, perfevent и необязательных netlink-операций; - назначить cgroup v2 memory.max и pids.max, чтобы авария не стала DoS; - считать host kernel критической общей зависимостью при каждом threat model review. Подробные разборы изоляции, K3s и сетевого стека: https://ftops.space
ПОСТМОРТЕМ: Как RFC 6555 (Happy Eyeballs) в чистом Go деградировал P99 латенси AI-инференса на 300 мс

Окружение: Bare-metal K3s кластер ftops.space, Go-микросервис (Go 1.22, pure net/http) в роли локального API-маршрутизатора к VLLM-эндпоинтам. IPv4 /24 внутренний mesh, IPv6 на нодах включен локально, но глобальный egress закрыт на файрволе через DROP (без REJECT).

---

1. Что сломалось
При нагрузке 450 RPS на локальный vLLM-инференс P99 латенси вырос с 12 мс до 312 мс. При этом CPU и GPU инференс-узлов загружены всего на 18%. Каждые ~10-15 запросов получали необъяснимую задержку ровно в 300 мс перед началом потоковой генерации токенов (Server-Sent Events).

2. Ложная гипотеза
Инженеры грешили на работу cgroup memory limit и задержки в GC Go. В системном /etc/gai.conf была явно прописана директива precedence ::ffff:0:0/96 100, чтобы приоритезировать IPv4-трафик над IPv6 в getaddrinfo(). Однако изменения в /etc/gai.conf абсолютно никак не влияли на метрики.

3. Что показал tcpdump и dmesg
Снятие дампа на veth-интерфейсе пода (tcpdump -i any port 53 or port 8080 -nn -ttt) вскрыло следующую картину:
1. net.Dialer из Go генерирует параллельные DNS-запросы типа A (IPv4) и AAAA (IPv6) через встроенный Go-резолвер (net/dnsclient_unix.go), полностью игнорируя libc и /etc/gai.conf (так как Go собран с CGO_ENABLED=0).
2. Резолвер получает ответы для обоих типов записей. RFC 6555 (Happy Eyeballs v2 / RFC 8305) стартует соединение по IPv6.
3. Пакет SYN на IPv6 уходит в тупиковый маршрут и тихо дропается на Edge-фаерволе без ICMPv6 Destination Unreachable.
4. Таймер FallbackDelay в net.Dialer составляет строго 300 мс по умолчанию. Запрет на переключение длится ровно 300 мс, прежде чем Go попробует установиться по IPv4.

4. Архитектурный фикс
Внедрено двухуровневое решение для исключения синтетических задержек:

1. Явное отключение IPv6 в DialContext Go-клиента:
```go
transport := &http.Transport{
DialContext: (&net.Dialer{
Timeout: 30 time.Second,
KeepAlive: 30 time.Second,
// Выключаем дублирующие AAAA запросы и Fallback
Resolver: &net.Resolver{
PreferGo: true,
},
}).DialContext,
}
// Использование custom net.Dialer с forced IP family
Удалить swapfile недостаточно, чтобы исключить дисковый своп. У zram есть собственный механизм writeback: при настроенном backingdev и запуске выгрузки страницы отправляются на блочное устройство. Поэтому единственная строка /dev/zram0 в списке свопа ещё не подтверждает, что страницы остаются в RAM. Механизм описан в [документации ядра](https://cdn.kernel.org/doc/html/latest/admin-guide/blockdev/zram.html). Проверка состоит из трёх пунктов: swapon --show — какие области свопа активны; /sys/block/zram0/backingdev — назначено ли хранилище для выгрузки; /sys/block/zram0/bdstat — были ли обращения к нему. Если требование — своп исключительно в памяти, отдельный NVMe swapfile и backing device у zram должны отсутствовать. Высокий приоритет zram этого требования не обеспечивает. Следующий контроль — реальная цена сжатия. В /sys/block/zram0/mmstat сравнивают origdatasize с memusedtotal: последний учитывает расход памяти вместе с накладными расходами. disksize задаёт логическую ёмкость,...
Удалить swapfile недостаточно, чтобы исключить дисковый своп. У zram есть собственный механизм writeback: при настроенном backing_dev и запуске выгрузки страницы отправляются на блочное устройство. Поэтому единственная строка /dev/zram0 в списке свопа ещё не подтверждает, что страницы остаются в RAM. Механизм описан в [документации ядра](https://cdn.kernel.org/doc/html/latest/admin-guide/blockdev/zram.html). Проверка состоит из трёх пунктов: swapon --show — какие области свопа активны; /sys/block/zram0/backing_dev — назначено ли хранилище для выгрузки; /sys/block/zram0/bd_stat — были ли обращения к нему. Если требование — своп исключительно в памяти, отдельный NVMe swapfile и backing device у zram должны отсутствовать. Высокий приоритет zram этого требования не обеспечивает. Следующий контроль — реальная цена сжатия. В /sys/block/zram0/mm_stat сравнивают orig_data_size с mem_used_total: последний учитывает расход памяти вместе с накладными расходами. disksize задаёт логическую ёмкость, mem_limit ограничивает потребление RAM устройством. Плохо сжимаемые данные быстро съедают выигрыш; сжатие также требует CPU. Отказ от дискового свопа исключает дисковые обращения именно из этого пути работы с памятью. Гарантии «спасения ядра» он не даёт: zram расходует ту же RAM, и OOM остаётся возможным. Для bare-metal регламент должен задавать бюджет памяти и условия остановки нагрузки. Конфигурацию принимают по поведению при исчерпании ресурсов: https://ftops.space.
Патч CVE-2026-46331 (Pedit COW) требует обновления ядра, но именно этот шаг запускает самый опасный участок цепочки: DKMS пересобирает внешние модули под новый ABI. WireGuard, ZFS, NVIDIA и сетевые offload-модули могут собратьcя с ошибкой, а пакет ядра всё равно установится. Перед перезагрузкой проверяю: - dkms status — модуль и версия ядра в состоянии installed; - find /lib/modules/$(uname -r) -name 'wireguard.ko' — модуль реально присутствует; - modprobe -n wireguard — загрузка разрешена; - dracut -f или update-initramfs завершились без ошибок. В CI для bare-metal держу smoke-тест: новая нода загружается, поднимает wg0, проходит handshake с двумя peer и сохраняет маршрут до control-plane. Старое ядро оставляю первым fallback в GRUB, а autoremove блокирую до успешного теста. Подробные регламенты для K3s и WireGuard mesh: https://ftops.space
K3s поверх WireGuard — это не «сам себе Kubernetes». Это способ оставить control plane, сеть и отказоустойчивость в своей зоне ответственности.

Managed Kubernetes удобен, пока инфраструктура укладывается в чужую модель: разрешённые регионы, внешний IAM, публичные endpoint’ы, навязанный CNI и тарифы за каждый слой. В bare-metal схеме control plane живёт на своих узлах, WireGuard даёт закрытый transport между площадками, а Cilium — прозрачную сетевую политику и наблюдаемость на уровне eBPF.

Но суверенность не появляется от одного install.sh. etcd чувствителен к latency и jitter: растянутая quorum по нестабильному WAN превращает любой сетевой сбой в выборы лидера и задержки API. Longhorn тоже требует дисциплины: быстрые диски, понятные failure domains, резервные копии вне кластера и контроль rebuild traffic.

Рабочая схема начинается с измерений: RTT между control-plane, packet loss, IOPS, время восстановления и поведение при потере ноды. K3s сокращает операционный шум, но не отменяет инженерную ответственность. Подробная практика: https://ftops.space

#ftops #devops #linux #freebsd #sre #инфраструктура
Почему K3s поверх WireGuard, а не managed k8s — для тех, кому нужна своя инфраструктура, а не аренда чужой.

Считаем честно. Managed-кластер EKS или GKE сначала подкупает: control plane бесплатно (на бумаге), апгрейды сами, метрики в коробке. Но за это ты платишь трижды. Во-первых, lock-in: autoscaler, ingress, сетевые политики завязаны на провайдерскую магию, и уйти оттуда с работающим стеком — задача на недели. Во-вторых, latency: etcd и API-сервер живут у провайдера, и каждый узел ходит к ним через чужой маршрут. В-третьих, счёт: узлы с премией за «управляемость», исходящий трафик за каждую egress-болванку, балансировщики по тарифу.

K3s на bare-metal решает ровно этот слой боли. Один бинарь с встроенным etcd (или SQLite для малого), управление через systemd, никакого внешнего рантайма. Но главное — сеть. WireGuard поднимает flat-меш между нодами: wg0 на каждом хосте, публичные ключи в Ansible-инвентаре, MTU выставлен под over-head. Внутри — Cilium CNI. Ты получаешь eBPF-программиру...
Почему K3s поверх WireGuard, а не managed k8s — для тех, кому нужна своя инфраструктура, а не аренда чужой.

Считаем честно. Managed-кластер EKS или GKE сначала подкупает: control plane бесплатно (на бумаге), апгрейды сами, метрики в коробке. Но за это ты платишь трижды. Во-первых, lock-in: autoscaler, ingress, сетевые политики завязаны на провайдерскую магию, и уйти оттуда с работающим стеком — задача на недели. Во-вторых, latency: etcd и API-сервер живут у провайдера, и каждый узел ходит к ним через чужой маршрут. В-третьих, счёт: узлы с премией за «управляемость», исходящий трафик за каждую egress-болванку, балансировщики по тарифу.

K3s на bare-metal решает ровно этот слой боли. Один бинарь с встроенным etcd (или SQLite для малого), управление через systemd, никакого внешнего рантайма. Но главное — сеть. WireGuard поднимает flat-меш между нодами: wg0 на каждом хосте, публичные ключи в Ansible-инвентаре, MTU выставлен под over-head. Внутри — Cilium CNI. Ты получаешь eBPF-программируемую сеть на уровне ядра: Service Mesh без sidecar, NetworkPolicy, что реально бьются, L7-фильтрация, Hubble для observability. Managed-провайдер такого уровня контроля над путём пакета не даст — у него политика «не трогай dataplane».

Отдельная статья — хранилище. Longhorn поверх локальных дисков вместо облачных persistent-volume с их таймингами и сюрпризами по IOPS. Реплики распределяются по mesh, снапшоты и бэкапы в S3 — и это живёт на твоём железе, ноды в одной физической локации, latency до etcd считан в единицы миллисекунд, а не в десятки через интернет.

Когда mesh собран правильно, отказ одного узла — это не инцидент, а штатное событие: Quorum у etcd сохраняется, Cilium перестилает маршруты, Longhorn переизбирает реплику. Никакого звонка в поддержку провайдера с тикетом «у нас прод упал, ускорьте». Ты сам для себя поддержка, и это не минус, а определение суверенитета.

#ftops #devops #linux #freebsd #sre #инфраструктура
IaC должен описывать не только сборку, но и аварию

Terraform хорошо создает контур, Ansible хорошо доводит систему до рабочего состояния, immutable Linux хорошо режет дрейф. Но зрелая инфраструктура начинается там, где в коде описан не только счастливый путь, а сценарий поломки: потеря ноды, битый маршрут, откат конфига, пересоздание сервиса с нуля и проверка, что данные остались живы.

Самая частая ошибка в IaC — считать репозиторий источником правды, пока продакшн живет своей жизнью. Вручную поправили nginx, изменили sysctl, подкрутили WireGuard peer, забыли внести в код. Через месяц Terraform и Ansible уже не восстанавливают систему, а спорят с ней. Это не автоматизация. Это архив старых намерений.

На критичных узлах я нормально отношусь к chattr +i для отдельных конфигов, но только как к предохранителю, а не как к культуре управления. immutable-флаг должен защищать от случайной руки в продакшне, а не заменять pipeline. Правильная схема простая: изменение идет через git, CI проверяет diff, Ansible снимает защиту, применяет конфиг, возвращает chattr +i и оставляет в логах причину изменения.

Инфраструктура считается воспроизводимой не когда playbook проходит на чистой VM. Она считается воспроизводимой, когда ты можешь в коде поднять копию аварии и доказать восстановление: тот же инвентарь, те же роли, те же секреты из vault, та же проверка маршрутов, quorum, backup restore и сервисных healthcheck. Без этого IaC просто красиво хранит YAML.

https://ftops.space

#ftops #devops #linux #freebsd #sre #инфраструктура
Инфраструктура как код — это не про скрипты, а про воспроизводимость

Когда продакшн падает в субботу в три часа ночи, тебе не нужно вспоминать, какую кнопку нажал коллега полгода назад. Тебе нужен код, который из пустого железа поднимает всё заново: разметка дисков, сеть, ключи, сервисы, роуты. Ansible и Terraform здесь не модные тулзы, а единственный способ не быть единственной точкой отказа в собственной команде.

Неизменяемая система (immutable Linux) идёт дальше. Образ собирается один раз, запекается, проверяется в CI и выкатывается на ноды целиком. Если что-то пошло не так — не чинишь руками, а откатываешься на предыдущий проверенный образ. Патчинг из ритуала с шаманскими бубнами превращается в версионирование артефакта.

Отдельная тема — защита критичных конфигов на проде. chattr +i на fstab, sshd_config и ключах. Это не паранойя, это защита от самого себя в три часа ночи, когда рука тянется быстро поправить и перезапустить. Иммутабельность превращает случайное изменение в ошибку, которую невозможно сделать молча.

Воспроизводимость аварии — высший пилотаж. Инцидент переводится в сценарий: та же команда, тот же конфиг, то же состояние. Пока авария не воспроизводится по кнопке — она не закрыта, а просто притихла.

#ftops #devops #linux #freebsd #sre #инфраструктура
Автоматический бэкап etcd в S3 создает у инженеров опасное чувство защищенности. В K3s встроенный механизм etcd-snapshot отлично отправляет снимки состояния в S3-хранилище, но процесс катастрофического восстановления (Disaster Recovery) на bare-metal превращается в хаос, если пытаться применить снепшот на работающем кластере без подготовки нод контрол-плейна. Главная ошибка при сбое — запуск процедуры восстановления на одном из мастеров при живых остальных. В этот момент etcd упирается в рассинхронизацию Cluster ID и отказ кворума. Нативный регламент восстановления требует жесткой последовательности действий: 1. Полная остановка службы k3s на всех нодах управления. 2. Физическая очистка каталога /var/lib/rancher/k3s/server/db/ на всех ведомых нодах, чтобы вычистить старое состояние etcd. 3. Выполнение команды k3s server --cluster-reset с указанием параметров S3 и имени снимка строго на одном первичном мастере. При выполнении cluster-reset K3s переинициализирует etcd в режим одиночного ...
Автоматический бэкап etcd в S3 создает у инженеров опасное чувство защищенности. В K3s встроенный механизм etcd-snapshot отлично отправляет снимки состояния в S3-хранилище, но процесс катастрофического восстановления (Disaster Recovery) на bare-metal превращается в хаос, если пытаться применить снепшот на работающем кластере без подготовки нод контрол-плейна. Главная ошибка при сбое — запуск процедуры восстановления на одном из мастеров при живых остальных. В этот момент etcd упирается в рассинхронизацию Cluster ID и отказ кворума. Нативный регламент восстановления требует жесткой последовательности действий: 1. Полная остановка службы k3s на всех нодах управления. 2. Физическая очистка каталога /var/lib/rancher/k3s/server/db/ на всех ведомых нодах, чтобы вычистить старое состояние etcd. 3. Выполнение команды k3s server --cluster-reset с указанием параметров S3 и имени снимка строго на одном первичном мастере. При выполнении cluster-reset K3s переинициализирует etcd в режим одиночного узла и генерирует новый идентификатор кластера. Однако восстановленная из S3 база данных все еще содержит старые записи о топологии и IP-адресах прошлых участников. До запуска остальных мастеров необходимо удалить неактивные ноды через kubectl и убедиться в корректности состояния API-сервера. Только после того как первичный мастер перешел в здоровый статус, ведомые узлы запускаются для чистой повторной инициализации etcd-репликации. Настоящая отказоустойчивость проверяется не наличием архива в облаке, а автоматизированным скриптом сброса локальных состояний нод. Технические разборы архитектуры K3s и сетевого стека ядра публикуются на https://ftops.space.
Автоматическая выгрузка S3-снепшотов etcd в K3s создает ложное чувство защищенности. Команда аварийного восстановления с флагами cluster-reset и cluster-reset-restore-path инициализирует новый etcd cluster ID и пересоздает ансамбль с единственным ведущим узлом. Если попытаться выкатить снепшот на одну из нод без предварительного отключения и очистки остальных участников control plane, система уходит в невосстановимый сплит-брейн. Главная техническая ловушка заключается в расхождении состояния Raft-журнала и сетевого стека. Сохранившиеся ноды master продолжают считать старый cluster ID валидным и отвергают TLS-handshake от восстановленного лидера. Параллельно с этим возникает рассинхрон WireGuard mesh: таблицы адресации и туннельные интерфейсы, восстановленные из S3-снепшота, содержат устаревшие привязки pod CIDR. В результате etcd рапортует об успехе, пока межсерверный трафик молча уходит в blackhole ядра. Регламент аварийного поднятия кластера на bare-metal требует жесткой последовате...
Автоматическая выгрузка S3-снепшотов etcd в K3s создает ложное чувство защищенности. Команда аварийного восстановления с флагами cluster-reset и cluster-reset-restore-path инициализирует новый etcd cluster ID и пересоздает ансамбль с единственным ведущим узлом. Если попытаться выкатить снепшот на одну из нод без предварительного отключения и очистки остальных участников control plane, система уходит в невосстановимый сплит-брейн. Главная техническая ловушка заключается в расхождении состояния Raft-журнала и сетевого стека. Сохранившиеся ноды master продолжают считать старый cluster ID валидным и отвергают TLS-handshake от восстановленного лидера. Параллельно с этим возникает рассинхрон WireGuard mesh: таблицы адресации и туннельные интерфейсы, восстановленные из S3-снепшота, содержат устаревшие привязки pod CIDR. В результате etcd рапортует об успехе, пока межсерверный трафик молча уходит в blackhole ядра. Регламент аварийного поднятия кластера на bare-metal требует жесткой последовательности действий: - Полная остановка службы k3s на всех контроллер-нодах одновременно. - Полное удаление содержимого /var/lib/rancher/k3s/server/db на всех ведомых нодах master. - Выполнение восстановления на выделенном лидере через cluster-reset с явным указанием пути к S3-снепшоту. - Поочередный запуск ведомых нод с пустым локальным хранилищем etcd для штатного прохождения процедуры rejoin. - Принудительный сброс и перезапуск интерфейсов WireGuard для обновления таблиц маршрутизации ядра. Настоящий Disaster Recovery проверяется не наличием файлов в S3-бакете, а возможностью поднятия полностью согласованного кворума с нуля на изолированном сетевом сегменте. Разборы архитектуры bare-metal Kubernetes, сетевого стека ядра и сценариев disaster recovery публикуются в проекте https://ftops.space.