АрхитектураОблако и инфраструктураИнженер по DevOps и облачной инфраструктуре

Два инженера одновременно запускают изменение одной инфраструктуры. Как блокировка состояния предотвращает ...

Два инженера одновременно запускают изменение одной инфраструктуры. Как блокировка состояния предотвращает повреждение общего состояния?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

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

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

Исторический контекст

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

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

Постановка проблемы

Пусть инженер A добавляет сеть, а инженер B одновременно меняет правила доступа. Оба считывают состояние версии 10, строят планы и после применения пытаются записать версии 11, содержащие разные изменения.

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

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

Подробное решение

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

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

Блокировка должна находиться в общем надёжном хранилище, доступном всем участникам: локальный файл на ноутбуке инженера не защищает операции на CI-серверах. Важно также, чтобы backend поддерживал атомарную попытку захвата lock; проверка «прочитать, затем записать признак занятости» без атомарности сама подвержена гонке.

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

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

Следует различать блокировку состояния и блокировку облачного ресурса. Первая сериализует операции конкретного backend состояния, но другой инструмент, ручное изменение в консоли или отдельный pipeline могут изменить тот же ресурс вне этого lock.

Ситуация из практики

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

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

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

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

Что кандидаты часто упускают

  1. Означает ли успешное получение lock, что план гарантированно безопасен?

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

  1. Что произойдёт, если процесс упадёт, удерживая блокировку?

Зависит от backend и его протокола. Lock может быть снят явной операцией, автоматически освобождён после истечения lease или остаться до ручного вмешательства. Принудительное снятие без проверки опасно: исходный процесс мог не завершиться и продолжить запись. Сначала проверяют журнал запуска, владельца, время установки и наличие активного процесса, затем удаляют зависший lock предусмотренной процедурой.

  1. Защищает ли блокировка от изменений через облачную консоль?

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