Русский
Русский
English
Статистика
Реклама

Обработка сигналов

Перевод Наш путь к нулевым простоям при непрерывном обновлении с помощью Ambassador

24.10.2020 08:05:17 | Автор: admin


Мы в Lifion строим распределенную платформу и портфель продуктов для клиентов по всему миру. С учетом этого важно, чтобы мы могли выпускать обновления нашей платформы непрерывно прямо во время ее работы, прозрачно для наших пользователей, которым важна доступность системы, при этом они находятся в разных регионах и часовых поясах. В этой статье мы поделимся с вами путем, которым мы шли, чтобы получить нулевые простои при непрерывном обновлении с помощью Kubernetes. Мы запускаем наши нагрузки с помощью управляемого сервиса Kubernetes AWS EKS. В качестве шлюза API мы применяем Ambassador, сборку Envoy с открытым исходным кодом, специально разработанную для Kubernetes. Наша платформа состоит из более чем 150 микросервисов, большинство из них написаны на Node.js, запускаются в многих подах поверх многочисленных рабочих узлов.


Состояние проблемы


Поскольку мы разворачиваем наше решение NextGen HGM для все большего числа клиентов, и требования к платформе растут, мы хотим в дальнейшем обеспечивать надежность нашей нижележащей инфраструктуры. Однако проблема, которую мы обнаружили при проведении непрерывного обновления некоторых наших сервисов в кластере Kubernetes, заключается в том, что поды отключаются сразу же, как только сервисы переходят в состояние Terminating, вместо мягкой остановки, как мы предполагали. Это привело к сбоям некоторых запросов во время таких обновлений, что нежелательно, а также потенциально может повлиять на работу пользователей.


Главная причина (Нет обработки SIGTERM)


Среда запуска контейнеров в некоторой части жизненного цикла пода Kubernetes отправляет сигнал SIGTERM в старый под во время обновления, к примеру, когда новый под уже запущен и может принимать запросы для обслуживания. Проведя исследование, мы поняли, что часть наших команд инженеров запускали сервисы на Node.js в подах под PID1, так что SIGTERM явно не обрабатывался на уровне кода, несмотря на рекомендации:


Node.js не разработан для запуска под PID1, это может привести к неопределенному поведению при запуске внутри контейнера Docker. Например, процесс Node.js, запущенный под PID1 не будет отвечать на SIGINT (CTRL-C) и другие подобные сигналы.

Это значит, что во время обновления, когда поды получают сигнал SIGTERM, они ждут 30 секунд (промежуток времени для мягкого завершения), а затем им присылается SIGKILL, так что процессы с PID1 резко выключаются с кодом возврата 137. Это приводит к сбору существующих обрабатываемых в этот момент запросов к поду, на которые не будет дан ответ.



Решение (первая попытка)


В нашу библиотеку Node.js, поверх которой строятся наши микросервисы, мы добавили типовую обработку сигнала SIGTERM, который останавливает активное обслуживание запросов после некоторой задержки. Это значит, что оставшимся запросам дается некоторое время для завершения, прежде чем они будут закрыты и их соединения TCP с все еще активными keep-alive также будут завершены. Ну и наконец сервис останавливается.


...process.on('SIGINT', () => {    logger.warn('SIGINT received. Shutting down');    process.exit(0);  });  process.on('SIGTERM', () => {    logger.warn('SIGTERM received. Initiating graceful shutdown');    shutdown()      .catch((err) => {        logger.error('Ignoring error during graceful shutdown:', err);      })      .finally(() => {        logger.warn('Graceful shutdown completed.');        process.exit(0);      });?  });....module.exports = Object.assign(exposed, {  _listen: exposed.listen,  config,  listen: start,  listenAsync: startAsync,  reset,  setAfterShutdown: (fn) => {    hooks.afterShutdown = fn;  },  setBeforeShutdown: (fn) => {    hooks.beforeShutdown = fn;  },  start,  startAsync,  stop,  stopAsync: promisify(stop)});

Еще один барьер (получение запросов после SIGTERM)


После подключения обработки SIGTERM в нашей основной библиотеке мы получили еще одну проблему: один из инженеров сказал нам, что по факту его сервис все еще получал некоторые запросы после получения SIGTERM во время обновления. А если верить соглашению жизненного цикла пода в Kubernetes, как только под получил SIGTERM, он удаляется из endpoints сервиса, а значит, и из балансировщика нагрузки. Однако если под удаляется из кластера через API, то он только помечается для удаления на сервере метаданных. Сервер уже в свою очередь отправляет уведомление об удалении пода всем связанным подсистемам, обрабатывающим запрос на удаление:


  • kubelet, запускающий последовательности запуска и остановки пода
  • сервис kube-proxy, удаляющий на всех узлах ip-адрес пода в iptables
  • контроллер endpoints удаляет под из списка корректных endpoints, что приводит к удалению пода из Service

Мы можем воспроизвести эту проблему следующим кусочком кода:


