Главная » Хабрахабр » Patch me if you can: как мы отлаживаемся на production. Часть 1

Patch me if you can: как мы отлаживаемся на production. Часть 1

Привет, Хабр! Меня зовут Александр Измайлов. В Badoo я возглавляю команду релиз-инженеров. Я знаю, что во многих компаниях можно присылать изменения кода специально обученному человеку, он их смотрит и добавляет куда следует (например, именно так происходит с кодом Git). А я хочу рассказать о том, как мы автоматизировали этот процесс у нас.

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

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

Так у нас появилась идея создать систему патчей. Время шло, компания росла — и нам пришлось задуматься об автоматизации процессов, включая процесс выкладки небольших изменений. С нашей стороны мы требовали, чтобы изменения посмотрел ещё один разработчик и чтобы они были привязаны к задаче из нашей багтрекинговой системы (мы используем Jira). В первую очередь мы хотели, чтобы она позволяла любому разработчику присылать свои изменения в Git и раскладывать их на серверы.

Patch collector 6000

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

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

А что нам надо?

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

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

На второй странице можно было посмотреть изменения, отклонить или принять их.

После подтверждения изменения попадали в master.

Сегодня многие используют непрерывную интеграцию, и она могла бы хорошо справиться с задачей, если бы наши «честные» сборка и раскладка не занимали так много времени. Второй вопрос: как эти изменения быстро доставить до серверов?

Честная сборка

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

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

Для этого мы использовали блочное устройство, которое мы называли лупом. Дальше состояние директории нужно было куда-то сохранить. С этих серверов мы забирали архивы в процессе раскладки. Вся директория копировалась на пустое устройство, которое затем архивировалось и доставлялось на отдельные «главные» серверы. На сборку без статики у нас уходило около пяти минут. Каждый архив был объёмом 200 Мб, а в распакованном виде луп весил 1 Гб.

Честная раскладка

Сначала нам нужно было доставить архив на конечные серверы. Их у нас тысячи, поэтому вопрос доставки для нас всегда был большой проблемой: у нас несколько платформ (дата-центров), и на самой «толстой» порядка тысячи серверов с кодом. В попытках добиться лучших показателей (минимум времени и ресурсов) мы перепробовали разные методы: от простого SCP до торрентов. В итоге мы остановились на использовании UFTP. Метод был быстрым (при хорошей погоде — минута времени), но, к сожалению, не беспроблемным. Периодически что-то ломалось, и нам приходилось бежать к админам и сетевикам.

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

Никакой сборки

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

Оно живо

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

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

Один патч на несколько файлов

Пример предсказуемой проблемы. Новые файлы раскладывались по очереди. Что делать, если нужно изменить несколько файлов и изменения в них связаны? Например, я хочу добавить новый метод в одном файле и сразу использовать его в других. Пока нет закольцованного использования методов (см. взаимная рекурсия), достаточно помнить о правильном порядке раскладки файлов.

Честное решение

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

Допустим, у нас есть директория Д, и нам нужно заменить её содержимое. Усложним задачу. Однако есть обходное решение: можно заранее заменить директорию Д на так называемую символическую ссылку (symlink). Операция rename нам не поможет, потому что она не может заменить непустую директорию. В тот момент, когда потребуется замена, новое содержимое записывается в директорию Д_2, на которую создаётся новая ссылка TMP. Тогда само содержимое будет лежать в другом месте, например, в директории Д_1, а Д будет ссылкой на Д_1. Теперь rename TMP Д сработает, потому что эту операцию можно применять к ссылкам.

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

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

Несколько патчей на один файл

Сложнее, если файл один, а разработчиков, которые хотят его изменить, — несколько. Первый патч мы применили, но не разложили. В этот момент приходит второй патч, и его просят разложить. Что делать? Ещё интереснее, если второй патч применился, и в этот момент нас просят разложить первый.

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

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

Много патчей, и все меняют одни и те же файлы

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

Картинка: источник

Проблемы с железом

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

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

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

Ложка мёда

Но, кроме проблем, были и положительные моменты.

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

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

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


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

Сетевой дайджест: 20 экспертных материалов о протоколах, стандартах и информационной безопасности

В эту подборку мы включили свежие посты, подготовленные специалистами компании VAS Experts. Главные темы подборки — сетевые протоколы, 5G и информационная безопасность. Под катом вы также найдете ряд рекомендаций по построению сетей операторов связи. / Pxhere / PD Про ИБ ...

[Перевод] Забудьте о мегаструктурах инопланетян: новые наблюдения объясняют поведение звезды Табби одной только пылью

Художественное изображение KIC 8462852, яркость которой за последние несколько лет менялась необычным образом Когда планета проходит перед её родительской звездой, если смотреть с нашей точки зрения, часть света звезды на некоторое время исчезает. Научная охота за планетами в XXI веке ...