paint-brush
Как безопасно отправлять изменения в производствок@israel_hlc
16,506 чтения
16,506 чтения

Как безопасно отправлять изменения в производство

к 10m2023/10/24
Read on Terminal Reader

Слишком долго; Читать

Мы все знаем это упражнение, верно? После того, как мы закончим работу над изменением кода и (будем надеяться) протестируем его на нашей локальной машине, мы переносим изменение на следующий этап цикла. Локальное тестирование очень предвзято, и в идеале мы хотели бы проверить изменение в более стабильной среде (а также не следовать только точке зрения инженера, реализовавшего изменение).
featured image - Как безопасно отправлять изменения в производство
 HackerNoon profile picture

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


Следующий шаг здесь кажется вполне естественным: перенести изменения в надежную промежуточную среду и попросить партнеров (QA, PM, других инженеров) помочь с проверкой перед переносом изменений. За этим последует исправление ошибок и повторная проверка до тех пор, пока мы не убедимся, что продукт достаточно хорош для запуска в производство. Большой!


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


Проблема в том… Что, если что-то сломается? Собственно, как обнаружить проблемы раньше? Хорошие новости: можно внедрить некоторые инструменты и методы, чтобы сделать тестирование и валидацию в производстве не только безопасной практикой для вас и вашей компании, но, возможно, даже хорошей идеей.

Базовый уровень: метрики

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

Бизнес-метрики

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

Технические показатели

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


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

Мониторинг

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


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


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

Более безопасная посадка

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

Автоматизированные тесты

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


Стремление к 100%-ному покрытию тестами с помощью модульных, интеграционных и сквозных тестов может быть идеалистическим для большинства проектов. Вместо этого расставьте приоритеты тестов, основанных на усилиях, а не на выгоде. Метрики могут помочь в этом: охват основных бизнес-функций, вероятно, более важен, чем нишевые функции с меньшим влиянием, не так ли? Начните с основных функций, расширяя их по мере развития системы.


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

Тестирование

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


Существуют разные стратегии кормления собак. Для упрощения обзора мы могли бы сгруппировать их в две большие группы:

  1. Полная проверка артефактов : Это часто встречается, например, в приложениях для iOS/Android, где у нас есть встроенные инструменты для выпуска новой версии приложения для конкретных пользователей, а затем для того, чтобы сделать эту же версию доступной для широкой публики в магазинах.
  2. Выборочное догфудинг : Иногда невозможно (или даже желательно) протестировать весь артефакт, но мы все равно можем разрешить тестирование на основе конкретной пользовательской информации. Скажем, например, мы можем идентифицировать сотрудников, сопоставив некоторые данные. Затем приложение можно настроить на включение/отключение определенной функции путем проверки этих данных и предоставления пользователю желаемого поведения. Приложение будет содержать обе функции, но новое изменение затронет только некоторых пользователей. Мы вернемся к некоторым из этих концепций в следующих темах.

Канарский релиз

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


Канарский релиз


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

Синий Зеленый Развертывание

Blue Green Deployment, практика DevOps, направлена на предотвращение простоев за счет использования двух кластеров серверов (синего и зеленого) и переключения производственного трафика между ними. Во время развертывания функций изменения публикуются в одном наборе (зеленый), а другой (синий) остается неизменным. В случае возникновения проблем трафик можно быстро вернуть на серверы Blue, поскольку они продолжали работать в предыдущей версии.


#Синий зеленый развертывание

Развертывание Blue Green часто противопоставляют Canary Release, о котором мы говорили ранее. Мы не будем углубляться в детали этого обсуждения, но важно упомянуть об этом, чтобы помочь нам решить, какие инструменты больше подходят для нашей работы.

Аварийные переключатели и переключатели функций

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


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


 if (feature_is_enabled('feature_x')) {xNewBehaviour();} else {xOldBehaviour();}


Допустим, например, что мы осуществляем миграцию на новый сторонний API. В тестах все в порядке, в канареечной версии все стабильно, а затем изменение на 100% выкатывается в производство. Через некоторое время новый API начинает бороться с объёмом и запросы начинают падать (помните технические метрики?). Поскольку у нас есть аварийный переключатель, запросы API можно мгновенно вернуть к старому API, и нам не нужно возвращаться к предыдущей версии или быстро выпускать исправления.


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

Сохранение старого поведения доступным

Код, приведенный выше, вероятно, заставил некоторых из нас задуматься, действительно ли это хороший шаблон, когда в приложении одновременно присутствуют и старые, и новые варианты поведения. Я согласен, что это, скорее всего, не то конечное состояние, которое мы хотим для нашей кодовой базы, иначе каждый фрагмент кода будет окружен предложениями if/else, что сделает код нечитаемым в кратчайшие сроки.


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


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

Теневое тестирование

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


 int sum(int a, int b) {int currentResult = currentMathLib.sum(a, b);int newResult = newMathLib.sum(a, b);logDivergences(a, b, currentResult, newResult);return currentResult;}void logSumDivergences(int a, int b, int currentResult, int newResult) {if (currentResult != newResult) {logger.warn(      'Divergence detected when executing {0} + {1}: {2} != {3}',a, b, currentResult, newResult);}}


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


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


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

Журналы

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


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

Последние мысли

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


Всем безопасной посадки!