function readyCheck() {    let ready = true;process.on('SIGTERM', () => {      logger.info('SIGTERM received, making service as no longer ready');      ready = false;    });return (req, res) => {      if (ready) {        logger.info('Successful ready check');        res.sendStatus(200);      } else {        res.sendStatus(503);        logger.info('Signaling ready check failure');      }    };  }....router.get('/ready', readyCheck());

Во время исследований мы нашли ключевую причину этой проблемы, она была связана с нашим шлюзом API Ambassador/Envoy. Ambassador оборачивает для Envoy, создавая ему настройки. Команда Ambassador помогла нам в наших исследованиях, их официальный ответ от техподдержки был таким:


Envoy старается быть максимально эффективным при поддержке открытых соединений к вышестоящим сервисам. Поскольку фактические endpoints меняются, эти долгоживущие соединения все еще могут быть связаны с старым подом, который будет удален через некоторое короткое время. Проблема в том, что существует некая задержка между Kubernetes, отправляющим SIGTERM для отключения пода, и Ambassador, удаляющим под из списка endpoints. Стоит отметить, что проблема существует и в kube-proxy, если вы с ним работаете в больших масштабах.

Проще говоря, из-за оптимизации Envoy некоторые сервисы будут получать запросы после того, как они получили SIGTERM, что приведет к потере текущих запросов (запрос пришел до DIGTERM, но еще не обработан) во время обновления этого сервиса.


Решение (вторая попытка)


Envoy нужно некоторое время для остановки существующих соединений на время остановки пода до получения подом SIGTERM. Так что в качестве решения мы добавили поддержку preStopHook в Helm Chart для нашего сервиса:


lifecycle:  preStop:    exec:      command:      - sleep      - "10"

Во время обновления процесс остановки старого пода ждет 10 секунд, чтобы дать возможность Envoy отключить все существующие соединения к поду, а также удостовериться, что под убран из endpoints балансировщика нагрузки. Сразу же после этого Kubernetes, как обычно, отправляет сигнал SIGTERM процессу с PID1.


Для гибкости мы расширили это изменение, так что команды инженеров могут также переопределять такое поведение по умолчанию, если это им понадобится. Например, у нас есть несколько сервисов, использующих NGINX для раздачи статического контента из пода, для них мы решили проблему следующими изменениями в helm chart:


