ftops.space
83 subscribers
610 photos
98 videos
33 files
361 links
ftops.space
Сервера на linux, FreeBSD, сети на микротик и сиськах.
Download Telegram
Managed Kubernetes был зеленым. Кластер уже разваливался

Мониторинг провайдера показывал healthy control plane, пока pod-to-pod трафик внутри WireGuard терял крупные пакеты. Причина оказалась не в Kubernetes: MTU оверлея не совпал с реальным маршрутом, MSS не зажимался, conntrack подошел к пределу. Облачная панель показывала норму, потому что ядро и сеть были спрятаны за SLA.

На bare metal с K3s расследование короче. Cilium дает наблюдаемость datapath и управляемую маршрутизацию, WireGuard оставляет межузловой трафик под нашим ключом, а счетчики ядра показывают правду без согласования с поддержкой. etcd размещается рядом с control plane, поэтому его latency определяется нашей топологией, а не соседями в чужом облаке.

Longhorn тоже не магия: реплики требуют предсказуемой сети и дисковой задержки. Если p99 etcd растет одновременно с retransmits и очередями диска, лечить надо физический контур, а не перезапускать pod. K3s не отменяет эксплуатацию — он возвращает оператору причинно-следственную связь.

Managed k8s продает снятие ответственности, но вместе с ней забирает контроль. Суверенная инфраструктура начинается там, где сеть, ключи, диски и журнал etcd принадлежат одной команде.

https://ftops.space

