Search
Write a publication
Pull to refresh
2
0

Пользователь

Send message

Мы отказались от таймаутов на стороне приложения именно из-за высокого риска иметь отстреливаемые бизнес-сценарии на продолжительном промежутке времени.

Но все равно звучит, что нужно двигаться в эту сторону, иначе часть кейсов “подвисших запросов” так и останется не покрыта. Т.е. потушили пожар наиболее быстрым и безопасным способом, а потом уже в спокойном режиме с более низким приоритетом можно плавно двигаться к "long-term" решению. Начать, допустим, только с новых фичей/сервисов и тех, где по мониторингу на 99.99 перцентилях все хорошо. А какое-нибудь легаси пускай себе остается только с tcp_user_timeout, пока до него руки не дойдут. Ну или как вариант, сделать retry полиси, когда на следующий ретрай увеличивается таймаут до абсурдно больших значений (все еще лучше, чем не иметь таймаута вообще + позволит потом по логам/мониторингу изучить, где ошиблись с инишиал таймаутом) - аналог exponential backoff, только для таймаута, а не паузы между ретраями.

Не в случае gRPC: следующий ретрай для него как раз таки не обязательно пойдет на здоровый инстанс. Об этом кейсе статья :)

Конкретно про реализацию gRPC не скажу, но если при наличии хелсчеков менеджер пула не убирает зафейленные (по хелсчеку) инстансы из балансировки, то как-будто фиксить поведение нужно именно тут. Не было бы вопросов, если бы так происходило при отсутствии хелсчеков или, если бы это касалось только тех запросов, что отправились до хелсчека, но после падения инстанса (при отсутствии апплик таймаута).

Мейнтенерам Linkerd нужно решать все те же проблемы, что и cloudflare lb. 

Мейнтейнерам Linkerd - да, так как потенциально кто-то их решение может использовать для внешних кастомеров. В вашем же случае корневое отличие в том, что клиенты и бэкенды Linkerd тоже находятся под вашим контролем, то чего бы не пользоваться этим преимуществом. Плюс, в вашем случае скорее всего речь идет только про inter-service трафик в пределах одного дц (или какого-то другого закрытого контура), т.е. сильно меньше кейсов, где можно ожидать неожиданное поведение сети. 

Тк Linkerd может быть использован не только как прокси для application протоколов, но и general tcp прокси, для соединений до баз данных к примеру. 

Так это все еще аппликейшны, и хорошо бы чтобы у них также были таймауты/хелсчеки. Просто голый tcp никому не нужен, поверх него все равно будет какой-то протокол. Т.е. остаются узкие кейсы, где почему-то нужно обойтись без “protocol-aware” хелсчеков. Но и для таких кейсов все равно все еще можем использовать примитивный хелсчек, который гоняет ack’и в отдельном коннекте или переодически новые tcp сессии создает - зафейлилось - перестаем туда отправлять данные новых коннектов и, по-хорошему, прибиваем старые коннекты по таймауту, если сами не закрылись.

В общем основной мой поинт в том, что это хорошо, конечно, что можно подстраховаться тюнингом таймаутов на уровне TCP, но чаще будет правильней решать такие проблемы на уровне L7 (особенно, когда и клиенты и бэкенды под контролем). При этом tcp таймауты все равно можно оставлять для подстраховки.

Было не совсем это - по сегфолту упала сама worker-нода.

Ага, но принцип все равно такой же, пока сохраняется IP (даже не обязательно, чтобы сервис поднялся, главное, чтобы пакеты могли дойти до хоста, где в данный момент старый IP).

Может у вас какая-то дока или кейс чтобы почитать про такое поведение. Потому что при своем исследовании, я такого не нашел.

https://datatracker.ietf.org/doc/html/rfc9293#name-reset-generation

> As a general rule, reset (RST) is sent whenever a segment arrives that apparently is not intended for the current connection.

> If the connection does not exist (CLOSED), then a reset is sent in response to any incoming segment except another reset

 Могу предположить, что в вашем случае на воркере, или где-то в другом месте по пути был iptables рул (или что-то аналогичное), который чекал conntrack, и дропал пакеты, не принадлежащие текущим сессиям. В таком случае ядру не на что будет возвращать RST (src пакет не дошел до места, которое бы тригернуло RST).

Если старый IP “routable”, и нет хитрых файрвол рулов, которые могут дропнуть пакеты со старых “зависших” сессий, то RST должен обязательно вернуться.

