Load2SRE: от нагрузки к доступности, без потери производительности

38c3df014f8fb697f69c9969b9f35ab1.png

Привет! Меня зовут Кирилл Юрков, я SRE Team Lead в Samokat.tech. Уже более десяти лет занимаюсь ускорением и проблемами производительности, а также нагрузочным тестированием. 

Отвечая на вопрос, чем занимается SRE в Samokat.tech, скажу, что это те, кто занимается инцидентами и проблемами на всём их жизненном цикле, от этапа архитектуры и разработки до postmortem’а после инцидента.

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

Отправная точка 

848bdab49d10a4fdc0e12f842a996797.png

Почему начинаем именно с нагрузочника? Всё просто — это моя выдуманная карьерная лестница, которую я считаю интересной.

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

Среда обитания этого персонажа — чаще всего тестовый стенд, а основные задачи таковы:  

  • написание нагрузочных скриптов и заглушек 

  • проверять соответствие результатов тестов и требований

  • автоматизация;

  • запуск тестов и их документирование. 

Не будем долго рассуждать о роли и функциональности этого персонажа, тем более он многим знаком, а сразу пойдём дальше.

Расширение контекста

f23cff75eba838814c1b256281a982ad.png

Следующая возможная роль для нагрузочного тестировщика — инженер производительности. 

Производительность — более широкое понятие, чем нагрузочное тестирование, поэтому это уже следующий уровень. С этим шагом меняются и обязанности нагрузочного тестировщика, теперь в его зоне ответственности:

  • локализация проблем производительности помимо проверки требований — это когда что-то пошло не так в ходе нагрузочного теста, или есть какая-то проблема, и нужно понять, в чём она заключается: высокое потребление CPU, утечки памяти, 500-е ошибки и т. д.;

  • тюнинг производительности — с помощью кода или изменения конфигурации, реже архитектурные фиксы;

  • умная автоматизация и работа с инструментарием — написание скриптов, автоматизирующих работу. 

Но это ещё не всё. На уровне, когда вы ещё нагрузочный тестировщик и работаете в выделенном контуре или на тестовом стенде, обычно, у вас есть глухая дверь, за которой находится прод. Мало кто из нагрузочных тестировщиков эту дверь открывает.

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

Итоговый список основных задач инженера производительности выглядит так:

  • локализация проблем производительности и её тюнинг;

  • умная автоматизация и работа с инструментарием;

  • скрипты и запуски;

  • документация тестов;

  • проверка требований от заказчика;

  • написание заглушек;

  • работа с проблемами прода (иногда);

  • совсем редко испытания на проде (редко)

А теперь перейдём к тому, как нам превратиться из такого инженера производительности в SRE-инженера.

SRE-инженер и его starter pack

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

На этом этапе в голову приходят мысли: «Надо почитать, чем вообще должен заниматься SRE». И про это есть масса книг и подходов, которые легко гуглятся. Три вещи, которые можно найти с ходу — это performance, stability, availability и reliability. Собственно, это три базовых вещи, на которых строится SRE. 

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

По ходу дела может возникнуть вопрос: «А нужно ли нагрузочное тестирование, в этом вашем SRE? Или знания о JMeter, LoadRunner и Gatling, которые я копил, можно выкинуть?». На это я отвечу, что не нужно ничего выкидывать, ведь нагрузочное тестирование — это в том числе, инструментарий для SRE. Хорошее тому подтверждение — популярный инструмент k6, который прямо на главной странице своего сайта заявляет, что это средство нагрузочного тестирования для SRE.

Производительность

В задачах и практиках SRE, встречающихся на просторах интернета, есть интригующая фраза: «capacity planning». Сперва я подумал, что это, наверное, типичная capacity, которую делает каждый нагрузочный тестировщик, когда проводит тест-максимума. Но это не так, ведь сфера ответственности SRE чаще всего шире, чем какой-то определённый продукт. Под capacity planning в данном случае имеется в виду вся инфраструктура, на которой крутятся эти самые продукты.

