Lev Goncharov

Infrastructure simplifying engineer

View My GitHub Profile

Agreements as Code: как отрефакторить инфраструктуру и не сломаться

Agreements As Code

Date: 2020-10-09

Здесь расшифровка выступления на TechLeadConf 2020-06-09. Прежде чем начнем, попробуйте ответить для себя на вопрос какие у вас ожидания от взаимодействия с инфраструктурой? Например сколько времени займет:

Спойлер результатов опроса во время TechLeadConf:

! Menti

You are asking for a new environment

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

Инфраструктура как она есть

Cлучайности + Договоренности + Процессы = Инфраструктура

Infrastructure

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

  1. Случайность. Есть приложение. Но оно не появляется просто так, его разрабатывают вполне конкретные люди. Со временем или сразу появляется потребность развернуть/запустить приложение где-то(Спасибо Кэп!). В нашем случае лет 10-15 назад было отправлено письмо с просьбой смонтировать сервер в стойку. У кого-то это просьба в телеграмм чате настроить сервер. Суть в том, что инфраструктура это про то, что вас кто-то что-то попросил сделать, развернуть сервис. Изменения не происходят потому что вам так захотелось, за изменениями стоят люди.
  2. Договоренности. Со временем, случайные запросы на изменения через jira, email, slack могут перерасти в хаотичный поток запросов. В нашем случае необходимо было разворачивать множество окружений похожих на клиентские. Но бывает можно услышать “если хотите ускорить развёртывание, то не пишите нам в четверг, потому что мы ходим в серверную по средам”. Появляются договоренности.
  3. Процессы. Апогеем становится преобразование договоренности в процесс. Появляется формальный процесс: заведите таску в jira, заполните необходимые поля и в течение 7 дней первый освободившийся инженер создаст вам новое окружение.

Инфраструктура стремится к хаосу

Infrastructure -> Chaos

Как вы понимаете, монтаж серверов в стойку, процесс не быстрый, а разработка должна лететь. Но всё меняется, и приложение было контейнеризировано. Появилась возможность создавать динамически виртуалки на CoreOS и запустив compose файл получить окружение похожее боевое. Этакий k8s на минималках. И тут появился первый звоночек: а кто отвечает за YML файлике в git? Кто описывает инфру? Закономерно, код без присмотра начинает дурно пахнуть и привет групповая безответственность. Растет технический долг за счет быстрых и незаменимых подпорок из велосипедов. Меняется команда с одной стороны, потом с другой. И всё. Приплыли. Наступает ОПА момент - когда инфраструктура работает, но никто не видит картинку целиком и не понимает почему она работает именно так. Это ни хорошо и ни плохо. Это данность: Инфраструктура стремится к хаосу, как и наша вселенная стремится к тепловой смерти.

Как бороться с Хаосом?

Бумажки и инструкции на защите от хаоса

Deal with chaos

Написать инструкции может прийти первым на ум, когда вы захотите бороться с хаосом. У меня тут есть, забавная история, как в одной ооооочень большой организации любили писать бумажки почти на каждый чих. Однажды, там для переезда сервиса согласовали временную схему сети на пару недель и выставили сервис в интернет. Соль в, том что я нашел это спустя пять лет. А на минутку это: нефтебаза… в аэропорту… с доступом в сеть ЦОД. Не хорошо как-то. Бумажка есть, а реальность показывает другое.

Agreements as Code

Deal with chaos

Аналогичная ситуация будет с задачами в Jira. Вас попросили, подготовить новое окружение. Вы что-то сделали и забыли как-оно там было настроено. Но если те же договорённости формализовать в виде кода. Пусть даже на своем DSL, или просто кодом на Ansible написали. Итогом у вас есть воспроизводимое решение и единая точка правды. Кто-то то поправил код в репозитории и вот обновленная версия приложения уже в проде. Но стоит ли это все эти договоренности автоматизировать? Стоит ли овчинка выделки?

Agreements as Code внедрять нельзя забить

Agreements as Code

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

Agreements as Code

Рассмотрим краевые случаи:

Ручной труд -> Механизация -> Автоматизация

