Давайте дружить в Телеграме: рассказываем про новые фичи, общаемся в комментах, прислушиваемся к вашим идеям Подписаться

Infrastructure as Code (IaC) — Инфраструктура как код: обзор и применение

Артур Акмалов
Артур Акмалов
Инженер по разработке
24 апреля 2024 г.
33
11 минут чтения
Средний рейтинг статьи: 5

Инфраструктура как код — это подход, который используется для автоматизации настройки инфраструктуры. Каких-то унифицированных и единственно верных решений нет, но есть различные инструменты, которые помогают данный подход использовать.

Обычно он представляет собой git-репозиторий, который описан по правилам и стандартам выбранного инструмента.

Зачем использовать Infrastructure as Code?

В чем же плюсы использования Infrastructure as Code? Постараюсь показать на простом примере.

Задача:

Поднять обратный прокси сервер (Reverse Proxy Server) nginx, который будет заниматься перенаправлением входящего внешнего трафика на внутренние сервисы.

Используется система виртуализации VMware, Proxmox или облачные виртуальные машины — разница не критичная.

Действия инженера по шагам:

  • Создать виртуальную машину (выделить ресурсы: CPU, RAM, disk, network)

  • Установить ОС

  • Настроить удаленное подключение

  • Обновить пакеты

  • Установить и настроить конфигурацию Nginx

  • Установить и настроить средства диагностики, мониторинга

  • Запустить сервис

Все отлично, не сложно и, главное, работает без проблем. Через год решили, что этот сервер выглядит как точка отказа, и если с ним что то случится, все остальное работать не будет. Попросили уже другого сотрудника поднять и настроить точно такой же сервер в качестве резервного и настроить балансировку.

Действия инженера по шагам:

  • Зайти на первый сервер (собрать информацию о ресурсах, ПО, конфигурации)

  • Создать идентичную виртуальную машину (выделить ресурсы: CPU, RAM, disk, network)

  • Установить ОС

  • Настроить удаленное подключение

  • Обновить пакеты

  • Установить и настроить конфигурацию nginx

  • Установить и настроить средства диагностики, мониторинга

  • Запустить сервис

В процессе установки решили, что как отдельную службу держать не очень удобно и попробовали запускать Nginx в Docker (проще обновлять и обслуживать).

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

Что можно получить, если описать инфраструктуру как код:

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

  2. Ускорение: так как все действия выполняются автоматически, а не вручную, то это сильно ускорит процесс.

  3. Наглядность и контроль: необязательно подключаться и изучать существующую инфраструктуру. Данный подход позволяет:

    • Видеть всю конфигурацию в одном месте.

    • Контролировать все изменения в инфраструктуре.

    • Обеспечить прозрачность.

    • Упростить процесс внесения изменений и управления.

  4. Повторяемость: сколько бы раз ни запускали установку, должны получить один и тот же результат, что позволит избежать человеческих ошибок и ничего не упустить.

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

Такой подход можно использовать не только для серверов, но и других устройств, которые могут использовать в настройке конфигурационные файлы (например, сетевое оборудование, коммутаторы, маршрутизаторы и т.д.).

Image1

Инфраструктура как кот (изображение: нейросеть)

Инструменты для IaC

Рассмотрим основные инструменты, используемые для работы с IaC.

Ansible

Самый универсальный и популярный инструмент.

Благодаря удобным шаблонам Jinja2, подключению по SSH, условиям и циклам получил массовое распространение. Ansible имеет активное сообщество пользователей и разработчиков, которые предоставляют обширную документацию, модули и плагины для различных сценариев использования. Это обеспечивает хорошую поддержку и развитие инструмента.

Terraform

Инструмент, разработанный компанией Hashicorp, который позволяет управлять виртуальными машинами, сетями, группами безопасности и другими компонентами инфраструктуры с помощью файлов конфигураций. Terraform использует декларативный характер, позволяет привести инфраструктуру к нужному состоянию, указав необходимые параметры системы.