Для того чтобы оценить capacity этой всей инфраструктуры, надо её как-то релевантно нагрузить — подумают бывалые нагрузочные тестировщики. И это задача, которая потребует очень много ресурсов.

3861d5dee2f3e77de68f72e0e3893ae2.png

Здесь советую идти от простого, и в самые популярные практики внедрять какие-то определённые триггеры. Например, мы в Samokat.tech живём в Kubernetes-среде на «железных» машинах. У нас есть определённый набор триггеров, который помогает соблюдать практику capacity planning.

Когда наш кластер утилизирован на 70%, мы понимаем то, что нам нужно закупать новые машины. Набор таких правил и будет являться практикой capacity planning. Основная её цель — предотвратить ресурсное исчерпание и делать его более прогнозируемым. И уже не нужно никаких супернагрузочных тестов. 

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

Стабильность

Стабильность системы означает её способность работать без каких-либо падений максимально длительное время.

ae901cebd8db039fd241f6f691873694.png

Как этого достичь? Есть очень популярная практика, которая называется incident management, описанная, например, в классном подходе документации ITIL. Заключается она в том, что мы должны реагировать на текущие проблемы и убирать их влияние на нашу систему, тем самым предотвращая новые проблемы. Звучит просто, но за этим скрывается коммуникация большого количества команд и много действий. Одно радует — эти процессы хотя бы понятно описаны. 

Если у вас будет стабильность, то можно говорить, что вы близки к SRE, или занимаетесь какой-то практикой SRE.

Практики стабильности очень тесно связаны с требованиями, которые мы предъявляем. Например, у нас есть требования к Deployment и Runtime. Давайте посмотрим, что это за требования и как они выглядят:  

  • настроены endpoints для Readiness/ Liveness probes;

  • минимально развёртывание сервиса осуществляется в два инстанса;

  • сервис умеет обрабатывать SIGTERM (закрываются сетевые соединения, сохраняются данные, завершаются любые работы);

  • сервис не хранит состояние и умеет запускаться в нескольких экземплярах (позволяет горизонтально масштабироваться и обеспечивать отказоустойчивость);

  • сервис пишет лог в stdout;

  • выставлены целочисленные значения CPU requests (>=1);

  • JVM | CPU requests =< 1 приводит к использованию SerialGC; 

  • JVM | в сервисе используется JDK 11+ версии;

Это то, что позволяет нашим приложениям создавать какую-то унификацию, чтобы мы не думали об уникальном решении проблем. 

Возникает вопрос: как это всё проверять? Особенно если у нас в приложении может быть 5 тысяч сервисов в продакшене.

Чтобы решить эту задачу — мы можем влиять на производственный процесс, например, сказать тестировщикам: «Ребята, с сегодняшнего дня вы каждый релиз проверяете на вот эти требования таким-то образом», т.е рассказываем им, на какие пункты надо смотреть. 

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

Надёжность


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

Здесь важно понять то, что эти паттерны в первую очередь влияют на слой приложения. 

Chaos engineering в версии нейросети

Chaos engineering в версии нейросети

Для того чтобы посмотреть, как эти паттерны работают в совокупности и понять, обеспечивают ли они нужную степень отказоустойчивости, нужны особенные тесты, например, Chaos engineering и испытания в проде (да-да).

Самый простой тест Chaos engineering выглядит следующим образом: запускаем нагрузочный тест и во время него у нас каким-то образом уничтожается под или инстанс нашего приложения. Без одного инстанса и при его падении наши приложения должны отвечать ровно тем нефункциональным требованиям, что и в полном составе.

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

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

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

Chaos engineering вместе с тестами в проде хорошо влияет на нашу надёжность. Вместе с этими практиками у нас появляются целые ворота в прод, вместо той двери, о которой мы говорили на уровне инженера по производительности.

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

Доступность

Доступность — это то время, в которое пользователь может зайти и получить услугу, которую предоставляет наш сервис, или воспользоваться нашим приложением. Иными словами, пройти по какому-то бизнес-процессу, который мы заложили.

