инфраструктура как код что это
Инфраструктура как код. Введение для начинающих
Согласно отчету «State of DevOps 2019», 80% респондентов сказали, что основное приложение или служба, которую они поддерживали, было размещено на какой-то облачной платформе. 50% респондентов заявили, что их основное приложение размещено в публичном облаке.
Что такое инфраструктура как код?
Идея состоит в том, что вы относитесь к своей инфраструктуре как к программному обеспечению, а затем пишете, тестируете и выполняете код для определения, развертывания, обновления и уничтожения своей инфраструктуры.
Вы пишете код для управления своими серверами, базами данных, сетями, журналами, развертыванием и настройкой приложений. Когда вы хотите внести изменения в свою инфраструктуру, вы вносите изменения в код, тестируете его, а затем применяете его в своих системах.
Льготы
Инфраструктура как код предоставляет значительные преимущества по сравнению с ручной подготовкой:
Самообслуживание
Поскольку инфраструктура определяется как код, весь процесс и развертывание могут быть автоматизированы и могут быть запущены любым пользователем в команде DevOps. Пользователи инфраструктуры получают ресурсы, которые им нужны, когда им это нужно.
Идемпотентность
Идемпотентность означает, что вы определяете желаемое состояние, и независимо от того, сколько раз вы запускаете скрипт, результат будет одинаковым. Он проверяет текущее и желаемое состояние и применяет только те изменения, которые необходимы. Этого может быть чрезвычайно трудно достичь с помощью скриптов bash.
Такие инструменты, как Ansible и Terraform, имеют встроенные функции, которые делают ваш код идемпотентным.
Снижение затрат
Сокращает время и усилия, необходимые для предоставления, намного меньше, чем подготовка вручную.
Более быстрая доставка программного обеспечения
Быстрое предоставление инфраструктуры для разработки, тестирования и производства позволяет значительно быстрее доставлять программное обеспечение. Поскольку процесс развертывания автоматизирован, он также последовательный и повторяемый.
Самодокументирование
Состояние инфраструктуры определяется в коде, который легко читается любым человеком.
Контролируемая версия
Традиционно изменения в производственных системах считаются рискованными. Но тогда изменения неизбежны. Вам может потребоваться добавить новую базу данных при добавлении новой функции. Вам может потребоваться добавить новые серверы или хранилище в кластер. Инфраструктура как код уменьшает усилия и риск внесения изменений в инфраструктуру.
Вы можете проверить свои исходные файлы в системе управления версиями, что означает, что вы можете отслеживать все изменения, внесенные в инфраструктуру, и быстро возвращаться к предыдущей версии, если что-то сломается.
Валидация и тестирование
Инфраструктура как код позволяет постоянно тестировать и применять небольшие изменения. Поскольку все является кодом, вы можете проверять ошибки, используя статический анализ и автоматические тесты.
Улучшенная безопасность
Переход к инфраструктуре в виде кода позволяет встроить систему безопасности с самого начала, а затем вы можете надежно и безопасно применять изменения.
Инфраструктура как инструменты кода
Несмотря на то, что доступно много инструментов, выбрать один из них для работы может быть нелегко. Ниже приведены некоторые соображения, которые могут оказаться полезными:
Управление конфигурацией и инструменты обеспечения
В целом доступные инструменты подпадают под две категории:
Инструменты управления конфигурацией
Вы можете использовать инструменты управления конфигурацией для установки и обновления программного обеспечения на серверах.
Инструменты обеспечения
Terraform, CloudFormatio, OpenStack Heat, с другой стороны, являются инструментами обеспечения, т.е. Используются для создания серверов, серверов баз данных, балансировщиков нагрузки, очередей, подсетей, брандмауэров и всех других компонентов вашей инфраструктуры. Эти инструменты делают API-вызовы к провайдерам для создания необходимой инфраструктуры.
Изменчивая и неизменная инфраструктура
После многих обновлений каждый сервер, вероятно, будет немного отличаться от других, что приведет к смещению конфигурации. Например, некоторые изменения, которые отлично работают на тестовых серверах, могут не работать на производственных серверах.
Такие инструменты, как Terraform и CloudFormation, предназначены для того, чтобы каждый раз создавать новый сервер из образа машины или образа контейнера. Если необходимо обновить серверы, вы замените их новыми серверами.
Когда новые серверы работают, вы можете отключить старые. Каждое развертывание использует неизменяемый образ для создания сервера, что позволяет избежать смещения конфигурации.
Императивные и декларативные инструменты
Обязательные инструменты похожи на скрипты. Вы перечисляете шаги, которые необходимо предпринять для достижения желаемого состояния. Декларативные инструменты позволяют вам указать конечное состояние, и инструмент разрабатывает шаги для достижения этого состояния.
В то время как Chef является в первую очередь императивным инструментом, Ansible использует гибридный подход и поддерживает как императивные, так и декларативные методы.
Terraform, CloudFormation, Puppet, OpenStack Heat и SaltStack принадлежат к категории декларативных инструментов, в которой вы объявляете желаемое конечное состояние.
Использование нескольких инструментов вместе
Хотя каждый из этих инструментов может использоваться самостоятельно, общий подход состоит в том, чтобы использовать их вместе. Например, вы можете использовать Terraform для создания VPC, подсетей, интернет-шлюзов, балансировщиков нагрузки и виртуальных машин, а затем использовать Ansible для настройки и развертывания служб в этих экземплярах.
Заключение
Что такое «Инфраструктура как код»?
Инфраструктура как код (IaC) — это управление инфраструктурой (сетями, виртуальными машинами, подсистемами балансировки нагрузки и топологией подключения) в описательной модели с использованием той же версии, что и группа DevOps, используемая для исходного кода. Подобно принципу, согласно которому один и тот же исходный код создает один и тот же двоичный файл, модель IaC при каждом применении формирует одну и ту же среду. IaC является ключевым DevOps методикой и используется в сочетании с непрерывной поставкой.
IaC решает реальные проблемы
Инфраструктура по мере развития кода для решения проблемы с отклонением среды в конвейере выпуска. Без IaC команды должны поддерживать настройки отдельных сред развертывания. Со временем каждая среда становится « _снежинка_», то есть уникальной конфигурацией, которая не может быть воспроизведена автоматически. Несогласованность между средами приводит к проблемам во время развертывания. Администрирование и обслуживание инфраструктуры связано с выполняемыми вручную процессами, которые сложно отследить и которые приводят к возникновению ошибок.
Идемпотентность является принципом инфраструктуры в виде кода. Идемпотентность — это свойство, которое команда развертывания всегда задает целевую среду в той же конфигурации независимо от состояния запуска среды. Идемпотентности достигается либо автоматической настройкой существующего целевого объекта, либо путем удаления существующей цели и повторного создания новой среды.
Соответственно, при использовании IaC команда вносит изменения в описание среды и версию модели конфигурации, которая обычно находится в хорошо документированных форматах кода, таких как JSON. Конвейер выпуска выполняет модель для настройки целевых сред. Если группе необходимо внести изменения, они изменяют источник, а не целевой объект.
IaC предоставляет реальные преимущества
Инфраструктура как код позволяет командам DevOps тестировать приложения в рабочих средах на ранних этапах цикла разработки. Эти команды предполагают, что несколько тестовых сред надежно и по требованию. Инфраструктура, представленная в виде кода, также может быть проверена и протестирована для предотвращения распространенных проблем развертывания. В то же время облако динамически подготавливает и слезами среды на основе определений IaC.
Команды, реализующие IaC, могут быстро доставлять стабильные среды и масштабировать их. Команды избегают ручной настройки сред и обеспечивают согласованность, представляя требуемое состояние своих сред с помощью кода. Развертывания инфраструктуры с IaC являются повторяемыми и предотвращают проблемы во время выполнения, вызванные отклонением конфигурации или отсутствием зависимостей. Команды DevOps могут работать вместе с единым набором практических рекомендаций и средств, позволяющих быстро и надежно предоставлять приложения и их поддерживающую инфраструктуру.
Предпочитать декларативные определения
Предпочтительный подход к IaC — использование файлов декларативного определения, где это возможно. В файле определения указывается, что требует Среда, а не обязательно. Иными словами, он может определить конкретную версию и конфигурацию серверного компонента в качестве требования, но не указывает процесс установки и настройки. Эта абстракция обеспечивает большую гибкость в середине, например оптимизированные методы, которые может использовать поставщик инфраструктуры. Кроме того, это позволяет сократить технические обязательства по обслуживанию императивного кода, такого как сценарии развертывания, которые могут начисляться со временем.
Для декларативного IaC не существует единого стандартного синтаксиса. Различные платформы поддерживают разные и зачастую несколько форматов файлов, таких как YAML, JSON и XML. В результате решение о выборе синтаксиса для описания IaC обычно сводится к требованиям целевой платформы.
Использование IaC в Azure
Azure обеспечивает собственную поддержку IaC с помощью Azure Resource Manager. Команды могут определять декларативные шаблоны, указывающие инфраструктуру, необходимую для развертывания своих решений.
Что я узнал, протестировав 200 000 строк инфраструктурного кода
Подход IaC (Infrastructure as Code) состоит не только из кода, который хранится в репозитории, но еще людей и процессов, которые этот код окружают. Можно ли переиспользовать подходы из разработки ПО в управление и описание инфраструктуры? Будет не лишним держать в голове эту идею, пока будете читать статью.
Infrastructure as bash history
Предположим приходите вы на новый проект, а вам говорят: «у нас Infrastructure as Code«. В реальности оказывается, Infrastructure as bash history или например Documentation as bash history. Это вполне реальная ситуация, например, подобный случай описывал Денис Лысенко в выступление Как заменить всю инфраструктуру и начать спать спокойно, он рассказал как из bash history они получили стройную инфраструктуру на проекте.
При некотором желании, можно сказать, что Infrastructure as bash history это как код:
Infrastructure as Code
Даже такой странный случай как Infrastructure as bash history можно притянуть за уши к Infrastructure as Code, но когда мы захотим сделать что-нибудь посложнее чем старый добрый LAMPовый сервер, мы прийдем к тому, что этот код необходимо как-то модифицировать, изменять, дорабатывать. Далее хотелось мы будем рассматривать параллели между Infrastructure as Code и разработкой ПО.
На проекте по разработке СХД, была подзадача периодически настраивать SDS: выпускаем новый релиз — его необходимо раскатать, для дальнейшего тестирования. Задача предельно простая:
Для описанной логики более чем достаточно bash, особенно на ранних стадиях проекта, когда он только стартует. Это не плохо что вы используете bash, но со временем появляются запросы развернуть нечто похожее, но чуть-чуть отличающиеся. Первое что приходит в голову: copy-paste. И вот у нас уже два очень похожих скрипта, которые делают почти тоже самое. Со временем кол-во скриптов выросло, и мы столкнулись с тем, что есть некая бизнес логика развертывания инсталляции, которую необходимо синхронизировать между разными скриптами, это достаточно сложно.
Оказывается, есть такая практика D.R.Y. (Do not Repeat Yourself). Идея в том, чтобы переиспользовать существующий код. Звучит просто, но пришли к этому не сразу. В нашем случае это была банальная идея: отделить конфиги от скриптов. Т.е. бизнес логика как разворачивается инсталляция отдельно, конфиги отдельно.
S.O.L.I.D. for CFM
Со временем проект рос и естественным продолжением стало появление Ansible. Основная причина появления его это наличие экспертизы в команде и что bash не предназначен для сложной логики. Ansible тоже стал содержать сложную логику. Для того что бы сложная логика не превращалась в хаос, в разработке ПО существуют принципы организации кода S.O.L.I.D. Так же, например, Григория Петров в докладе «Зачем айтишнику личный бренд» затронул вопрос, что человек, так устроен, что ему проще оперировать какими-то социальными сущностями, в разработке ПО это объекты. Если объединить эти две идеи продолжить развивать их, то можно заметить, что в описании инфраструктуры тоже можно использовать S.O.L.I.D. что бы в дальнейшем было проще поддерживать и модифицировать эту логику.
The Single Responsibility Principle
Каждый класс выполняет лишь одну задачу.
Не надо смешивать код и делать монолитные божественные макаронные монстры. Инфраструктура должна состоять из простых кирпичиков. Оказывается, что если раздробить Ansible playbook на небольшие кусочки, читай Ansible роли, то их проще поддерживать.
The Open Closed Principle
Изначально мы разворачивали тестовую инфраструктуру на виртуальных машинах, но за счет того, что бизнес логика разворачивания была отдельно от реализации, мы без проблем добавили раскатку на bare-metall.
The Liskov Substitution Principle
Принцип подстановки Барбары Лисков. объекты в программе должны быть заменяемыми на экземпляры их подтипов без изменения правильности выполнения программы
Если посмотреть шире, то не особенность какого-то конкретного проекта, что там можно применить S.O.L.I.D., оно в целом про CFM, например, на другом проекте необходимо разворачивать коробочное Java приложение поверх различных Java, серверов приложений, баз данных, OS, итд. На это примере я буду рассматривать дальнейшие принципы S.O.L.I.D.
В нашем случае в рамках инфраструктурной команды есть договоренность, что если мы установили роль imbjava или oraclejava, то у нас есть бинарный исполняемый файл java. Это нужно т.к. вышестоящее роли зависят от этого поведения, они ожидают наличие java. В тоже время это нам позволяет заменять одну реализацию/версию java на другую при этом не изменяя логику развертывания приложения.
Проблема здесь кроется в том, что в Ansible нельзя реализовать такое, как следствие в рамках команды появляются какие-то договоренности.
The Interface Segregation Principle
Принцип разделения интерфейса «много интерфейсов, специально предназначенных для клиентов, лучше, чем один интерфейс общего назначения.
Изначально мы пробовали складывать всю вариативность разворачивания приложения в один Ansible playbook, но это было сложно поддерживать, а подход, когда у нас специфицирован интерфейс наружу (клиент ожидает 443 порт) то под конкретную реализацию можно компоновать инфраструктуру из отдельных кирпичиков.
The Dependency Inversion Principle
Принцип инверсии зависимостей. Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Здесь пример будет основан на антипаттерне.
Т.е. высокоуровневая логика развертывания приложения, зависимостями протекала на нижележащие уровни гипервизора, и это означало проблемы при переиспользование этой логики. Не надо так.
Interaction
Инфраструктура как код — это не только про код, но ещё и про отношения между кодом и человеком, про взаимодействия между разработчиками инфраструктуры.
Bus factor
Предположим, что у вас на проекте есть Вася. Вася всё знает про вашу инфраструктуру, что будет если Вася вдруг пропадет? Это вполне реальная ситуация, ведь его может сбить автобус. Иногда такое случается. Если такое случится и знание о коде, его структуре, как он работает, явках и паролях, не распределены в команде, то можно столкнуться с рядом неприятных ситуаций. Что бы минимизировать эти риски и распределить знание в рамках команды можно использовать различные подходы
Pair Devopsing
Это не как в шутке, что админы пили пиво, пароли меняли, а аналог парного программирования. Т.е. два инженера садятся за один компьютер, одну клавиатуру и начинают вместе настраивать вашу инфраструктуру: сервер настраивать, Ansible роль писать, итд. Звучит красиво, но у нас не сработало. Но вот частные случаи этой практики работали. Пришел новый сотрудник, его наставник вместе с ним берет реальную задачу, работает — передает знание.
Другой частный случай, это incident call. Во время проблемы собирается группа дежурных и причастных, назначается один ведущий, который расшаривает свой экран и озвучивает ход мысли. Другие участники следуют за мыслью ведущего, подсматривают трюки из консоли, проверяют что не пропустил строчку в логе, узнают новое об системе. Такой подход скорее работал, чем нет.
Code Review
Субьективно, более эффективно распространение знаний об инфраструктуре и том как она устроена проходило при помощи code review:
Изюминкой здесь было, то что ревьюверы выбирались по очереди, по графику, т.е. с некоторой долей вероятности ты залезешь в новый участок инфраструктуры.
Code Style
Со временем стали появляться склоки во время ревью, т.к. у ревьюверов был свой стиль и ротируемости ревьюверов стакивала их с разными стилями: 2 пробела или 4, camelCase или snake_case. Внедрить это получилось не сразу.
Green Build Master
Время идет, и пришли к тому что нельзя пускать в мастер коммиты, которые не проходят некие тесты. Вуаля! мы изобрели Green Build Master который уже давным-давно практикуется в разработке ПО:
Принятие этого решения было весьма болезненным, т.к. вызвало множество споров, но оно того стоило, т.к. на ревью стали приходить запросы на слияние без разногласий по стилю и со временем кол-во проблемных мест стало уменьшаться.
IaC Testing
Кроме проверки стиля можно использовать и другие вещи, например, проверять что ваша инфраструктура действительно может развернуться. Или проверять что изменения в инфраструктуре не приведут к потере денег. Зачем это может понадобиться? Вопрос сложный и философский, ответить лучше байкой, что как-то был auto-scaler на Powershell который, не проверял пограничные условия => создалось больше ВМ чем надо => клиент потратил денег больше чем планировал. Приятного мало, но эту ошибку вполне реально было бы отловить на более ранних стадиях.
Можно спросить, а зачем делать сложную инфраструктуру еще сложнее? Тесты для инфраструктуры, так же, как и для кода, это не про упрощение, а про знание как ваша инфраструктура должна работать.
IaC Testing Pyramid
IaC Testing: Static Analysis
Если сразу разворачивать всю инфраструктуру и проверять, что она работает, то может оказаться, что это занимает уйму времени и требует кучу времени. Поэтому в основе должно быть что-то быстро работающее, его много, и оно покрывают множество примтивных мест.
Bash is tricky
Вот рассмотрим банальный пример. выбрать все файлы в текущей директории и скопировать в другое место. Первое что приходит в голову:
А что если в имени файла пробел есть? Ну ок, мы же умные, умеем пользоваться кавычками:
Молодцы? нет! Что если в директории нет ничего, т.е. глобинг не сработает.
Static analysis tools
Проблему из предыдущего шага можно было отловить когда мы забыли кавычки, для это в природе существует множество средство Shellcheck, вообще их много, и скорей всего вы сможете найти под свою IDE линтер для вашего стэка.
IaC Testing: Unit Tests
Как мы убедились из предыдущего примера, линтеры не всемогущие и не могут указать на все проблемные места. Дальше по аналогии с тестированием в разработке ПО можно вспомнить про unit tests. Тут сразу на ум приходят shunit, junit, rspec, pytest. Но что делать с ansible, chef, saltstack и иже с ними?
В самом начале мы говорили про S.O.L.I.D. и то что наша инфраструктура должна состоять из маленьких кирпичиков. Пришло их время.
IaC Testing: Unit Testing tools
Вопрос, а что такое тесты для CFM? можно банально запускать скрипт, а можно использовать готовые решения для этого:
Что выбрать? вопрос сложный и не однозначный, вот пример изменения в проектах на github за 2018-2019 года:
IaC Testing frameworks
Возникает как это все собрать вместе и запустить? Можно взять и сделать всё самому при наличии достаточного кол-во инженеров. А можно взять готовые решения, правда их не очень-то и много:
Пример изменения в проектах на github за 2018-2019 года:
Molecule vs. Testkitchen
Для 25-35 ролей это работало 40-70 минут, что было долго.
Следующим шагом стал переход на jenkins / docker / ansible / molecule. Идиологически все тоже самое
Линтовка для 40 ролей и тесты для десятка стали занимать порядка 15 минут.
Что выбрать зависит от множества факторов, как то используемый стэк, экспертиза в команде итд. тут каждый решает сам как закрывать вопрос Unit тестирования
IaC Testing: Integration Tests
На следующей ступени пирамиды тестирования инфраструктуры появлются интеграционные тесты. Они похожи на Unit тесты:
Грубо говоря, мы не проверяем работоспособность отдельного элемента системы как в unit тестах, мы проверяем как сервер сконфигурирован в целом.
IaC Testing: End to End Tests
На вершине пирамиды нас встречают End to End тесты. Т.е. мы не проверяем работоспособность отдельного сервера, отдельного скрипта, отдельного кирпичика нашей инфраструктуры. Мы проверяем что множество серверов, объединенных воедино, наша инфраструктура работает, как мы этого ожидаем. К сожалению готовых коробочных решений, мне не доводилось видеть, наверно т.к. инфраструктура зачастую уникальная и ее сложно шаблонизировать и сделать фрэймворк для ее тестирования. Как итог все создают свои собственные решению. Спрос есть, а вот ответа нет. Поэтому, расскажу что есть, чтобы натолкнуть других на здравые мысли или ткнуть меня носом, что всё давно изобретено до нас.
Проект с богатой историей. Используется в больших организациях и вероятно каждый из вас косвенно пересекался. Приложение поддерживает множество баз данных, интеграций итд итп. Знание о том, как инфраструктура может выглядеть это множество docker-compose файлов, а знание того, какие тесты в каком окружение запускать — это jenkins.
Эта схема достаточно долго работала, пока в рамках исследования мы не попробовали это перенести в Openshift. Контейнеры остались теже, а вот среда запуска сменилась (привет D.R.Y. опять).
Мысль исследования пошла дальше, и в openshift нашлась такая штука APB (Ansible Playbook Bundle), которая позволяет в контейнер запаковать знание как разворачивать инфраструктуру. Т.е. есть воспроизводимая, тестируемая точка знания, как развернуть инфраструктуру.
Всё это звучало хорошо, пока не уткнулись в гетерогенную инфраструктуру: нам для тестов нужна Windows. В итоге знание о том что, где как развернуть, и протестировать сидит в jenkins.
Conclusion
Infrastructure as Code это