В Terraform также есть функция Plan, которая перед активными действиями сравнивает текущее состояние системы с будущим и покажет пользователю, что именно будет удалено, запущено или изменено в соответствии с новым конфигурационным файлом. Это помогает избежать ошибок при создании, изменении рабочей инфраструктуры.

В основном используется в работе с облачными провайдерами. Для подключения используется сущность, которая так и называется Provider (для взаимодействия с API поставщика). Можно просмотреть полный список на сайте registry.terraform.io.

Хорошо, когда Provider поддерживает сам облачный провайдер, например Timeweb Cloud.

Image2

Иногда энтузиастам приходится писать свои Provider-ы; но если у поставщика обновится API,  придется самостоятельно поддерживать работоспособность или надеяться на разработчика или сообщество.

Pulumi

Достаточно молодой open-source-инструмент. Позволяет создавать инфраструктурный код, используя языки программирования, их несколько на выбор. На этом языке можно описать инфраструктуру, а также  использовать свою любимую IDE с автодополнением, проверкой типов, документацией и т.п.

Можно использовать:

  • TypeScript

  • Python

  • Go

  • C#

  • Java

  • YAML

Еще не получил массовой популярности, но благодаря своим гибким возможностям выглядит как хорошая заявка на победу. 

SaltStack, Puppet, Chef

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

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

Развитие практик IaC

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

По мере развития времени и расширения кодовой базы в IaC существует риск создания сложной, плохо поддерживаемой системы. Постарайтесь избегать этого.

Инфраструктурные знания не должны быть ограничены одним человеком. Любые изменения конфигураций делаются в коде (git-репозитории), можно также настроить линтеры, чтобы не допустить случайных ошибок. Также желательно: проводить ревью, проводит тесты перед запуском, соблюдать единый code style.

В IaC удобно версионировать и отслеживать каждое изменение в инфраструктуре. Это обеспечивает прозрачность и возможность быстро обнаруживать и устранять любые изменения, которые могут быть причиной технических проблем, аварий или угрожать безопасности

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

Практическая часть

В практической части покажу простой пример поднятия сервера в Timeweb Cloud с использованием этих инструментов.

Репозиторий для экспериментов с IaC Timeweb Cloud

Ссылка на репозиторий Github: https://github.com/akmalovaa/iac-timeweb.

Со временем информация в репозитории может незначительно отличаться от написанной статьи.

Цель

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

  • Заказать VPS
  • Установить docker, docker compose
  • Загрузить docker-compose.yaml и файлы конфигураций сервисов
  • Запустить

Сервер для мониторинга

В качестве примера буду использовать сервис 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

Настройка

Учетная запись Timeweb Cloud

Войти или зарегистрироваться https://timeweb.cloud/.

Настройка проекта

В качестве названия проекта используется homelab. Вам необходимо создать такой же или поменять на свой проект в настройках terraform/main.tf.

data "twc_projects" "terraform-project" {
 name = "homelab"
}

SSH key

Можно создать новые или использовать уже сгенерированные ранее ключи.

  • public_key: Добавляется на сервер при его создании Terraform
  • private_key: Используется для подключения и работы Ansible 

Необходимо добавить свой public_key в панель управления. Мой ключ имеет имя monitoring.

Используется в terraform/main.tf:

data "twc_ssh_keys" "ssh-key" {
 name = "monitoring"
}

Для Ansible необходимо подставить private_key локально по пути ansible/ssh/id_rsa.

API keys

Создаем токены в панели управления

Их необходимо использовать в переменных окружения 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.cloud
  • ANSIBLE_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-провайдера

Зарегистрируйтесь и начните пользоваться
сервисами Timeweb Cloud прямо сейчас

15 лет опыта
Сосредоточьтесь на своей работе: об остальном позаботимся мы
165 000 клиентов
Нам доверяют частные лица и компании, от небольших фирм до корпораций
Поддержка 24/7
100+ специалистов поддержки, готовых помочь в чате, тикете и по телефону