Agreements as Code

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

Agreements as Code

Когда эволюционировать и переходить на следующий уровень автоматизации, а когда нет?

По мере развития инфраструктуры, договоренности формализуются в виде кода и стремятся стать * as Service.

Инфраструктуру можно и нужно рефакторить. Но не всегда

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

Ansible: Миграция конфигурации 120 VM c Coreos на Centos за 18 месяцев

IaC refactoring

В моем случае, досталось в наследство самописное configuration management решение. Оно представляло инфраструктуру в виде кода, оно работало, но его поддержка было сложной, т.к. оно было хрупкой, никто не хотел его поддерживать. Планомерным итогом стала замена его на Ansible, подробности можно глянуть тут Ansible: Миграция конфигурации 120 VM c Coreos на Centos за 18 месяцев. Почему 1,5 года заняла миграция? Ответ прост - 80% был reverse engineering как оно работает и только 20% непосредственно написание плэйбуков, ролей и миграция. Сам же процесс был прост:

CFM 2 Ansible

  1. Сформировать список серверов.
  2. Выбрать сервер из списка не перенесенных.
  3. Зафиксировать текущие договоренности.
  4. Разобраться как работает.
  5. Описать в виде кода.
  6. Вернуться на пункт №2.

Как начать тестировать Ansible, отрефакторить проект за год и не слететь с катушек

Ansible refactoring

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

  1. Составить список существующих ролей.
  2. Выбрать одну роль.
  3. Покрыть тестами и зафиксировать текущие договоренности.
  4. Внести правки в плэйбуки/роли, исправив причины падения.

Как реализовано тестирование Ansible ролей?

Ansible testing

Так исторически сложилось, что использовался репозиторий в котором лежали все роли. Был создан Jenkins Pipeline, который:

  1. Вычитвает конфиг из репозитория что тестировать.
  2. Генерирует динамически стадии для Jenkins.
  3. Запускает lint для всех ролей и плэйбуков.
  4. Запускает molecule для всех ролей

Реафаторинг IaC

IaC refactoring

Мы то с вами помним, что инфраструктура эволюционирует и формализуется в скрипты и/или множество * as Service. А с этим можно работать как с кодом и переиспользовать практики по рефакторингу кода. Из предыдущих сценариев выбивается нечто общее:

  1. Определяем измеримую цель.
  2. Проверяем наличие нужных знаний и времени на изменения.
  3. Выбираем маленький кусочек инфраструктуры.
  4. Разбираем что он делает.
  5. Формализуем договоренности и покрываем их тестами.
  6. Отдыхаем(это важно! иначе сгоришь оставив недоделанным работу).
  7. Повторяем.

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

Ускоряем ускорение

IaC testing

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

По графику можно увидеть, что:

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

Используй IaC testing pyramid. Не откладывай не потом!

IaC testing pyramid

Годом ранее на DevopConf рассказывал Что я узнал, протестировав 200 000 строк инфраструктурного кода и подробно рассмотрел пирамиду тестирования инфраструктуры. Ровно таже идея, что в разработке, но для инфраструктуры: идем от дешевых быстрых тестов, которые проверяют простые вещи, например отступы, к дорогим полноценным тестами разворачивающих цельную инфраструктуру.

Когда начинать писать тесты?

Ок, договоренности в инфраструктуре можно представить как код. А потом можно рефакторить. А если есть тесты, то еще и не закопаться в рефакторинге. Но вот вопрос, когда начинать писать тесты? Рассмотрю пару проектов.

Проект №1

IaC testing

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

Проект №2

IaC testing

На другом проекте рефакторинг начался с линтинга и весьма бодро пошёл. Но и кодовая база была скромная.

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

Lessons learned

  1. Инфраструктура стремится с хаосу.
  2. Agreements as Сode внедрять нельзя забить.
  3. Ручной труд -> Механизация -> Автоматизация.
  4. Инфраструктуру можно и нужно рефакторить. Но не всегда.
  5. Тесты на инфраструктуру удешевляют/ускоряют ее изменения.
  6. Используй IaC testing pyramid. Не откладывай не потом!