#ftops #devops #linux #freebsd #sre #инфраструктура
Инцидент: процесс запустили в chroot и назвали контейнером. Мониторинг показывал нормальные RSS и load average внутри клетки. На хосте росли memory.events, pids.current и pressure stall; соседние сервисы теряли CPU, пока аварийный процесс продолжал считать себя здоровым. Ядро не интересует маркетинговое название песочницы. Проверка: cat /proc/$PID/status \| egrep 'Cap(Eff\|Bnd)\|NoNewPrivs\|Seccomp'; cat /proc/$PID/cgroup; cat /sys/fs/cgroup/<slice>/memory.events; cat /sys/fs/cgroup/<slice>/pids.current; cat /proc/pressure/\{cpu,memory,io\}. Chroot ограничивает разрешение путей, но не syscalls, capabilities, PID-шторм и потребление ресурсов. Исправление: отдельный cgroup v2 с memory.max, memory.high, pids.max и cpu.max; capabilities сбросить; включить nonewprivs; seccomp строить по фактическому syscall-профилю и завершать процесс на нарушении. Свежая история с Pedit COW снова показывает цену разрешённой поверхности ядра: уязвимый syscall нельзя обезвредить красивым каталогом. Виртуал...
Инцидент: процесс запустили в chroot и назвали контейнером. Мониторинг показывал нормальные RSS и load average внутри клетки. На хосте росли memory.events, pids.current и pressure stall; соседние сервисы теряли CPU, пока аварийный процесс продолжал считать себя здоровым. Ядро не интересует маркетинговое название песочницы. Проверка: cat /proc/$PID/status \| egrep 'Cap(Eff\|Bnd)\|NoNewPrivs\|Seccomp'; cat /proc/$PID/cgroup; cat /sys/fs/cgroup/<slice>/memory.events; cat /sys/fs/cgroup/<slice>/pids.current; cat /proc/pressure/\{cpu,memory,io\}. Chroot ограничивает разрешение путей, но не syscalls, capabilities, PID-шторм и потребление ресурсов. Исправление: отдельный cgroup v2 с memory.max, memory.high, pids.max и cpu.max; capabilities сбросить; включить nonewprivs; seccomp строить по фактическому syscall-профилю и завершать процесс на нарушении. Свежая история с Pedit COW снова показывает цену разрешённой поверхности ядра: уязвимый syscall нельзя обезвредить красивым каталогом. Виртуализация нужна не всегда. Но дешёвая изоляция обязана быть многослойной и проверяться снаружи процесса. Практика эксплуатации bare metal: https://ftops.space
03:00. Сценарий отказа: после перехода на Cilium новые соединения сыплются таймаутами. Мониторинг обвиняет приложение, дежурный готовит рестарт. На хосте sysctl net.netfilter.nfconntrackcount net.netfilter.nfconntrackmax показывает запас. Ложный вывод: таблица соединений здорова. Проверили только conntrack Netfilter — у Cilium есть собственные BPF CT maps. В контейнере cilium-agent проблемной ноды запускаем cilium-dbg monitor --type drop и cilium-dbg bpf metrics list. Ищем CT: Map insertion failed и рост соответствующего счётчика потерь datapath. Это повод проверить заполнение CT maps и работу сборщика мусора, а не готовый диагноз переполнения: одна причина drop ещё не объясняет механизм ошибки. Такой путь диагностики описан в документации Cilium. Почему вообще уходят от iptables? Он тоже работает в ядре. Выигрыш Cilium — в другом месте принятия решения: при socket LB backend выбирается через cgroup-хук уже на connect(...
03:00. Сценарий отказа: после перехода на Cilium новые соединения сыплются таймаутами. Мониторинг обвиняет приложение, дежурный готовит рестарт. На хосте sysctl net.netfilter.nfconntrackcount net.netfilter.nfconntrackmax показывает запас. Ложный вывод: таблица соединений здорова. Проверили только conntrack Netfilter — у Cilium есть собственные BPF CT maps. В контейнере cilium-agent проблемной ноды запускаем cilium-dbg monitor --type drop и cilium-dbg bpf metrics list. Ищем CT: Map insertion failed и рост соответствующего счётчика потерь datapath. Это повод проверить заполнение CT maps и работу сборщика мусора, а не готовый диагноз переполнения: одна причина drop ещё не объясняет механизм ошибки. Такой путь диагностики описан в документации Cilium. Почему вообще уходят от iptables? Он тоже работает в ядре. Выигрыш Cilium — в другом месте принятия решения: при socket LB backend выбирается через cgroup-хук уже на connect(), а состояние сервисов хранится в BPF maps вместо цепочек правил kube-proxy. Это сокращает путь обработки, но сохраняет эксплуатационные лимиты. Механика — в описании kube-proxy replacement. План устранения после подтверждения нехватки ёмкости: ограничить шторм новых соединений, проверить повторное использование подключений, рассчитать размеры CT maps под память ноды и проверить GC. Критерий восстановления — успешные новые соединения под нагрузкой и прекращение роста соответствующих drops. Покупать ещё Kubernetes ради отсутствующего счётчика — дорогая форма суеверия. https://ftops.space
Учебный постмортем, 03:00: API отдаёт 503, RAM свободна, CPU скучает. Дежурный подозревает свежий seccomp-профиль. Сервис работает в chroot под cgroups v2; после увеличения параллелизма перестаёт создавать рабочие потоки. Облачная панель уже предлагает купить ещё одну машину. Проверка: strace -f -e trace\=clone,clone3 -p PID показывает EAGAIN. Путь группы берём из cat /proc/PID/cgroup. В соответствующем каталоге /sys/fs/cgroup читаем pids.current, pids.max и pids.events: в этом сценарии current достиг лимита, а счётчик max растёт при отказах. Проверяем также родительские группы: их ограничения действуют на потомков. Контроллер учитывает потоки по TID — это описано в документации ядра. Один EAGAIN ещё не доказывает срабатывание pids.max: проверяем также Max processes в /proc/PID/limits. Seccomp умеет возвращать заданный errno, поэтому сверяем загруженную политику; поле Seccomp в status не раскрывает её правила. Механиз...
Учебный постмортем, 03:00: API отдаёт 503, RAM свободна, CPU скучает. Дежурный подозревает свежий seccomp-профиль. Сервис работает в chroot под cgroups v2; после увеличения параллелизма перестаёт создавать рабочие потоки. Облачная панель уже предлагает купить ещё одну машину. Проверка: strace -f -e trace\=clone,clone3 -p PID показывает EAGAIN. Путь группы берём из cat /proc/PID/cgroup. В соответствующем каталоге /sys/fs/cgroup читаем pids.current, pids.max и pids.events: в этом сценарии current достиг лимита, а счётчик max растёт при отказах. Проверяем также родительские группы: их ограничения действуют на потомков. Контроллер учитывает потоки по TID — это описано в документации ядра. Один EAGAIN ещё не доказывает срабатывание pids.max: проверяем также Max processes в /proc/PID/limits. Seccomp умеет возвращать заданный errno, поэтому сверяем загруженную политику; поле Seccomp в status не раскрывает её правила. Механизм описан в seccomp(2). Здесь диагноз подтверждает рост max одновременно с отказами создания потоков. Исправление: ограничить пул и очередь, согласовать бюджет потоков с лимитами всей иерархии, повторить нагрузку. Chroot, cgroups и seccomp работают без отдельного гостевого ядра, но требуют измерений и настройки. Покупать K8s ради непрочитанного pids.events — дорогой способ спрятать незнание Linux. Практика эксплуатации: https://ftops.space.
03:00. Учебный постмортем: панель объявила OOM по exit 137, дежурный предложил поднять memory limit. Но 137 совместим с SIGKILL и сам по себе не устанавливает причину. Проверяем journalctl -k --since '20 min ago', журнал kubelet и прирост oomkill в memory.events именно cgroup пострадавшего контейнера за окно аварии. В сценарии OOM-событий нет, зато kubelet зафиксировал провал liveness и принудительное завершение после grace period. Семантика счётчиков: [документация ядра](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html). На клиенте и сервере одновременно запускаем tcpdump -ni eth0 -nn -vvv 'tcp port 443 or icmp', подставив рабочий интерфейс. Клиент отправляет SYN повторно, сервер не видит его вовсе. Это локализует потерю между точками захвата, но ещё не доказывает петлю. Снимаем дельту TcpRetransSegs через nstat -az TcpRetransSegs: ретрансляции подтверждают симптом, а не его причину. Дальше traceroute -n -T -p 443 SERVERIP с клиента и отдельная трассировка обратно. ...
03:00. Учебный постмортем: панель объявила OOM по exit 137, дежурный предложил поднять memory limit. Но 137 совместим с SIGKILL и сам по себе не устанавливает причину. Проверяем journalctl -k --since '20 min ago', журнал kubelet и прирост oom_kill в memory.events именно cgroup пострадавшего контейнера за окно аварии. В сценарии OOM-событий нет, зато kubelet зафиксировал провал liveness и принудительное завершение после grace period. Семантика счётчиков: [документация ядра](https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html). На клиенте и сервере одновременно запускаем tcpdump -ni eth0 -nn -vvv 'tcp port 443 or icmp', подставив рабочий интерфейс. Клиент отправляет SYN повторно, сервер не видит его вовсе. Это локализует потерю между точками захвата, но ещё не доказывает петлю. Снимаем дельту TcpRetransSegs через nstat -az TcpRetransSegs: ретрансляции подтверждают симптом, а не его причину. Дальше traceroute -n -T -p 443 SERVER_IP с клиента и отдельная трассировка обратно. Повторяющиеся хопы — улика; на подозрительных маршрутизаторах ловим возврат одного IP-пакета с убывающим TTL. Проверяем ip route get SERVER_IP, нужную таблицу FIB и BGP next-hop на обоих узлах. Только сопоставление таблиц объясняет, почему пересылка замкнулась: слово BGP в тикете ничего не доказывает. Параметры TCP-проб: [traceroute](https://www.man7.org/linux/man-pages/man8/traceroute.8.html). Исправление в этом сценарии — устранить взаимную пересылку для проблемного префикса, затем подтвердить доставку SYN/SYN-ACK с обеих сторон и восстановление probes. Сетевая петля может довести сервис и до настоящего OOM через накопление очередей; тогда это отдельное подтверждённое звено отказа. Автомасштабирование до проверки маршрута просто размножает платные таймауты. Эксплуатационный принцип https://ftops.space: сначала доказательства, потом дополнительные гигабайты.
ZFS не тормозил. Его просто не измеряли

Мониторинг кричал о задержках диска на FreeBSD-шлюзе. Железо было исправно, ошибок в пуле не было. Настоящая причина сидела выше: ARC разросся под рабочей нагрузкой, полезные метаданные начали вытесняться, а jails синхронно получили паузы на повторном чтении с накопителей.

Криминалистика начинается не с покупки NVMe. Сначала смотрят zpool status -v, zpool iostat -v 1 и sysctl kstat.zfs.misc.arcstats. Если размер ARC, промахи и состав кэша не сопоставлены с реальным профилем I/O, любой график latency рассказывает только половину истории.

FreeBSD остается эталоном для сетевых шлюзов и надежного хранения не из-за UNIX-ностальгии. ZFS, jails и прозрачные системные счетчики дают оператору главное: предсказуемость отказа. Но стабильность появляется только там, где ARC ограничен осознанно, пул регулярно проверяется, а деградацию замечают до того, как она становится аварией.

Облако продает лишнюю память как лекарство от незнания. На своем железе диаг...
ZFS не тормозил. Его просто не измеряли

Мониторинг кричал о задержках диска на FreeBSD-шлюзе. Железо было исправно, ошибок в пуле не было. Настоящая причина сидела выше: ARC разросся под рабочей нагрузкой, полезные метаданные начали вытесняться, а jails синхронно получили паузы на повторном чтении с накопителей.

Криминалистика начинается не с покупки NVMe. Сначала смотрят zpool status -v, zpool iostat -v 1 и sysctl kstat.zfs.misc.arcstats. Если размер ARC, промахи и состав кэша не сопоставлены с реальным профилем I/O, любой график latency рассказывает только половину истории.

FreeBSD остается эталоном для сетевых шлюзов и надежного хранения не из-за UNIX-ностальгии. ZFS, jails и прозрачные системные счетчики дают оператору главное: предсказуемость отказа. Но стабильность появляется только там, где ARC ограничен осознанно, пул регулярно проверяется, а деградацию замечают до того, как она становится аварией.

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

https://ftops.space

#ftops #devops #linux #freebsd #sre #инфраструктура
Мониторинг кричал: apiserver недоступен, S3 отвечает медленно. Дежурный проверил не легенду, а железо: cat /proc/pressure/io, iostat -xz 1, dmesg -T \| tail -100, ss -lntp \| egrep ':2379\|:2380'. I/O pressure не рос, TCP не терялся. Сломался не транспорт — нарушили процедуру membership. На одной server-ноде K3s остановили и выполнили: k3s server --cluster-reset --cluster-reset-restore-path\=<snapshot-name> --etcd-s3 --etcd-s3-bucket\=<bucket> .... Для нового хоста нужен исходный --token: им расшифровываются bootstrap-данные. S3 Secret из Kubernetes при restore недоступен — API ещё мёртв, поэтому параметры S3 подаются через CLI или конфиг на диске. После сообщения о завершённом reset запустили только первый server и проверили curl -sf http://127.0.0.1:2381/metrics \| egrep 'etcdserverhasleader\|etcddiskwalfsyncdurationseconds'. На остальных server-нодах при остановленном K3s архивировали и удалили из рабочего пути /var/lib/rancher/k3s/server/db, затем присоединили их заново. Ст...
Мониторинг кричал: apiserver недоступен, S3 отвечает медленно. Дежурный проверил не легенду, а железо: cat /proc/pressure/io, iostat -xz 1, dmesg -T \| tail -100, ss -lntp \| egrep ':2379\|:2380'. I/O pressure не рос, TCP не терялся. Сломался не транспорт — нарушили процедуру membership. На одной server-ноде K3s остановили и выполнили: k3s server --cluster-reset --cluster-reset-restore-path\=<snapshot-name> --etcd-s3 --etcd-s3-bucket\=<bucket> .... Для нового хоста нужен исходный --token: им расшифровываются bootstrap-данные. S3 Secret из Kubernetes при restore недоступен — API ещё мёртв, поэтому параметры S3 подаются через CLI или конфиг на диске. После сообщения о завершённом reset запустили только первый server и проверили curl -sf http://127.0.0.1:2381/metrics \| egrep 'etcdserverhasleader\|etcddiskwalfsyncdurationseconds'. На остальных server-нодах при остановленном K3s архивировали и удалили из рабочего пути /var/lib/rancher/k3s/server/db, затем присоединили их заново. Старые member ID нельзя пускать в новый quorum. Снепшот в бакете — лишь сырьё. DR существует только после регулярного restore-test, отдельного хранения token и записанного порядка запуска узлов. Практика bare-metal эксплуатации: https://ftops.space
Разбор аварии: active, но мертв

В 14:07 мониторинг увидел живой frr.service и четыре BGP-сессии в состоянии Established. Пользователи в это время получали таймауты. Дежурный перезапустил FRR, затем сетевой стек. Ничего не изменилось: процесс был исправен, а маршрут — нет.

Один транзитный провайдер принял утечку более специфичного префикса, второй предпочел этот маршрут и вернул трафик первому. Получилась межоператорская петля. Пакеты ходили между двумя AS до обнуления TTL, пока systemctl is-active продолжал печатать active. Он не врал: он отвечал на бесполезный вопрос о состоянии PID.

Криминалистика началась с mtr и tcpdump, а не с рестарта. Повторяющиеся адреса транзитов показали петлю, ICMP Time Exceeded подтвердил смерть по TTL, а сравнение received-routes и advertised-routes нашло более специфичный префикс. Счетчики ip -s link были чистыми: ядро передавало пакеты ровно туда, куда велела таблица маршрутизации.

После инцидента проверку сервиса заменили проверкой функции: внешний ...
Разбор аварии: active, но мертв

В 14:07 мониторинг увидел живой frr.service и четыре BGP-сессии в состоянии Established. Пользователи в это время получали таймауты. Дежурный перезапустил FRR, затем сетевой стек. Ничего не изменилось: процесс был исправен, а маршрут — нет.

Один транзитный провайдер принял утечку более специфичного префикса, второй предпочел этот маршрут и вернул трафик первому. Получилась межоператорская петля. Пакеты ходили между двумя AS до обнуления TTL, пока systemctl is-active продолжал печатать active. Он не врал: он отвечал на бесполезный вопрос о состоянии PID.

Криминалистика началась с mtr и tcpdump, а не с рестарта. Повторяющиеся адреса транзитов показали петлю, ICMP Time Exceeded подтвердил смерть по TTL, а сравнение received-routes и advertised-routes нашло более специфичный префикс. Счетчики ip -s link были чистыми: ядро передавало пакеты ровно туда, куда велела таблица маршрутизации.

После инцидента проверку сервиса заменили проверкой функции: внешний probe до контрольных адресов, контроль AS_PATH и префиксов, лимиты max-prefix, RPKI-фильтрация и аварийное отключение дефолтного экспорта. systemctl проверяет процесс. Эксплуатация обязана проверять функцию.

https://ftops.space

#ftops #devops #linux #freebsd #sre #инфраструктура
В 03:00 мониторинг показал DiskPressure, pod eviction и провал rollout. Поверхностный диагноз — «маленький VPS». Реальность: /var/lib/rancher/k3s/agent/containerd разросся слоями образов, а ImageGC стартовал слишком поздно и не успел освободить место до eviction threshold. Проверяем не красивый процент в панели, а ноду: kubectl describe node NODE; df -hT; df -ih; sudo du -xhd2 /var/lib/rancher/k3s/agent/containerd \| sort -h; sudo k3s crictl images. Если df показывает дефицит, а du нет — ищем удалённые, но открытые файлы: sudo lsof \+L1. Смотрим, что происходило внизу: cat /proc/pressure/io; awk '\{print $3,$4,$6,$8,$10,$13\}' /proc/diskstats; journalctl -u k3s -u k3s-agent --since '-2h' \| grep -Ei 'imagegc\|diskpressure\|evict\|filesystem'. Настраиваем kubelet заранее: imageGCHighThresholdPercent и imageGCLowThresholdPercent должны оставлять реальный резерв до evictionHard, а не делить последние гигабайты. На малой ноде свободное место — эксплуатационный бюджет. Ограничивайте размер ...
В 03:00 мониторинг показал DiskPressure, pod eviction и провал rollout. Поверхностный диагноз — «маленький VPS». Реальность: /var/lib/rancher/k3s/agent/containerd разросся слоями образов, а ImageGC стартовал слишком поздно и не успел освободить место до eviction threshold. Проверяем не красивый процент в панели, а ноду: kubectl describe node NODE; df -hT; df -ih; sudo du -xhd2 /var/lib/rancher/k3s/agent/containerd \| sort -h; sudo k3s crictl images. Если df показывает дефицит, а du нет — ищем удалённые, но открытые файлы: sudo lsof \+L1. Смотрим, что происходило внизу: cat /proc/pressure/io; awk '\{print $3,$4,$6,$8,$10,$13\}' /proc/diskstats; journalctl -u k3s -u k3s-agent --since '-2h' \| grep -Ei 'imagegc\|diskpressure\|evict\|filesystem'. Настраиваем kubelet заранее: imageGCHighThresholdPercent и imageGCLowThresholdPercent должны оставлять реальный резерв до evictionHard, а не делить последние гигабайты. На малой ноде свободное место — эксплуатационный бюджет. Ограничивайте размер образов, удаляйте неиспользуемые теги, контролируйте inode и проверяйте GC после каждого обновления K3s. Практика bare-metal эксплуатации: https://ftops.space
В 03:00 S3 честно отдал snapshot, а K3s после восстановления получил зависшие контроллеры, старые объекты в informer cache и попытки прежних server-нод вернуться в quorum. Поверхностный мониторинг написал: «etcd backup corrupted». Нет. Оператор восстановил байты, но не восстановил согласованное состояние кластера. Начинать надо не с перезапуска всего подряд: k3s etcd-snapshot ls --s3, затем проверить объект и выполнить на единственном выбранном server: k3s server --cluster-reset --cluster-reset-restore-path\=<SNAPSHOT>. После успешного reset убрать этот флаг, запустить узел штатно и только потом последовательно присоединять остальные server-ноды с актуальным token. Старые каталоги /var/lib/rancher/k3s/server/db на бывших участниках нельзя считать безобидными. Во время восстановления смотреть не только journal: journalctl -u k3s -b, ss -lntp \| grep 2379, ss -s, nstat -az \| grep -E 'TcpRetransSegs\|TcpExtTCPTimeouts', cat /proc/sys/net/netfilter/nfconntrackcount и cat /proc/sys/net/n...
В 03:00 S3 честно отдал snapshot, а K3s после восстановления получил зависшие контроллеры, старые объекты в informer cache и попытки прежних server-нод вернуться в quorum. Поверхностный мониторинг написал: «etcd backup corrupted». Нет. Оператор восстановил байты, но не восстановил согласованное состояние кластера. Начинать надо не с перезапуска всего подряд: k3s etcd-snapshot ls --s3, затем проверить объект и выполнить на единственном выбранном server: k3s server --cluster-reset --cluster-reset-restore-path\=<SNAPSHOT>. После успешного reset убрать этот флаг, запустить узел штатно и только потом последовательно присоединять остальные server-ноды с актуальным token. Старые каталоги /var/lib/rancher/k3s/server/db на бывших участниках нельзя считать безобидными. Во время восстановления смотреть не только journal: journalctl -u k3s -b, ss -lntp \| grep 2379, ss -s, nstat -az \| grep -E 'TcpRetransSegs\|TcpExtTCPTimeouts', cat /proc/sys/net/netfilter/nfconntrackcount и cat /proc/sys/net/netfilter/nfconntrackmax. Для диска: iostat -xz 1, grep -E 'Dirty\|Writeback' /proc/meminfo. Иногда «etcd timeout» — это забитый conntrack, потери TCP или fsync, утонувший в writeback. DR считается рабочим только после отдельной проверки API, quorum, системных контроллеров, секретов и повторного подключения нод. Хранить snapshot в S3 умеет даже ленивый managed-сервис; доказать восстановление умеет только команда с регулярно исполняемым runbook. Практика bare-metal эксплуатации: https://ftops.space
Мониторинг кричал: S3 недоступен, restore упирается в timeout. Проверили ядро: ss -s, nstat -az | egrep 'TcpRetransSegs|IpFragFails', conntrack -C, conntrack -S. Retransmit, фрагментация и conntrack были в норме. Сеть оправдана. Настоящий отказ был выше: настройки S3 хранились в Secret внутри самого кластера. Во время аварийного восстановления kube-apiserver ещё не работает, поэтому --etcd-s3-config-secret бесполезен. Получился классический замок с ключом внутри сейфа. Восстановление запускается на одном остановленном server с явными S3-параметрами и исходным токеном: k3s server --cluster-reset --cluster-reset-restore-path=SNAPSHOT --etcd-s3 --etcd-s3-bucket=BUCKET --etcd-s3-access-key=KEY --etcd-s3-secret-key=SECRET --token=ORIGINAL_TOKEN. Затем обычный запуск K3s; на остальных etcd-server старую базу убирают только после отдельной копии и присоединяют узлы заново. В DR-комплект входят снепшот, /var/lib/rancher/k3s/server/token, CA для S3, автономные credentials и проверенный runbook....
Мониторинг кричал: S3 недоступен, restore упирается в timeout. Проверили ядро: ss -s, nstat -az | egrep 'TcpRetransSegs|IpFragFails', conntrack -C, conntrack -S. Retransmit, фрагментация и conntrack были в норме. Сеть оправдана. Настоящий отказ был выше: настройки S3 хранились в Secret внутри самого кластера. Во время аварийного восстановления kube-apiserver ещё не работает, поэтому --etcd-s3-config-secret бесполезен. Получился классический замок с ключом внутри сейфа. Восстановление запускается на одном остановленном server с явными S3-параметрами и исходным токеном: k3s server --cluster-reset --cluster-reset-restore-path=SNAPSHOT --etcd-s3 --etcd-s3-bucket=BUCKET --etcd-s3-access-key=KEY --etcd-s3-secret-key=SECRET --token=ORIGINAL_TOKEN. Затем обычный запуск K3s; на остальных etcd-server старую базу убирают только после отдельной копии и присоединяют узлы заново. В DR-комплект входят снепшот, /var/lib/rancher/k3s/server/token, CA для S3, автономные credentials и проверенный runbook. Если restore никогда не прогоняли на пустом железе, резервной копии у вас нет. Есть надежда с HTTP API. https://ftops.space