lifecycle:  preStop:    exec:      command: [        "sh", "-c",        # Introduce a delay to the shutdown sequence to wait for the        # pod eviction event to propagate. Then, gracefully shutdown        # nginx.        "sleep 5 && /usr/sbin/nginx -s quit",      ]

Выводы


Если сложить все вместе, то эта статья покрывает:


  • Принципы обработки жизненного цикла Kubernetes, используемые для мягкого и безопасного выключения приложений, при котором они не будут терять текущие запросы.
  • Нюансы, с которыми поды удаляются из системы. Важность понимания и особенности обработки соответствующей процедуры выключения, особенно в крупных масштабах с применением Ambassador.

Если все эти функции применять вместе, мы можем достичь нашей цели: нулевого простоя при непрерывном обновлении сервисов.


N.B. Для тех, кому нужна практика построения систем с надежной архитектурой, готовых к перегрузкам, Слёрм проводит онлайн-интенсив по SRE. Интенсив пройдет 1113 декабря 2020, до начала декабря можно купить билет со скидкой.

Подробнее..

FOVEA томографируем коня через игольное ушко

27.05.2021 14:07:09 | Автор: admin

Рентгеновская томография - один из двух (наряду с МРТ) самых известных способов заглянуть внутрь непрозрачных объектов. В медицине он является инструментом клинического мониторинга и средством терапии, в индустрии помогает контролировать технологические процессы, в таможне - найти то, что кое-кто предпочел бы спрятать. Эта технология в нашей стране развивается in house на мировом уровне. Но мы в Smart Engines пишем про томографию так часто не только поэтому. Мы - ученые и изобретатели, а томография - неиссякаемый источник проблем и задач, требующих решения (мы уже писали о несовершенных детекторах и широкополосном излучении). Сегодня мы расскажем о том, что делать, если объект исследования не помещается в томограф. Вот как, например, британские ученые исследуют коня в зоопарке. Голову коня в гентри поместить удается, а с остальным дела обстоят сложнее. Пример не очень серьезный, но жизненный. Кто в лаборатории работал, тот в зоопарке не смеется. Заглянув под кат вы узнаете, как получается, что у физиков сантиметровый образец не помещается в километровый томограф, и чем тут могут помочь вычислительные математики.

Наш томографический маскот воодушевляет специалистов буквально всеми своими ммм деталями. Вот и с общими геометрическими формами все очень удачно. Гентри ей - как хула-хуп: можно сканировать хоть сверху-вниз, хоть снизу-вверх.

Впрочем, для боди-позитивного маскота можно было бы построить гентри побольше - в чем проблема? Но не все томографические комплексы вообще используют гентри. Есть такая машина - синхротрон. Машиной их называют специалисты, и это может вызвать неправильные образы при первом знакомстве. Размеры такой машины достигают километров, а строятся они, бывает, всем миром. В полном смысле этого слова. Например, синхротрон ESRF, расположенный во французском городе Гренобле, был построен в 1994 году совместными усилиями 20 стран. Синхротрон дает мощнейший узконаправленный пучок рентгеновских лучей. Такой мощный, что время многих измерений сокращается в десятки и сотни тысяч раз. Для регистрации рентгеновского излучения на его станциях используются уникальные плоскопараллельные детекторы с высочайшим пространственным разрешением. Излучатель и детектор остаются неподвижными, а образец вращается. Часто размеры исследуемых объектов, мельчайшие детали которых требуется рассмотреть, большие, а вот размеры детекторов ограничены.

Давайте посмотрим на результат измерений типичного биологического объекта в такой томографической схеме. Это фрагмент кости, отснятый с субмикронным разрешением. Измерения проведены на современном швейцарском синхротроне Swiss Light Source Paul Scherrer Institut. Намётанный глаз позволяет увидеть и контуры объекта, и трабекулы (перегородки) внутри. Но при таком разрешении объект не помещается целиком в поле зрения детектора. На каждой из проекций просматривается только часть объекта.

Похожее мы наблюдали в детстве, когда подсматривали в замочную скважину. Мы видели только часть запертой от нас комнаты. Заглядывая в нее под разными углами, можно расширить поле зрения, увидеть больше, но общую картину придется сшивать силой воображения. Традиционные алгоритмы томографической реконструкции для такого не предназначены.

Чтобы лучше почувствовать проблему, обратимся, как это принято среди ученых, к модели. Возьмем в качестве модельного объекта грецкий орех, совсем недавно оттомографированный в разных режимах нашими коллегами из Голландии. На картинке ниже показан орех и его рентгеновское изображение.

По структуре орех похож на кость, и для него нам известен ground truth - реконструкция, полученная при полных данных.

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

При таком соотношении размеров вместо целой синограммы объекта (что это такое, мы уже писали на Хабре) будет видна только ее часть (ниже в красной рамке).

Поскольку в детектор помещается больше половины ореха, то при вращении все его части когда-нибудь попадают в поле зрения детектора. Сама же синограмма имеет характерную структуру и кажется, что её фрагмент возможно экстраполировать до полного размера.

Будем строить такую синограмму, чтобы 1) она в области измерений совпадала с экспериментальной синограммой, 2) существовал объект, которому соответствовала бы наша синограмма (это нетривиальный факт, но не любая функция является синограммой). Предложенный нами для этого итерационный алгоритм называется Field Of View Extension Algorithm - FOVEA (любопытные хабровчане могут порыться в интернете и отгадать, почему аббревиатура составляет именно это слово).

Вот пошаговое описание алгоритма:

  1. Создадим массив D_{iterative} , заполненный 0 . В нём мы будем итеративно обновлять значения элементов восстанавливаемого цифрового объёма.

  2. Рассчитаем синограммы S_{iterative} от D_{iterative} .

  3. Заменим рассчитанные на Шаге 2 значения S_{iterative} доступными нам экспериментальными значениями - S_{experimental} .

  4. Проведём томографическое восстановление D_{iterative} из синограммы S_{iterative} методом FBP.

  5. Рассчитаем синограмму S_{iterative} от D_{iterative} .

  6. Сравним (например, рассчитав L2 норму) S_{iterative} и S_{experimental} в той области, где мы знаем экспериментальные значения. Если расхождение малое, т.е. экспериментальная и модельная синограммы совпадают, то конец расчёта: искомая реконструкция лежит в D_{iterative} . В противном случае переходим на Шаг 3.

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

Из иллюстраций ясно, что на неполных данных мы избавились от области засветки (в зелёном прямоугольнике и усы вверх). Уже это позволяет увидеть больше деталей восстановленного ореха. Но, кроме того, нам удалось увидеть те части ореха, которые вообще не были видны до этого (в красных эллипсах).

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

Над методами томографии высокого пространственного разрешения продолжают биться ученые всего мира. Ведь так хочется увидеть каждый нейрон в нашей голове и разгадать, наконец, как работает человеческий нейрокомпьютер. Для этого нужно нанометровое разрешение. 1 кубический миллиметр содержит квинтиллион вокселей размером 1 нанометр. Если значение вокселя кодируется числом с плавающей точкой одинарной точности (float32), то только для хранения результатов реконструкции потребуется 4 эксабайта (4 106 Тбайт) памяти. Но в голове ни много ни мало, а порядка 30 миллионов таких кубических миллиметров. Поэтому сегодня в высоком разрешении томографируют не весь мозг, а отдельные его участки, для чего их необходимо извлечь из головы. Что-то нам подсказывает, что методы томографирования через замочную скважину будут актуальными еще долго...

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru