Инфраструктура как код — это подход, который используется для автоматизации настройки инфраструктуры. Каких-то унифицированных и единственно верных решений нет, но есть различные инструменты, которые помогают данный подход использовать.
Обычно он представляет собой git-репозиторий, который описан по правилам и стандартам выбранного инструмента.
В чем же плюсы использования Infrastructure as Code? Постараюсь показать на простом примере.
Задача:
Поднять обратный прокси сервер (Reverse Proxy Server) nginx, который будет заниматься перенаправлением входящего внешнего трафика на внутренние сервисы.
Используется система виртуализации VMware, Proxmox или облачные виртуальные машины — разница не критичная.
Действия инженера по шагам:
Создать виртуальную машину (выделить ресурсы: CPU, RAM, disk, network)
Установить ОС
Настроить удаленное подключение
Обновить пакеты
Установить и настроить конфигурацию Nginx
Установить и настроить средства диагностики, мониторинга
Запустить сервис
Все отлично, не сложно и, главное, работает без проблем. Через год решили, что этот сервер выглядит как точка отказа, и если с ним что то случится, все остальное работать не будет. Попросили уже другого сотрудника поднять и настроить точно такой же сервер в качестве резервного и настроить балансировку.
Действия инженера по шагам:
Зайти на первый сервер (собрать информацию о ресурсах, ПО, конфигурации)
Создать идентичную виртуальную машину (выделить ресурсы: CPU, RAM, disk, network)
Установить ОС
Настроить удаленное подключение
Обновить пакеты
Установить и настроить конфигурацию nginx
Установить и настроить средства диагностики, мониторинга
Запустить сервис
В процессе установки решили, что как отдельную службу держать не очень удобно и попробовали запускать Nginx в Docker (проще обновлять и обслуживать).
В итоге, через определенное время имеем два разных сервера для одной задачи, с разными версиями пакетов и разным способом запуска сервиса, а когда необходимо будет поднять третий такой же сервер, желательно посмотреть конфигурацию первого сервера, сравнить с конфигурацией второго сервера, выбрать, какой вариант актуальнее. И заново проделать те же самые действия повторно. Затем, возможно, мы решим сменить облачного провайдера — все действия придется повторить по новой. Пример сильно упрощен, но основную проблему он иллюстрирует.
Что можно получить, если описать инфраструктуру как код:
Избавление от рутины: не нужно проделывать одни и те же действия на каждом сервере, когда можно автоматизировать этот процесс. Использование IaC позволяет уменьшить затраты на ручной труд и уменьшить вероятность ошибок.
Ускорение: так как все действия выполняются автоматически, а не вручную, то это сильно ускорит процесс.
Наглядность и контроль: необязательно подключаться и изучать существующую инфраструктуру. Данный подход позволяет:
Видеть всю конфигурацию в одном месте.
Контролировать все изменения в инфраструктуре.
Обеспечить прозрачность.
Упростить процесс внесения изменений и управления.
Повторяемость: сколько бы раз ни запускали установку, должны получить один и тот же результат, что позволит избежать человеческих ошибок и ничего не упустить.
Масштабируемость и безопасность: легче расширять инфраструктуру, так как все изменения документированы. В случаи аварий есть возможность отменять или восстанавливать, версионировать. Также сильно облегчит переход на другого облачного провайдера или, наоборот, на свое железо.
Такой подход можно использовать не только для серверов, но и других устройств, которые могут использовать в настройке конфигурационные файлы (например, сетевое оборудование, коммутаторы, маршрутизаторы и т.д.).
Инфраструктура как кот (изображение: нейросеть)
Рассмотрим основные инструменты, используемые для работы с IaC.
Самый универсальный и популярный инструмент.
Благодаря удобным шаблонам Jinja2, подключению по SSH, условиям и циклам получил массовое распространение. Ansible имеет активное сообщество пользователей и разработчиков, которые предоставляют обширную документацию, модули и плагины для различных сценариев использования. Это обеспечивает хорошую поддержку и развитие инструмента.
Инструмент, разработанный компанией Hashicorp, который позволяет управлять виртуальными машинами, сетями, группами безопасности и другими компонентами инфраструктуры с помощью файлов конфигураций. Terraform использует декларативный характер, позволяет привести инфраструктуру к нужному состоянию, указав необходимые параметры системы.
В Terraform также есть функция Plan, которая перед активными действиями сравнивает текущее состояние системы с будущим и покажет пользователю, что именно будет удалено, запущено или изменено в соответствии с новым конфигурационным файлом. Это помогает избежать ошибок при создании, изменении рабочей инфраструктуры.
В основном используется в работе с облачными провайдерами. Для подключения используется сущность, которая так и называется Provider (для взаимодействия с API поставщика). Можно просмотреть полный список на сайте registry.terraform.io.
Хорошо, когда Provider поддерживает сам облачный провайдер, например Timeweb Cloud.
Иногда энтузиастам приходится писать свои Provider-ы; но если у поставщика обновится API, придется самостоятельно поддерживать работоспособность или надеяться на разработчика или сообщество.
Достаточно молодой open-source-инструмент. Позволяет создавать инфраструктурный код, используя языки программирования, их несколько на выбор. На этом языке можно описать инфраструктуру, а также использовать свою любимую IDE с автодополнением, проверкой типов, документацией и т.п.
Можно использовать:
TypeScript
Python
Go
C#
Java
YAML
Еще не получил массовой популярности, но благодаря своим гибким возможностям выглядит как хорошая заявка на победу.
Данные инструменты я выделил в отдельную группу, так как здесь требуется использование заранее установленных агентов на хостах, которые облегчают регулярное приведение машины к состоянию и уменьшают вероятность ошибок.
Выбор инструментов зависит от задач, которые вы хотите решить. Вы можете комбинировать их в зависимости от ситуации, хотя использование большого количества («зоопарка») инструментов может быть неудобным.
Независимо от выбора инструмента, важно четко разделять процессы развертывания и управления конфигурацией. При использовании IaC все операции с конфигурацией сводятся к изменению кода. Если начать вносить изменения в инфраструктуру вручную, ни один инструмент не сможет решить возможные проблемы.
По мере развития времени и расширения кодовой базы в IaC существует риск создания сложной, плохо поддерживаемой системы. Постарайтесь избегать этого.
Инфраструктурные знания не должны быть ограничены одним человеком. Любые изменения конфигураций делаются в коде (git-репозитории), можно также настроить линтеры, чтобы не допустить случайных ошибок. Также желательно: проводить ревью, проводит тесты перед запуском, соблюдать единый code style.
В IaC удобно версионировать и отслеживать каждое изменение в инфраструктуре. Это обеспечивает прозрачность и возможность быстро обнаруживать и устранять любые изменения, которые могут быть причиной технических проблем, аварий или угрожать безопасности
Это динамично развивающееся направление в области управления инфраструктурой. С каждым годом появляются новые инструменты, технологии и стандарты, которые расширяют возможности IaC и делают процесс управления инфраструктурой более гибким и эффективным. Существуют должности IaC-инженеров как отдельной специализации.
В практической части покажу простой пример поднятия сервера в Timeweb Cloud с использованием этих инструментов.
Ссылка на репозиторий Github: https://github.com/akmalovaa/iac-timeweb.
Со временем информация в репозитории может незначительно отличаться от написанной статьи.
Создать сервер мониторинга, который можно быстро настроить и запустить, просто нажав на кнопку и используя самые простые подходы инфраструктуры как кода для автоматизации этого процесса.
В качестве примера буду использовать сервис Gatus.
Дополнительно в нагрузку подниму сервисы Prometheus + Grafana, все сервисы будут в docker compose.
Terraform — создание VPS.
Ansible — установка софта, передача конфигурационных файлов и запуск сервисов.
Установить инструменты:
Можно установить локально или использовать готовый container image, где я уже подготовил и собрал все необходимые компоненты:
docker pull ghcr.io/akmalovaa/iac-tools
На локальной машине можно даже ничего не устанавливать, кроме docker.
Далее в примерах буду использовать именно данный способ.
Скопировать репозиторий к себе:
git clone https://github.com/akmalovaa/iac-timeweb.git
cd iac-timeweb
Войти или зарегистрироваться https://timeweb.cloud/.
В качестве названия проекта используется homelab
. Вам необходимо создать такой же или поменять на свой проект в настройках terraform/main.tf
.
data "twc_projects" "terraform-project" {
name = "homelab"
}
Можно создать новые или использовать уже сгенерированные ранее ключи.
Необходимо добавить свой public_key в панель управления. Мой ключ имеет имя monitoring
.
Используется в terraform/main.tf
:
data "twc_ssh_keys" "ssh-key" {
name = "monitoring"
}
Для Ansible необходимо подставить private_key локально по пути ansible/ssh/id_rsa
.
Создаем токены в панели управления.
Их необходимо использовать в переменных окружения TF_VAR_TWC_TOKEN
или создать файл terraform/env.auto.tfvars
.
TWC_TOKEN = "eyJhbGcsaohjdshoaohgasgashod..."
Основные настройки — в файле terraform/main.tf
.
Пример фиксированной настройки сервера по цене:
data "twc_presets" "main-preset" {
location = "ru-1"
price_filter {
from = 150
to = 200
}
Если не попасть ни в один фильтр, сервер не создастся.
Все доступные варианты удобнее смотреть в интерфейсе Timeweb Cloud при первых шагах создания сервера, в разделе выбора тарифов.
Фильтровать можно не только по стоимости, но и по требуемым ресурсам (CPU, RAM, disk) и гео-расположению
Конфигурационные файлы и docker-compose.yaml
вынес в отдельную директорию services
.
Данную директорию сделал полностью независимой. Есть возможность даже без IaC-автоматизаций вручную скопировать данную директорию и запустить локально или на сервере. Такая структура позволяет легко использовать данный шаблон и для других своих сервисов (все изменения, которые относятся к контейнерам, настраиваются в одном месте)
Для удобства настройки и конфигурирования основные переменные вынесены в отдельный файл: .gitab-variables.yaml
.
Пример .gitab-variables.yaml
:
variables:
# Ansible config file
ANSIBLE_CONFIG: "./ansible/ansible.cfg"
# Common settings
MAIN_DIR: /srv/monitoring
# Services
GATUS_IMAGE_TAG: twinproduction/gatus:v5.7.0
PROMETHEUS_IMAGE_TAG: prom/prometheus:v2.50.1
GRAFANA_IMAGE_TAG: grafana/grafana:10.3.5-ubuntu
Переменные подготовлены для запуска в GitLab CI/CD.
Скрипт variables-to-local.py
создает файл .env
для локального запуска Docker c необходимыми переменными окружения.
python variables-to-local.py
Запуск контейнера в интерактивном режиме:
docker run --rm -it -v .:/srv --env-file .env ghcr.io/akmalovaa/iac-tools bash
Terraform
task terraform:all
Заказ VPS по выбранному тарифу
Добавление публичного SSH ключа
Создание файла ansible/hosts.yaml
с полученным IP-адресом
Ansible
task ansible:play
Подключение по SSH к IP хоста
Копирование конфигурационных данных для Docker
Запуск сервисов docker-compose
Необходимо учитывать, что репозитории Terraform могут быть недоступны из РФ.
Основной вариант запуска предполагается в github action или gitlab ci/cd.
Пример .gitlab-ci.yml
:
include: .gitlab-variables.yaml
image: ghcr.io/akmalovaa/iac-tools
stages:
- linter
- terraform
- ansible
.ansible_prepare: &ansible_prepare
- echo "$ANSIBLE_VAULT" > ansible/vault.key
- echo "$SSH_PRIVATE_KEY" > ansible/ssh/id_rsa
- chmod -R 400 ./ansible/ssh
lint-docker-compose:
stage: linter
image: docker:dind
script:
- docker compose -f ./services/docker-compose.yaml config
create-vps:
stage: terraform
variables:
TF_VAR_TWC_TOKEN: $TWC_TOKEN
script:
- task terraform:all # terraform init && terraform apply -refresh-only -auto-approve && terraform apply -auto-approve
when: manual
deploy:
stage: ansible
variables:
ANSIBLE_CONFIG: "./ansible/ansible.cfg"
script:
- *ansible_prepare
- task ansible:play # ansible-playbook ansible/playbook.yaml
when: manual
Используются переменные (необходимо добавить как секретные переменные в Gitlab - Settings - CI/CD - Variables):
TWC_TOKEN
— API-ключ из личного кабинета timeweb.cloudANSIBLE_VAULT
— для шифровки и дешифровки секретных данныхSSH_PRIVATE_KEY
— для подключения к созданному серверуВ результате выполнения мы должны получить готовый к работе VPS-сервер с выбранным тарифом и запущенными сервисами:
{YOUR_IP}:8080 — Gatus
{YOUR_IP}:9090 — Prometheus
{YOUR_IP}:3000 — Grafana
В данном примере я использовал образ от Timeweb Cloud с уже установленным Docker, но лучше устанавливать весь софт отдельно, у другого облачного провайдера такого готового образа может не оказаться
Добавить примеры github actions
В разделе с docker-compose, лучше использовать модуль community.docker
и команды community.docker.docker_compose_v2
Добавить использование доменного имени и API-управление настройками DNS-провайдера