7.04. Инфраструктура как код (IaC)
Инфраструктура как код (IaC)
Инфраструктура как код — это подход к управлению и автоматизации вычислительных ресурсов с помощью машинно-читаемых файлов конфигурации, а не через ручные процессы или интерактивные инструменты. Этот метод позволяет описывать серверы, сети, хранилища, базы данных и другие компоненты ИТ-инфраструктуры в виде текстовых файлов, которые можно версионировать, тестировать, повторно использовать и применять в различных средах. IaC превращает инфраструктуру в программный артефакт, подчиняющийся тем же принципам разработки, что и прикладное программное обеспечение.
Подход IaC возник в ответ на рост сложности современных систем, где десятки, сотни или даже тысячи компонентов должны быть согласованы между собой, быстро развёрнуты, масштабированы и заменены при необходимости. Ручное управление такой инфраструктурой становится непрактичным, подверженным ошибкам и несовместимым с высокими темпами разработки, характерными для DevOps и Agile-практик.
Основные принципы IaC
Инфраструктура как код опирается на несколько ключевых принципов, которые формируют её философию и практическую ценность.
Декларативность или императивность.
В IaC существует два основных стиля описания инфраструктуры: декларативный и императивный. Декларативный подход указывает желаемое конечное состояние системы — например, «должны существовать три виртуальные машины с Ubuntu 22.04 и 4 ГБ оперативной памяти». Система сама определяет, какие действия выполнить для достижения этого состояния. Императивный подход задаёт последовательность шагов — например, «создать виртуальную машину, установить ОС, настроить сеть, запустить службу». Оба подхода имеют свои области применения, но декларативный стиль получил большее распространение благодаря своей идемпотентности и устойчивости к изменениям.
Идемпотентность.
Идемпотентность означает, что многократное применение одного и того же описания инфраструктуры приводит к одному и тому же результату без побочных эффектов. Это свойство гарантирует, что повторный запуск процесса развёртывания не создаст дубликатов, не нарушит конфигурацию и не вызовет непредсказуемых изменений. Идемпотентность достигается за счёт того, что инструменты IaC сравнивают текущее состояние инфраструктуры с целевым и применяют только необходимые изменения.
Версионирование.
Файлы конфигурации IaC хранятся в системах контроля версий, таких как Git. Это позволяет отслеживать историю изменений, возвращаться к предыдущим состояниям, проводить код-ревью и обеспечивать полную прозрачность всех модификаций. Версионирование делает инфраструктуру воспроизводимой и аудируемой, что особенно важно в регулируемых отраслях.
Повторяемость и воспроизводимость.
Одна и та же конфигурация может быть применена в разных окружениях — разработки, тестирования, предпродакшена и продакшена — с минимальными различиями. Это устраняет проблему «работает у меня», когда система функционирует на локальной машине разработчика, но ломается в других средах. Повторяемость достигается за счёт унификации описаний и исключения ручных вмешательств.
Автоматизация.
Все операции по созданию, изменению и удалению ресурсов выполняются автоматически. Это снижает нагрузку на инженеров, ускоряет процессы и минимизирует человеческие ошибки. Автоматизация интегрируется в CI/CD-конвейеры, позволяя развёртывать не только приложения, но и всю поддерживающую их инфраструктуру в рамках единого процесса доставки.
Преимущества IaC
Применение инфраструктуры как код даёт значительные преимущества на всех этапах жизненного цикла программного обеспечения.
Скорость и масштабируемость.
Развёртывание новой среды занимает минуты или даже секунды вместо часов или дней. Это особенно важно при масштабировании под нагрузкой, запуске временных сред для тестирования или быстром восстановлении после сбоев. Масштабирование становится предсказуемым и контролируемым процессом.
Согласованность.
Все экземпляры инфраструктуры создаются на основе одного и того же описания. Это исключает расхождения между средами и обеспечивает единообразие конфигураций. Согласованность упрощает диагностику проблем и повышает надёжность системы в целом.
Безопасность и соответствие требованиям.
Конфигурации IaC могут включать правила безопасности, такие как настройки брандмауэров, политики доступа, шифрование данных и управление секретами. Эти правила становятся частью кодовой базы и проходят те же процедуры проверки, что и бизнес-логика. Это упрощает соблюдение стандартов, таких как GDPR, HIPAA или PCI DSS.
Сотрудничество и документирование.
Файлы IaC служат живой документацией инфраструктуры. Любой член команды может изучить текущее состояние системы, понять её устройство и внести изменения через прозрачный процесс. Это способствует коллективной ответственности и снижает зависимость от отдельных специалистов.
Экономическая эффективность.
Автоматизированное управление ресурсами позволяет точно подстраивать инфраструктуру под текущие потребности. Временные среды могут автоматически удаляться после завершения задачи, а масштабирование — происходить только при реальной нагрузке. Это снижает затраты на облачные услуги и оптимизирует использование вычислительных мощностей.
Ключевые концепции и терминология
Для глубокого понимания IaC необходимо освоить ряд фундаментальных понятий, которые формируют её концептуальный каркас.
Состояние (State).
Состояние — это зафиксированное описание текущей конфигурации управляемых ресурсов. Инструменты IaC хранят состояние в специальных файлах или удалённых хранилищах, чтобы сравнивать его с целевым описанием и определять, какие изменения нужно применить. Состояние позволяет отслеживать жизненный цикл ресурсов, управлять зависимостями и обеспечивать согласованность между реальной инфраструктурой и её описанием.
Провижининг (Provisioning).
Провижининг — это процесс создания и настройки вычислительных ресурсов. В контексте IaC провижининг выполняется автоматически на основе описаний, а не через ручные действия в веб-интерфейсе облачного провайдера или командной строке. Это включает создание виртуальных машин, сетевых интерфейсов, дисков, балансировщиков нагрузки и других компонентов.
Оркестрация (Orchestration).
Оркестрация — это координация множества ресурсов и сервисов для достижения целостного рабочего состояния системы. В отличие от простого провижининга, оркестрация учитывает зависимости, порядок запуска, проверку готовности и взаимодействие между компонентами. IaC-инструменты часто включают встроенные механизмы оркестрации, позволяя описывать сложные топологии инфраструктуры в едином файле.
Дрейф конфигурации (Configuration Drift).
Дрейф конфигурации возникает, когда реальное состояние инфраструктуры начинает отличаться от описанного в коде. Это может происходить из-за ручных изменений, обновлений, сбоев или внешних вмешательств. IaC помогает выявлять и устранять дрейф, периодически сверяя текущее состояние с целевым и применяя корректирующие действия.
Модульность и повторное использование.
Современные IaC-системы поддерживают модульную архитектуру, позволяя выделять общие шаблоны инфраструктуры в отдельные компоненты. Например, можно создать модуль для развёртывания базы данных, который затем используется в разных проектах с разными параметрами. Модульность повышает читаемость, упрощает поддержку и ускоряет разработку новых сред.
Параметризация и переменные.
Конфигурации IaC часто содержат параметры, которые могут меняться в зависимости от окружения, региона или бизнес-требований. Переменные позволяют использовать один и тот же шаблон для продакшена и тестовой среды, просто подставляя разные значения. Параметризация делает код гибким и адаптируемым без дублирования логики.
Основные инструменты IaC
Рынок предлагает множество инструментов для реализации подхода IaC. Каждый из них имеет свои особенности, экосистему и области применения.
Terraform
Terraform — один из самых популярных инструментов IaC с открытым исходным кодом, разработанный компанией HashiCorp. Он использует декларативный язык HCL (HashiCorp Configuration Language) и поддерживает сотни провайдеров, включая AWS, Azure, Google Cloud, VMware, Kubernetes и другие. Terraform строит граф зависимостей между ресурсами и применяет изменения в безопасном, идемпотентном порядке. Его архитектура основана на концепции состояния, которое может храниться локально или в удалённом бэкенде.
AWS CloudFormation
CloudFormation — нативный инструмент IaC от Amazon Web Services. Он позволяет описывать инфраструктуру AWS с помощью JSON или YAML-шаблонов. CloudFormation полностью интегрирован с экосистемой AWS, поддерживает стеки, вложенные шаблоны и автоматическое откатывание при ошибках. Этот инструмент особенно удобен для проектов, полностью размещённых в облаке AWS.
Azure Resource Manager (ARM) и Bicep
В экосистеме Microsoft Azure основным механизмом IaC служит Azure Resource Manager. Изначально ARM использовал JSON-шаблоны, но позже появился язык Bicep — более читаемый и удобный синтаксис, который компилируется в ARM-шаблоны. Bicep поддерживает модули, параметры, циклы и другие конструкции, упрощающие управление сложной инфраструктурой.
Google Cloud Deployment Manager
Deployment Manager — это инструмент IaC от Google Cloud Platform. Он использует YAML-конфигурации и Python-шаблоны для описания ресурсов GCP. Хотя он менее популярен, чем Terraform, он остаётся предпочтительным выбором для организаций, стремящихся к максимальной интеграции с экосистемой Google.
Pulumi
Pulumi представляет собой современный подход к IaC, позволяющий писать конфигурации на знакомых языках программирования: TypeScript, Python, Go, C# и других. Вместо специализированных DSL (Domain-Specific Languages) Pulumi использует полноценные языки, что даёт доступ к их выразительности, типизации и инструментам разработки. Pulumi управляет состоянием аналогично Terraform, но с более гибкой моделью программирования.
Ansible, Chef, Puppet
Хотя эти инструменты изначально создавались для управления конфигурацией операционных систем и приложений, они также могут использоваться в рамках IaC. Ansible, например, описывает последовательности задач в YAML-файлах и применяет их к целевым хостам. Эти инструменты чаще применяются на этапе пост-провижининга — после создания ресурсов, для настройки программного обеспечения, пользователей, служб и политик.
Жизненный цикл IaC-проекта
Успешное применение IaC требует соблюдения чёткого жизненного цикла, который охватывает все этапы — от проектирования до удаления ресурсов. Этот цикл интегрируется в общие практики DevOps и обеспечивает управляемость, предсказуемость и безопасность.
Проектирование.
На этапе проектирования определяются требования к инфраструктуре: типы ресурсов, их количество, топология сети, политики безопасности, зоны доступности, стратегии резервного копирования и восстановления. Архитекторы и инженеры совместно разрабатывают схему, которая затем переводится в машинно-читаемые описания. Проектирование учитывает не только текущие потребности, но и потенциальный рост, отказоустойчивость и соответствие нормативным требованиям.
Разработка конфигураций.
Конфигурации пишутся в виде текстовых файлов с использованием выбранного инструмента и языка. Разработка ведётся в локальной среде или в изолированном пространстве, часто с применением контейнеров или виртуальных машин для тестирования. На этом этапе активно используются переменные, модули, функции и другие конструкции, повышающие читаемость и поддерживаемость кода.
Верификация и тестирование.
Перед применением конфигурации проходят проверку на синтаксис, структуру и соответствие политикам. Существуют специализированные инструменты, такие как tflint для Terraform или checkov для анализа безопасности. Тестирование может включать запуск «сухого прогона» (plan), который показывает, какие изменения будут внесены без их фактического применения. Более продвинутые практики включают интеграционное тестирование в изолированных средах с последующей автоматической очисткой.
Ревью и утверждение.
Как и исходный код приложений, IaC-конфигурации проходят процесс код-ревью через pull request или merge request. Коллеги проверяют корректность, безопасность, соответствие стандартам и потенциальные риски. Утверждение изменений часто требует согласия нескольких участников, особенно при работе с продакшен-инфраструктурой.
Применение (apply).
После утверждения конфигурация применяется к целевой среде. Инструмент IaC сравнивает текущее состояние с желаемым, строит план действий и выполняет необходимые операции: создание, изменение или удаление ресурсов. Процесс сопровождается логированием, уведомлениями и возможностью отката в случае ошибок.
Мониторинг и аудит.
После развёртывания инфраструктура находится под постоянным наблюдением. Системы мониторинга отслеживают производительность, доступность и соответствие ожидаемому состоянию. Любые отклонения могут сигнализировать о дрейфе конфигурации или внешнем вмешательстве. Аудит ведётся через журналы изменений в системе контроля версий и через логи самого IaC-инструмента.
Обновление и эволюция.
Инфраструктура постоянно развивается вместе с бизнес-требованиями. Новые версии конфигураций вносятся через те же процессы: разработка, тестирование, ревью, применение. Эволюция может включать масштабирование, миграцию между регионами, обновление ОС или замену компонентов.
Удаление и очистка.
Когда ресурсы больше не нужны, они удаляются через тот же IaC-инструмент. Это гарантирует полную очистку без «забытых» компонентов, которые продолжают генерировать расходы. Удаление может быть частью автоматического процесса, например, после завершения тестового цикла или окончания срока действия временной среды.
Практические рекомендации по внедрению IaC
Эффективное использование IaC требует соблюдения ряда практических принципов, выработанных сообществом за годы применения.
Храните всё в системе контроля версий.
Все файлы конфигурации, модули, переменные и скрипты должны находиться в Git-репозитории. Это обеспечивает историю изменений, возможность отката и коллективную работу.
Разделяйте окружения.
Используйте отдельные директории, ветки или пространства имён для разных окружений: dev, staging, prod. Это предотвращает случайное применение тестовых конфигураций к продакшену.
Избегайте хардкода.
Никакие значения — ни имена ресурсов, ни пароли, ни IP-адреса — не должны быть жёстко прописаны в коде. Всё должно передаваться через переменные, параметры или внешние секреты.
Управляйте секретами отдельно.
Пароли, ключи API, сертификаты и другие чувствительные данные хранятся в специализированных хранилищах: HashiCorp Vault, AWS Secrets Manager, Azure Key Vault. IaC-конфигурации ссылаются на эти секреты, но никогда не содержат их напрямую.
Используйте модули для повторного использования.
Стандартные паттерны — например, VPC, кластер Kubernetes, база данных — выделяются в модули. Это ускоряет разработку и гарантирует единообразие.
Автоматизируйте применение через CI/CD.
Интегрируйте IaC в конвейер непрерывной интеграции и доставки. Изменения применяются автоматически после прохождения всех проверок, без ручного вмешательства.
Документируйте архитектуру.
Наряду с кодом ведите документацию: диаграммы архитектуры, описание зависимостей, инструкции по развёртыванию. Это помогает новым участникам команды быстрее вникнуть в систему.
Безопасность в IaC
Безопасность — неотъемлемая часть жизненного цикла инфраструктуры как код. Поскольку IaC-конфигурации определяют не только структуру, но и политики доступа, сетевые правила и настройки шифрования, ошибки в них могут привести к уязвимостям, утечкам данных или несанкционированному доступу. Поэтому безопасность интегрируется на всех этапах работы с IaC.
Сканирование конфигураций на уязвимости.
Специализированные инструменты, такие как Checkov, tfsec, cfn-nag или Snyk Infrastructure as Code, анализируют файлы конфигурации на наличие известных антипаттернов безопасности: открытые порты, отсутствие шифрования, избыточные права доступа, публичные бакеты хранения. Эти проверки запускаются автоматически в CI/CD-конвейере и блокируют применение небезопасных изменений.
Принцип минимальных привилегий.
Каждый ресурс и каждая служба получают только те права, которые необходимы для выполнения их функций. Например, виртуальная машина, обрабатывающая изображения, не имеет доступа к базе данных пользователей. В IaC это достигается через точную настройку ролей, политик IAM и сетевых ACL.
Управление секретами.
Никакие чувствительные данные не хранятся в файлах конфигурации. Вместо этого используются ссылки на внешние системы управления секретами. Инструменты IaC поддерживают интеграцию с такими системами: Terraform может читать секреты из Vault или AWS Secrets Manager, Pulumi — из Azure Key Vault или HashiCorp Vault. Это исключает попадание паролей и ключей в историю Git.
Изоляция сред.
Разные окружения — разработка, тестирование, продакшен — размещаются в отдельных сетях, аккаунтах или проектах. Это предотвращает случайное влияние одной среды на другую и ограничивает потенциальный радиус действия инцидента.
Аудит и соответствие.
Все изменения инфраструктуры фиксируются в системе контроля версий. Каждое изменение имеет автора, комментарий и временну́ю метку. Это позволяет проводить аудит в соответствии с требованиями регуляторов. Кроме того, многие IaC-инструменты поддерживают экспорт состояния в формате, пригодном для анализа внешними системами соответствия.
Политики как код (Policy as Code).
Некоторые платформы, такие как HashiCorp Sentinel или Open Policy Agent (OPA), позволяют описывать правила безопасности и соответствия в виде кода. Эти правила автоматически применяются ко всем IaC-конфигурациям и блокируют нарушения до их применения. Например, можно запретить создание виртуальных машин без шифрования дисков или требовать тегирования всех ресурсов.
IaC и облачные провайдеры
Инфраструктура как код особенно эффективна в облачных средах, где ресурсы являются эфемерными, программно управляемыми и доступными через API. Каждый крупный облачный провайдер предлагает собственные инструменты IaC, но также поддерживает сторонние решения.
Мультиоблачность и гибридность.
Terraform и Pulumi позволяют управлять ресурсами сразу в нескольких облаках — AWS, Azure, Google Cloud, Oracle Cloud и других. Это даёт организациям гибкость в выборе провайдера, снижает зависимость от одного вендора и упрощает миграцию. Гибридные сценарии, сочетающие локальные дата-центры и облака, также поддерживаются через специальные провайдеры.
Нативные инструменты.
AWS CloudFormation, Azure Bicep и Google Deployment Manager обеспечивают максимальную глубину интеграции с родными сервисами. Они получают обновления одновременно с новыми возможностями облака и гарантируют поддержку всех функций. Однако они ограничены экосистемой одного провайдера.
Абстракция и переносимость.
Сторонние инструменты, такие как Terraform, создают уровень абстракции над API облачных провайдеров. Это упрощает обучение и стандартизацию внутри команды, но может отставать в поддержке самых новых функций. Выбор между нативным и абстрактным подходом зависит от стратегии организации: глубокая интеграция с одним облаком или гибкость между несколькими.
IaC и культура DevOps
Инфраструктура как код — не просто технический инструмент, а элемент культурной трансформации. Она способствует стиранию границ между разработкой и эксплуатацией, делая инфраструктуру ответственностью всей команды.
Общая ответственность.
Разработчики участвуют в проектировании и поддержке инфраструктуры, поскольку она становится частью их кодовой базы. Это повышает осведомлённость о производственных реалиях и ускоряет решение проблем.
Быстрая обратная связь.
Ошибки в конфигурации выявляются на ранних этапах — ещё до развёртывания. Это сокращает время на исправление и снижает риски для пользователей.
Эксперименты и инновации.
Создание новой среды занимает минуты, что поощряет эксперименты. Команды могут быстро пробовать новые архитектуры, технологии и подходы, не опасаясь высоких затрат или сложности отката.
Стандартизация и масштабирование культуры.
Когда инфраструктура описана в коде, её легко клонировать, модифицировать и распространять по всей организации. Это позволяет масштабировать успешные практики и поддерживать единые стандарты даже в крупных компаниях с десятками команд.
Примеры IaC-конфигураций
Ниже приведены реалистичные, но упрощённые фрагменты кода, демонстрирующие синтаксис и логику основных IaC-инструментов. Все примеры соответствуют лучшим практикам: используют переменные, избегают хардкода и демонстрируют декларативный подход.
Terraform (HCL)
Создание виртуальной машины в AWS с привязкой к VPC и группе безопасности:
# variables.tf
variable "instance_type" {
description = "Тип экземпляра EC2"
type = string
default = "t3.micro"
}
variable "ami_id" {
description = "AMI ID для Ubuntu 22.04 в регионе us-east-1"
type = string
default = "ami-0abcdef1234567890"
}
# main.tf
provider "aws" {
region = "us-east-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
}
resource "aws_subnet" "public" {
vpc_id = aws_vpc.main.id
cidr_block = "10.0.1.0/24"
map_public_ip_on_launch = true
}
resource "aws_security_group" "web" {
name = "web-sg"
description = "Разрешить HTTP и SSH"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
resource "aws_instance" "web_server" {
ami = var.ami_id
instance_type = var.instance_type
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.web.id]
tags = {
Name = "WebServer"
}
}
Этот пример показывает, как описываются зависимости между ресурсами: подсеть ссылается на VPC, экземпляр — на подсеть и группу безопасности. Terraform автоматически определит порядок создания.
AWS CloudFormation (YAML)
Создание S3-бакета с политикой запрета публичного доступа:
AWSTemplateFormatVersion: '2010-09-09'
Description: Безопасный S3 бакет для хранения логов
Parameters:
BucketName:
Type: String
Description: Имя бакета
Resources:
SecureBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref BucketName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
VersioningConfiguration:
Status: Enabled
Outputs:
BucketArn:
Description: ARN созданного бакета
Value: !GetAtt SecureBucket.Arn
CloudFormation гарантирует, что бакет будет создан с включённой блокировкой публичного доступа, что соответствует рекомендациям безопасности AWS.
Azure Bicep
Развёртывание управляемого PostgreSQL в Azure:
param location string = resourceGroup().location
param serverName string
param administratorLogin string
param administratorLoginPassword securestring
resource postgresServer 'Microsoft.DBforPostgreSQL/flexibleServers@2022-12-01' = {
name: serverName
location: location
sku: {
name: 'Standard_B1ms'
tier: 'Burstable'
}
properties: {
version: '15'
administratorLogin: administratorLogin
administratorLoginPassword: administratorLoginPassword
storage: {
storageSizeGB: 32
}
network: {
publicNetworkAccess: 'Disabled'
delegatedSubnetResourceId: resourceId('Microsoft.Network/virtualNetworks/subnets', 'vnet-main', 'subnet-db')
}
}
}
output serverFqdn string = postgresServer.properties.fullyQualifiedDomainName
Обратите внимание на использование securestring для пароля — это предотвращает его отображение в логах развёртывания.
Pulumi (TypeScript)
Создание Kubernetes-кластера в Google Cloud и развёртывание приложения:
import * as gcp from "@pulumi/gcp";
import * as k8s from "@pulumi/kubernetes";
const cluster = new gcp.container.Cluster("app-cluster", {
initialNodeCount: 2,
nodeVersion: "1.28",
minMasterVersion: "1.28",
nodeConfig: {
machineType: "e2-medium",
oauthScopes: [
"https://www.googleapis.com/auth/cloud-platform"
],
},
});
const kubeconfig = gcp.container.getClusterKubeconfig({
name: cluster.name,
location: cluster.location,
});
const provider = new k8s.Provider("k8s-provider", {
kubeconfig: kubeconfig.kubeconfig,
});
const appLabels = { app: "nginx" };
const deployment = new k8s.apps.v1.Deployment("nginx-deployment", {
spec: {
selector: { matchLabels: appLabels },
replicas: 3,
template: {
metadata: { labels: appLabels },
spec: {
containers: [{
name: "nginx",
image: "nginx:1.25",
ports: [{ containerPort: 80 }],
}],
},
},
},
}, { provider: provider });
export const clusterName = cluster.name;
Pulumi позволяет использовать полноценный язык программирования, что даёт доступ к циклам, условиям, типизации и IDE-поддержке.
Ansible (YAML)
Настройка Nginx на уже существующем сервере:
---
- name: Установка и настройка Nginx
hosts: webservers
become: yes
vars:
nginx_port: 8080
tasks:
- name: Установить Nginx
apt:
name: nginx
state: present
update_cache: yes
- name: Скопировать конфигурационный файл
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
notify: Перезапустить Nginx
- name: Убедиться, что Nginx запущен и включён в автозагрузку
systemd:
name: nginx
state: started
enabled: yes
handlers:
- name: Перезапустить Nginx
systemd:
name: nginx
state: restarted
Ansible здесь используется не для провижининга, а для конфигурации ПО — это типичный сценарий пост-провижининга.