В предыдущей статье мы рассмотрели удобную структуру директорий для Ansible.
Оставался один вопрос – причем тут Configuration Management Database? Ну, раз уж мы говорим про IaC, то именно CMDB будет тем самым носителем знания, «что есть инфраструктура».
Религия Ansible утверждает, что наборы настроек компонуются в роли, которые, в свою очередь, назначаются соответствующим хостам. В результате у нас должны получиться очень лаконичные playbook, только с ролями.
Вот, только, сразу возникают проблемы с их читаемостью. Действительно, угадать что именно сделает роль «nftables» не заглядывая в нее совершенно невозможно, а вот получить «выстрел в ногу» в виде наглухо заблокированного ssh порта можно запросто. Ну и самое страшное - далеко не все DevOps (даже в одной команде) «умеют в Ansible». Поэтому, если каким-то чудом он найдет эту самую роль, будет ситуация из известного фильма - «как он может своей головой думать, если он эти куклы первый раз видит».
Опять же, для разных приложений бывает необходимо подкладывать различные файлы в самые неожиданные места сервера. А вот редактировать их копаясь в бесконечных путях ролей занятие явно не для девелопера. Но ведь именно он, а не DevOps совершенно точно знает, что именно нужно положить или изменить.
Решением является директория «cmdb», в которой централизовано хранятся файлы конфигурации соответствующих групп или хостов. Как раз их наименования и будут первым уровнем вложенности. И они должны совпадать с аналогичными наименованиями в inventory. Тогда, согласно идеологии CMDB, это будут конфигурационные единицы (configuration item, CI — не путать с Continuous Integration).
Вторым уровнем (внутри CI), размещаются директории с шаблонами конфигурационных файлов приложений. Plays используют эти файлы для генерации и загрузки на хосты.
По традиции немного магии. Часто бывает ситуация, когда один-два специфичных файла нужно положить по определенному пути файловой системы (при этом они не относятся к общесистемным). Для этого внутри CI создается директория «rootfs» (велосипед за нас изобрели разработчики LXC). А соответствующая роль просто проецирует ее содержимое на корень целевого хоста. Например, для групп «webserver» и «postgres» нужны drop-ins в «/etc/nftables.d/», которые открывают соответствующие порты.
И, конечно, очередная просушка (DRY). На первом уровне размещаются директории, наименования которых начинаются с префикса «common-». В них выносятся файлы, которые явно повторяются для нескольких CI. Применять их можно двумя способами: в директориях хостов на них делаются symlink, или их непосредственно подбирают соответствующие playbook.
Возможности
Вся конфигурация инфраструктуры в виде папки «cmdb» у нас помещается в репозиторий.
- В любой момент можно совершенно точно сказать, кто, когда и какие изменения вносил.
- Если что-то сломалось всегда можно откатиться к пердыдущему состоянию.
- Девелоперы могут самостоятельно вносить изменения в конфигурацию приложений.
- Тестировщики могут получить stage, максимально приближенный к production.
- DevOps могут самостоятельно размножать приложения, не изучая их внутреннее устройство.
- DevSecOps получают дополнительные точки контроля безопасности на уровне инфраструктуры.
Следуя лучшим практикам, можно внедрить и максимально автоматизировать процесс управления изменениями.
Особенности реализации
По умолчанию Ansible ищет роли ниже относительно playbook. Так почему же я настаиваю, что они должны быть выше, и к ним придется указывать относительный путь с «..»? Рассмотрим пример. У нас в «~/playbooks/» есть парочка playbook, которые используют файл из CMDB, допустим «../cmdb/common-nftables/nftables.conf». И они просто разворачивают Nftables на разных сущностях в одинаковой конфигурации. Тогда, следуя идеологии DRY, мы выносим повторяющийся код в процедуру «~/roles/common-nftables.yml» и делаем в наших playbook:
Когда из нее мы будем обращаться к этому файлу, его относительный путь будет «../cmdb/common-nftables/nftables.conf»! То есть – точно таким же! Несмотря на то, что в момент запуска «ansible-playbook» все относительные пути считаются от playbook. Такая структура директорий позволяет безболезненно переносить код между процедурой и playbook!
Если же мы говорим про полноценную роль, то в соответствии с нашей концепцией она должна быть самодостаточна. Действительно, у нее есть собственная директория для используемых файлов и шаблонов, поэтому нечего ей делать в нашем CMDB.
Все или ничего!
При таком централизованном подходе кажется очевидным сделать единственный playbook, под названием «deploy-my-infrastructure.yml». Но если хостов много, проигрывание займет непозволительно много времени. А при возникновении ошибки затраченное время становится чистыми расходами.
Для ускорения развертывания инфраструктуры удобнее оперировать playbook масштаба приложения. Фактически, такие playbook естественным путем становятся компонентом автоматизации deploy и могут самостоятельно применяться в процессах разработки и тестирования. И появляется дополнительная точка контроля, в процессе review, которой могут одновременно воспользоваться все команды (от разработки до эксплуатации).
Однако и «deploy-my-infrastructure.yml» тоже очень нужен. Состоять он должен только из «import_playbook», а запускаться автоматически, по расписанию и только в «check_mode». Если кто-то или что-то внесет изменения напрямую в production, минуя CMDB, мы об этом сразу узнаем. Равно как и об отсутствии или недоступности отдельных хостов. Поэтому сразу же выделяем ему почетное место в составе систем мониторинга.
Так где же CMDB?
Конечно, само по себе понятие CMDB гораздо шире, чем просто набор файлов и переменных. И в первую очередь оно включает в себя реестр конфигурационных единиц. В Ansible за это у нас отвечает inventory.
Пока вы только внедряете процесс управления изменениями, его вполне можно вести вручную. Опять же, факт фиксации в репозитории нового inventory наглядно демонстрирует момент, когда у нас добавлялись или удалялись конкретные хосты/группы/приложения.
В дальнейшем, необходимо рассматривать способы автоматизации данного процесса. Например, если вы используете IPAM, имеет смысл интегрироваться с ним. Так, тот же NetBox обладает встроенным механизмом генерации отчетов и конфигов, который с успехом можно применять для формирования файлов inventory. Но это тема для отдельной статьи.