Все же решение на уровне транспортного протокола не сильно отличается от решения на уровне ядра. Все те же минусы: нужно углубляться в детали реализации, проверять какие могут быть edge кейсы, можем ли что-то поломать, добавляется ли оверхед в сетевом стеке ядра (в случае user_timeout не должен, так как проверка таймера происходит при следующем ретрае, но все же), могут ли другие нестандартные sysctl’и поменять ожидаемое поведение и так далее. Дополнительно tcp_user_timeout добавляет еще и доп. tcp опцию (28ую) в хедер пакета, а ее иногда “неофициально” используют для проброса клиентского IP (раз, два).

Ну и самое главное: это решает только тот вид проблем, с которыми уже столкнулись, и знаем, что для них такое решение подходит. А при какой-то другой комбинации обстоятельств не поможет (условно: ack’и проходят, но push пакеты теряются/тротлятся где-то в ядре на пути к апплику, потому что подвисла какая-нибудь прослойка, которая инспектит пакеты через nfqueue).

Поэтому лучше такие проблемы решать на уровне аппликейшна/mesh_сети (в общем на том уровне, где client LB реализован). Тогда неважно, что будет происходить/меняться на инфрастуктуре, в ОС или других местах “под нами”.

В большинстве случаев должно хватать хелсчеков + желательно timeout на application запросы.

Зафейлились хелсчек пробы - выкинули из пула проблемный инстанс (нам не важно, как именно он упал и закрылись ли коннекшны. Хелс эндпоинт не отработал - удаляем инстанс из балансировки).

По timeout’ам на application запросы у вас немного странные аргументы. Чаще всего 99% запросов в inter-service коммуникации подпадают под какую-то адекватную верхнюю границу (допустим, не больше 2-3 секунд), которая засетана где-нибудь в общих дефолтах для всех сервисов. А для остальных ситуаций уже поднимается дефолт (но это должно быть что-то редкое, иначе странно, если есть много синхронных запросов, где ок висеть 30 секунд - что-то тут не так тогда).

С таким подходом нам не важно, что именно случилось с проблемным инстансом - следующий аппликативный ретрай уже пойдет на здоровый инстанс.

В случае cloudflare’а подход с tcp_user_timeout и другие low-level тюнинги на уровне ядра/сети имеют смысл, потому что:

a. У них другая задача: вовремя освобождать ресурсы на балансере не имея контроля над upstream/downstream (они не могут знать, какой аппликативный таймаут валиден для того или иного пользовательского реквеста). Поэтому да, им нужно спускаться на уровень ниже.

b. У них есть ресурсы глубоко лезть в сетевой стэк ядра, разбираться во всех edge кейсах, и патчить ядро или писать кастомные eBPF программы, если всплывают какие-нибудь нюансы.

c. На их масштабах окупается тюнинг на всех уровнях (hw, OS, network, application). Раз и так все кастомное, то чего бы и таймауты на уровне tcp не подтюнить (как и кучу других параметров заодно).

Ну и еще пару копеек:

  • По-хорошему "плохой инстанс" должен перезапускаться по liveness пробе или чему-то аналогичному. Тем более в самом простом кейсе, когда процесс убился по сегфолту. Допустим в случае k8s перезапустился контейнер, но он будет с тем же IP - все "зависшие" коннекшны получат RST пакет на следующем ретрае и закроются даже без всего того, что было расписано выше. Т.е. вышеописанные проблемы должны происходить только, когда "плохой" инстанс" на каждом перезапуске получает новый IP (зачем?) или по какой-то причине инстанс не может стартануть обратно (должно быть что-то редкое).

  • Если все-таки что-то пошло совсем не по плану, и сервис "A" работает с проблемами, то тут должны помогать circuit breaker'ы, лимиты на очередь запросов и все такое. Так хотя бы ситуация не будет ухудшаться и продолжит работать остальной функционал (если он есть на сервисах B,C,D без сервиса A). Ну или как минимум не заддосим сервис A еще больше.

Справедливости ради, у wsl2 уже под капотом обычная виртуалка на hyper-v, соответственно сделать можно все, что позволит hyper-v и kernel/userspace, что внутри wsl2 гостя ( с этим ограничений тоже нет).

Другое дело, что так в каждой ОС можно сделать:  отличие от того, чтобы самому развернуть vm, используя нативный гипервизор, и поставить туда нужный дистр, только в том, что это идет из коробки с интеграцией в хостовую систему (маунты plan9 внутрь гостя и всякое такое). Но опять же, ничего такого, что сложно сделать самому.

 

Да, но если бы дело было только в этом, то тогда бы как праймари использовался cloudfront. А так на свой cdn переключились только после того, как сторонний перестал работать.

Забавное в этой ситуации, что один cdn провайдер использует другого cdn провайдера для своего сайта. Так себе реклама cloudfront'у.