Часто можно нагуглить, что SRE-инженеры занимаются SLA/SLI/SLO, это обратная практика бюджету ошибок и про неё можно делать отдельную статью. Поэтому я лучше напишу про бюджет ошибок. Условно он показывает, сколько мы были недоступны для пользователей в каком-то временном эквиваленте. 

Давайте на коленке сделаем такой бюджет ошибок и разберём каждый пункт:  

  • недоступность входных точек в бизнес-процессы;

  • недоступность главного процесса, который приносит прибыль и каждого его этапа;

  • потраченный бюджет == приоритезация задач отказоустойчивости.

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

Обычно пользователи заходят, набирают корзину и что-то там покупают. Кто-то редактирует свой профиль, кто-то пишет отзывы. Это все разные бизнес-процессы и их может быть очень много. Для того чтобы получить доступ к этим бизнес-процессам, нужна какая-то входная точка, то есть мы каким-то образом заходим на этот сайт.

При открытии главной страницы или приложения появляется доступ к определённому бизнес-процессу. Эта точка входа объединяет практически все бизнес-процессы и служит отправной точкой для их развития. Отсутствие доступа к этой точке является наиболее критической проблемой, так как оно блокирует все бизнес-процессы. Например, нашей точкой входа может быть главная страница со скидками, на которую пользователей привлекают наши рекламные акции.

Переходим ко второму пункту — главный процесс. Это минимальный набор действий, который совершает пользователь для того, чтобы приносить нам деньги, то есть когда он выбирает что-то на сайте, кладёт в корзину и нажимает «Оплатить». Это наш главный бизнес-процесс и его мы тоже можем померить с помощью метрик (клиентских, бэкендовских или каких-то ещё). 

Давайте сначала попробуем описать входную точку. Берём главную страницу, с которой выполняются 5–10 запросов в наш бэкенд при её загрузке. Запросы могут быть как блокирующие синхронные, так и не блокирующие асинхронные. 

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

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

Потом мы можем сказать, что пользователи не хотят долго ждать загрузки нашей входной точки, и ограничить эти запросы по времени, считая, что если эти запросы в 99-м процентиле превышают 2 секунды, то это тоже недоступность. 

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

Как вообще тратится бюджет ошибок и что мы с ним делаем? У нас есть интервал — например, месяц. Внутри этого месяца есть сколько-то секунд, которые мы можем потратить. Если мы недоступны большее время, чем у нас заложено в этот месяц, то мы не выполнили свои обязательства. 

Есть достаточно примеров таких бюджетов ошибок и этой доступности. Если зайти, например, на сайт AWS, то там написано, что их доступность 99,999%. Это тот процент времени внутри какого-то интервала, в который ребята гарантируют, что вы сможете зайти к ним  и что-нибудь сделать. В нашем случае мы стартанули с 99%, и смотрели, как мы тратим бюджет ошибок в месяц для этой величины. 

За всеми этими цифрами нужно не забывать, что бюджет ошибок — это про доступность для конкретной аудитории. Поэтому у нас в Samokat.tech есть две аудитории и два бюджета ошибок для каждой:

  • основные клиенты — люди, которые в «Самокате» делают заказы и получают домой какие-то классные продукты очень быстро;

  •  курьеры-партнёры и сборщики-партнёры, собирающие и доставляющие заказы, а также их руководители.

Индивидуальный бюджет ошибок для каждой из этих аудиторий это 7 часов 20 минут в месяц (1% времени в месяц). Именно столько времени мы можем «потратить» на ошибки исходя из наших же гарантий.

Итоговый портрет SRE-инженера

fe4f659ca9d651dbcc6bc748c696f39c.png

Теперь мы сложим всё то, что у нас получилось, и посмотрим на этого SRE-человека.

Его основные задачи: создавать требования, локализовывать проблемы прода, обеспечивать стабильность, производительность и надёжность. Это не пустые слова, под ними есть конкретные практики.

Работает он в основном на продуктовом стенде, но иногда заходит и на тестовые стенды для того, чтобы там поэкспериментировать.

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

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

© Habrahabr.ru