dig images-na.ssl-images-amazon.com +short
m.media-amazon.com.
media.amazon.map.fastly.net.
151.101.1.16

Хотя после инцидента с fastly пока обратно вернулись на свой cdn.

с другими версиями ядра

Ядро используется хостовое, и запустить вы сможете внутри jail только тот набор userspace приложений, который может работать с текущим хостовым ядром. Понятно, что это может быть и linux userspace, если хостовое ядро собрано с linux_enable=«YES».
Непонятно также почему выбран Virtio-Block, хотя прокс рекомендует Virtio-Scsi.
Именно в вопросе производительности это не сильно важно. Proxmox рекомендует virtio-scsi скорее из-за большего количества функций (полноценное scsi устройство, поддержка blkdiscard, масштабируемость и т.д.) при примерно той же производительности (при некоторых паттернах нагрузки она хуже из-за большего количества прослоек).
Купив лицензию на StarWind HA

Это, как и ceph — распределнное программно определяемое хранилище, т.е. другой тип решений. Обсуждалась же классическая централизованная блочная СХД.
«2-х узловую резервированную СХД» на 30% дешевле

Резервированную? Т.е. поверх будет еще синхронная репликация? Тогда это, опять же, другой тип решений с другим показателем производительности. Обсуждалась реализация аналога 2ух котроллерной СХД, когда каждый узел одновременно видит все диски из jbod. Диски для этого должны быть с SAS интерфейсом (по path на каждый узел СХД) и jbod, подключенный по SAS одновременно к 2ум узлам. В этом случае мы одновременно используем 2 узла, балансируем между ними нагрузку (каждый держит разные raid'ы, раздает разные луны), и при этом не нужна никакая ухудшающая производительность репликация. Тут по ценнику может быть тоже самое, но при этом меньше функционала (который не всегда, конечно, нужен), отсутствие кэша (аппаратный raid с батарейкой и кэшем не подойдет, т.к. с ним не реализовать 2ух узловой режим работы без доп. механизмов репликации).

О NVMe и говорить не нужно, в этом случае аналог 2ух контроллерной вендорской СХД особо собрать и не получится (как диски по PCIe одновременно на 2 сервера пробрасывать).
Я, «грамотный инженер» который успешно эксплуатировал комплект как СХД

Имеются в эксплуатации всевозможные типы SAN: самодельные на базе supermicro без репликации (2x 2U head, lsi hba, Nx 4U jbods via sas, software: mdadm,lvm,scst_target), самодельные на базе supermicro c репликацией (2x 4U head, lsi hba, software: drbd, mdadm,lvm,scst_target), различные вариации вышеперечисленного, различные вендорские СХД. Конечно, 2x 4U Supermicro сервера с drbd репликацией будут в разы дешевле стоить готовой СХД, ну так и производительность будет совсем другая. При приближении функционала сравнивается и цена.
Примерный порядок розничных цен для стандартных компонентов я привёл ниже.

Так нужны SAS SSD, чтобы все диски были доступны с 2ух «голов» СХД для возможности online переезда RAID'а (если мы хотим получить аналогичное вендорскому решение). А они будут намного дороже, особенно если схожих с Optane характеристик. В случае с SATA дисками кроме RAID'а нужен будет еще механизм синхронной репликации, а это сразу просадка по производительности, и уже сравнивать с вендорской 2ух котроллерной СХД нельзя.
против одиночной «брендовой»

Так не одиночная же. Обычно берут 2ух контроллерную, а это аналог 2ух узлов в самодельном SAN'е.
мы получим стоимость более чем в 2 раза меньше

Вот как раз если попытаться повторить один в один вендорскую СХД (например какую-нибудь OceanStor Dorado5000 V3) с близки показателями по iops, latency, доступности, то будет сопоставимо по цене (заоблочные цены из статьи не рассматриваем), но при этом может быть меньшая функциональность (тот же dedup мало где нормально работает, да еще чтобы без просадки по производительности).
«грамотный инженер» за 100k в месяц соберёт более производительную и оптимизированную под конкретные задачи клиента систему на железе от «дешманского» Supermicro с парой запасных узлов и резервированием СХД в 2 раза дешевле

В сравнении вендорских СХД и тех, которые можно построить самостоятельно на базе того же Supermicro, не все так однозначно.

Например, вендорская СХД: 2 контроллера, куча RAM кэша, рабочие dedup/compression, thin volumes, различные программные прослойки для удобства управления дисками, массивами и т.д.

Чтобы построить что-то хоть немного аналогичное: нужно 2x сервера c HBA и производительными CPU, шареный jbod, подключенный к головам по SAS, различная мелочевка для коммутации этого всего, ну и, собственно, SAS диски (SAS-SSD от любого вендора будут не дешевыми). По программной части будет что-нибудь типа: mdadm — lvm — iscsi_target. По итогу: нету RAM кэша (мы же не можем рисковать, с отдельным сервером может случиться что угодно), нету dedup/compression, с mdadm+lvm нельзя добиться такой гибкости и такого функционала, какой есть в вендорских СХД (пример). При этом по цене не факт, что получится дешевле, особенно вместе с SAS-SSD дисками.

Альтернативой может быть ceph, но его грамотная поддержка потребует больше ресурсов и более квалифицированный персонал чем первые 2 варианта. Желательно разбираться в кодовой базе ceph, возможно понадобится вносить правки, тестировать все это.
Да, я поспешил. У вас в статье с этим все правильно. Просто бросилось в глаза «write utils», это и смутило. Не заметил дальше, что берется именно «write ticks», т.е. суммарное время всех w_io операций.
А в чем смысл вычислять производную от iops и util метрику *_svctime, если ядро предоставляет информацию о суммарном затреченном времени на все дисковые операции (в /sys/block/sdX/stat поля read ticks, write ticks или в /proc/diskstat аналоничные по смыслу поля). Делим на количество io в еденицу времени и получаем честный средний latency (await).

В случае с *_svctime цифра может не иметь ничего общего с реальным latency. Наример: за 1 секунду было сделано 5 параллельных r_io опреаций, каждая выполнялась 1 секунду. Реальный средний r_latency (и посчитанный исходя из 5ти секунд read ticks) — 1 секунда, r_svctime же будет 1/5 = 0.2 секунды.
bgp тут как универсальное и специально для этих дел оптимизированное средство доставки маршртов на целевую систему. Т.е. если из статьи убрать bgp, то нужны будут другие способы доставки маршрутов. Например кастомный скрипт, который считает diff новых/страрых маршрутов и заливает на роутер через expect по ssh разницу (не перезаливать же каждый раз 60k маршрутов). Разные роутеры — разные expect скрипты.
Способов много можно придумать, у каждого будут свои плюсы и минусы в конкретной ситуации.
Глупо загонять такое количество адресов в таблицу машрутизации.
Наоборот непонятно, зачем городить дополнительные сущности в виде iptables, ipset и ip_rules, если у нас уже есть dst, которые достаточно добавить в дефолтную таблицу маршрутизации.

Откдуда взято предположение, что jenkins hash ipset'а будет производительние и экономичнее чем модифицированный LPC-trie для обработки одинакового количества ipv4 адресов/подсетей (неплохое описание и тесты, да и на хабре писали)? Т.е. если ядерная маршрутизация не справится, то с iptables+ipset+ip_rules лучше не будет. Другое дело, что надо смотреть версию ядра, раньше hash использовался для таблицы маршрутизации и некоторые оптимизации позже появились.
Если нужно только отследить связи parent->child, то хватит и ps с флагом f (-H). В варианте автора еще показывается, через что общаются между собой процессы, если общаются.
Так а зачем на них идти? Речь идет об использовании модуля raw для изначальной инсталляции python 2.x, если отсутствует /usr/bin/python. Т.е. добавляется дополнительный task в «bootstrap» playbook.
Сколько использую, пока не встретил проблем с этим.

И все же, если это не какая-то исключительная ситуация, лучше пока устанавливать python 2.x, как и сделал автор поста.

Из faq последней версии ansible:
Python 3 support is being worked on but some Ansible modules are not yet ported to run under Python 3.0. This is not a problem though as you can just install Python 2 also on a managed host.

И в документации поддержка python 3.x все еще помечена как technology preview feature.
rsync знает о расширенных атрибутах и имеет соответтсвующую опцию -X.
Причем делать rsync можно даже на живой системе

Сделать-то можно, но точной консистентности данных не получится. Можно, конечно, остановить все сервисы и сделать remount root'а в read only, но легче ребутнуться и сделать финальный rsync из live окружения и гарантировать консистентность. Ведь все равно сервисы будут недоступны и в первом варианте.
А что, по вашему, делает pvmove? Создается raid через тот же dm-raid и дальше только мониторится процесс синка с заданным интервалом. Мало того, процесс pvmove можно спокойно «прибивать» сразу после запуска, на синк это никак не повлияет (сам процесс синка можно будет мониторить, например, так: dmsetup status|grep mirror). Pvmove только меняет lvm метаданные, создает raid и по окончанию меняет метаданные снова и разваливает raid.
1

Information

Rating
Does not participate
Registered
Activity