Инфраструктура как код и CI/CD: практическое руководство по интеграции Ansible, Terraform и GitLab | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Инфраструктура как код и CI/CD: практическое руководство по интеграции Ansible, Terraform и GitLab

22 мая 2026 11 мин. чтения
Содержание статьи

Современное управление инфраструктурой требует перехода от ручных операций и разрозненных скриптов к целостному, автоматизированному процессу. Связка Terraform, Ansible и GitLab CI/CD создает такой процесс: вы получаете воспроизводимую, документированную и отказоустойчивую среду, где каждое изменение проходит через контролируемый пайплайн. Эта статья дает практическое руководство по их интеграции - от базовых принципов до готовых конфигураций для production.

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

От разрозненных скриптов к единому пайплайну: философия современной инфраструктуры

Эволюция управления инфраструктурой привела к четкому разделению ответственности между инструментами. Terraform декларативно создает облачные ресурсы - «железо». Ansible идемпотентно настраивает серверы - устанавливает «софт» и конфигурирует его. GitLab CI/CD выступает оркестратором, который запускает эти процессы в правильной последовательности, управляет секретами и обеспечивает контроль. Ключ к их интеграции - структурированный обмен данными через форматы вроде JSON и API, что делает весь процесс воспроизводимым и надежным.

Terraform, Ansible, GitLab: кто за что отвечает в цепочке создания ценности

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

Инструмент Основная ответственность Примеры задач Ключевой принцип
Terraform Декларативное создание и управление облачной инфраструктурой. Создание VPC, подсетей, групп безопасности, виртуальных машин, балансировщиков нагрузки, managed баз данных (PostgreSQL, MySQL). Хранение состояния (state) в удаленном backend (S3). Infrastructure as Code. Состояние - источник правды.
Ansible Идемпотентная конфигурация и управление уже существующими серверами. Базовая настройка ОС (обновления, firewall), установка пакетов (Nginx, Python), настройка системных сервисов, деплой кода приложения, управление пользователями. Конфигурационный менеджмент. Идемпотентность.
GitLab CI/CD Оркестрация всего процесса, управление секретами, контроль качества. Триггер выполнения на событие (push, merge request). Последовательный запуск этапов: validate, plan, apply (Terraform), configure (Ansible), test. Хранение секретов в Variables или Vault. Управление артефактами. Автоматизация и контроль. Everything as Code.

Их используют вместе для полного цикла: Terraform создает серверы, а Ansible их настраивает - этот процесс оркестрирует GitLab CI/CD. Отдельно Ansible применяют для рутинных задач вроде патчинга, а Terraform - для управления жизненным циклом любых облачных ресурсов.

Ключевой принцип: инфраструктура как данные (JSON, API, артефакты)

Интеграция инструментов основана на структурированном обмене данными. Output Terraform, например IP-адреса созданных инстансов или endpoint базы данных, по умолчанию возвращается в формате JSON. Эти данные становятся источником правды для последующих шагов.

В пайплайне GitLab CI/CD output Terraform можно сохранить как артефакт (artifact), а затем передать в виде переменных в job с Ansible. Ansible, в свою очередь, может использовать динамический inventory-плагин, который читает этот JSON, чтобы получить актуальный список хостов для настройки. Этот подход аналогичен работе агрегатора API, который стандартизирует вызовы к разным провайдерам - ваш пайплайн становится таким gateway для управления инфраструктурой.

Простой workflow выглядит так: terraform apply → сохранение outputs.json → чтение файла Ansible → динамическое построение inventory → выполнение playbook.

Практический кейс: развертывание отказоустойчивого веб-приложения с нуля

Рассмотрим сквозной сценарий развертывания стека Nginx + Python (Django/Flask) + PostgreSQL в облаке. Цель - получить готовые конфигурации, которые можно адаптировать.

Шаг 1: Декларативное создание инфраструктуры с Terraform (main.tf)

Этот модуль Terraform создает базовые компоненты в Yandex Cloud. Аналогичная логика применима к AWS или Azure.

# main.tf - основные ресурсы
provider "yandex" {
  token     = var.yc_token
  cloud_id  = var.yc_cloud_id
  folder_id = var.yc_folder_id
  zone      = "ru-central1-a"
}

# Создание сети
resource "yandex_vpc_network" "prod_network" {
  name = "prod-network"
}

resource "yandex_vpc_subnet" "prod_subnet_a" {
  name           = "prod-subnet-a"
  zone           = "ru-central1-a"
  network_id     = yandex_vpc_network.prod_network.id
  v4_cidr_blocks = ["192.168.10.0/24"]
}

# Группы безопасности
resource "yandex_vpc_security_group" "prod_sg" {
  name       = "prod-security-group"
  network_id = yandex_vpc_network.prod_network.id

  ingress {
    protocol       = "TCP"
    port           = 80
    v4_cidr_blocks = ["0.0.0.0/0"]
  }
  ingress {
    protocol       = "TCP"
    port           = 22
    v4_cidr_blocks = ["0.0.0.0/0"] # Ограничьте на практике!
  }
}

# Две виртуальные машины в одной зоне для примера
resource "yandex_compute_instance" "web" {
  count = 2
  name  = "web-instance-${count.index}"

  resources {
    cores  = 2
    memory = 2
  }

  boot_disk {
    initialize_params {
      image_id = "fd8vmcue7aajpmeo39kk" # Ubuntu 22.04
    }
  }

  network_interface {
    subnet_id = yandex_vpc_subnet.prod_subnet_a.id
    nat       = true
    security_group_ids = [yandex_vpc_security_group.prod_sg.id]
  }

  metadata = {
    ssh-keys = "ubuntu:${file(var.ssh_public_key)}"
  }
}

# Управляемая база данных PostgreSQL
resource "yandex_mdb_postgresql_cluster" "prod_db" {
  name        = "prod-db-cluster"
  environment = "PRODUCTION"
  network_id  = yandex_vpc_network.prod_network.id

  config {
    version = 15
    resources {
      resource_preset_id = "s2.micro"
      disk_type_id       = "network-ssd"
      disk_size          = 10
    }
  }

  host {
    zone      = "ru-central1-a"
    subnet_id = yandex_vpc_subnet.prod_subnet_a.id
  }
}

# Output для передачи данных
output "web_instances_ips" {
  value = yandex_compute_instance.web[*].network_interface[0].nat_ip_address
  description = "Публичные IP-адреса веб-серверов"
}

output "db_host_fqdn" {
  value = yandex_mdb_postgresql_cluster.prod_db.host[0].fqdn
  description = "FQDN хоста базы данных"
}

Важно: Используйте remote backend (например, S3) для хранения state-файла в команде. Никогда не храните секреты (токены, пароли) прямо в коде. Используйте переменные (var.yc_token), которые передаются через environment variables GitLab CI.

Шаг 2: Конфигурация серверов и деплой приложения с Ansible (site.yml)

Playbook Ansible принимает динамические данные от Terraform. Предполагается, что IP-адреса переданы как переменная web_hosts_ips.

# site.yml - основной playbook
---
- name: Configure web servers and deploy application
  hosts: "{{ web_hosts_ips }}"
  become: yes
  vars:
    app_git_repo: "https://your-git-repo.com/app.git"
    db_host: "{{ db_host_fqdn }}"
    db_password: "{{ vault_db_password }}" # Секрет из ansible-vault или GitLab CI

  tasks:
    - name: Update apt cache and install basic packages
      apt:
        update_cache: yes
        cache_valid_time: 3600
        pkg:
          - nginx
          - python3-pip
          - python3-venv
          - git

    - name: Ensure firewall allows Nginx and SSH
      ufw:
        rule: allow
        port: '{{ item }}'
        proto: tcp
      loop:
        - "80"
        - "22"

    - name: Create application user
      user:
        name: appuser
        system: yes
        create_home: yes
        shell: /bin/bash

    - name: Clone application repository
      git:
        repo: "{{ app_git_repo }}"
        dest: /opt/myapp
        version: main
        force: yes

    - name: Create Python virtual environment and install dependencies
      pip:
        requirements: /opt/myapp/requirements.txt
        virtualenv: /opt/myapp/venv
        virtualenv_python: python3

    - name: Create systemd service for application
      template:
        src: templates/myapp.service.j2
        dest: /etc/systemd/system/myapp.service
        owner: root
        group: root
        mode: '0644'
      notify:
        - restart myapp service

    - name: Configure Nginx as reverse proxy
      template:
        src: templates/nginx-site.conf.j2
        dest: /etc/nginx/sites-available/myapp
        owner: root
        group: root
        mode: '0644'
      notify:
        - reload nginx

    - name: Enable Nginx site
      file:
        src: /etc/nginx/sites-available/myapp
        dest: /etc/nginx/sites-enabled/myapp
        state: link

  handlers:
    - name: restart myapp service
      systemd:
        name: myapp
        state: restarted
        daemon_reload: yes
        enabled: yes

    - name: reload nginx
      systemd:
        name: nginx
        state: reloaded

Playbook использует шаблоны Jinja2 для конфигурационных файлов. Переменные web_hosts_ips и db_host_fqdn передаются из GitLab CI в момент запуска с помощью флага --extra-vars.

Шаг 3: Оркестрация процесса в GitLab CI/CD (.gitlab-ci.yml)

Этот пайплайн связывает все этапы вместе, реализует проверки и управляет состоянием.

# .gitlab-ci.yml
stages:
  - validate
  - plan
  - apply
  - configure
  - test

variables:
  TF_ROOT: ${CI_PROJECT_DIR}/terraform
  ANSIBLE_ROOT: ${CI_PROJECT_DIR}/ansible

# Используем заранее подготовленный образ с инструментами
image: registry.gitlab.com/gitlab-org/terraform-images/releases/terraform:latest

before_script:
  - cd ${TF_ROOT}
  - terraform init -backend=false

validate:
  stage: validate
  script:
    - terraform validate

plan:
  stage: plan
  script:
    - terraform plan -out=tfplan
  artifacts:
    paths:
      - ${TF_ROOT}/tfplan

# Ручное подтверждение для production
apply:
  stage: apply
  script:
    - terraform apply -auto-approve tfplan
    - terraform output -json > ${CI_PROJECT_DIR}/terraform_output.json
  artifacts:
    paths:
      - ${CI_PROJECT_DIR}/terraform_output.json
  when: manual
  only:
    - main

# Job для Ansible использует свой образ
configure_with_ansible:
  stage: configure
  image: python:3.11-slim
  before_script:
    - cd ${ANSIBLE_ROOT}
    - pip install ansible
    - mkdir -p ~/.ssh
    - echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
  script:
    # Извлекаем данные из output Terraform
    - WEB_IPS=$(jq -r '.web_instances_ips.value[]' ${CI_PROJECT_DIR}/terraform_output.json | tr '\n' ',' | sed 's/,$//')
    - DB_HOST=$(jq -r '.db_host_fqdn.value' ${CI_PROJECT_DIR}/terraform_output.json)
    # Запускаем Ansible с передачей переменных
    - ansible-playbook site.yml -i "${WEB_IPS}," --extra-vars "web_hosts_ips=${WEB_IPS} db_host_fqdn=${DB_HOST} vault_db_password=${DB_PASSWORD}"
  dependencies:
    - apply
  only:
    - main

# Простейший smoke-тест
smoke_test:
  stage: test
  image: curlimages/curl:latest
  script:
    - WEB_IPS=$(jq -r '.web_instances_ips.value[0]' ${CI_PROJECT_DIR}/terraform_output.json)
    - curl -f "http://${WEB_IPS}" || exit 1
  dependencies:
    - configure_with_ansible
  only:
    - main

Секреты (YC_TOKEN, SSH_PRIVATE_KEY, DB_PASSWORD) хранятся в GitLab CI/CD Variables с пометками Masked и Protected. Для сложных сценариев можно интегрировать HashiCorp Vault.

Обеспечение отказоустойчивости и соответствия SLA в production

Базового деплоя недостаточно для production-среды. Критически важны стратегии, минимизирующие downtime, и встроенные механизмы observability.

Архитектурные паттерны: Blue-Green и Canary деплой в связке с Terraform

Blue-Green деплой предполагает наличие двух идентичных сред («blue» - текущая, «green» - новая). Terraform может управлять созданием «зеленого» пула ресурсов параллельно «синему». Пример логики в Terraform с использованием count и переменных:

variable "deployment_color" {
  description = "Цвет деплоя: blue или green"
  default     = "blue"
}

resource "yandex_compute_instance" "web" {
  count = var.deployment_color == "blue" ? 2 : 0 # Создаем blue-инстансы
  # ... конфигурация
}

resource "yandex_compute_instance" "web_green" {
  count = var.deployment_color == "green" ? 2 : 0 # Создаем green-инстансы
  # ... конфигурация (другие имена, теги)
}

Пайплайн GitLab CI/CD сначала разворачивает приложение на «зеленых» инстансах (запуская Ansible с соответствующим inventory). После успешного тестирования этап «переключения» обновляет целевой group балансировщика нагрузки или DNS-запись, чтобы направить трафик на новый пул. Старый пул остается на случай быстрого отката. Canary-деплой реализуется через постепенное добавление новых инстансов в целевой группу балансировщика и мониторинг метрик.

Для оркестрации Kubernetes-кластеров эти паттерны реализуются через инструменты вроде ArgoCD или Flagger, но базовый принцип интеграции с CI/CD остается.

Мониторинг, логирование и механизмы самовосстановления

Infrastructure as Code позволяет встроить observability на этапе создания ресурсов. Расширьте конфигурацию Terraform для автоматического создания дашбордов и алертов:

# Добавление в main.tf для Yandex Monitoring
resource "yandex_monitoring_dashboard" "web_app_dashboard" {
  name        = "web-app-overview"
  description = "Дашборд для мониторинга веб-приложения"

  widgets {
    text {
      text = "## Availability and Latency"
    }
  }
  # ... определение графиков и метрик
}

Ansible можно использовать для настройки агентов мониторинга (Prometheus node_exporter) на серверах и создания простых механизмов самовосстановления. Например, handler в playbook может перезапустить сервис при его падении, а cron-job, запускаемый через Ansible, будет проверять доступность endpoint.

Централизованный мониторинг и fallback routing, как в примере с Eden AI, - это стандарт для production. Ваш пайплайн должен включать этап проверки здоровья после деплоя и автоматического отката при неудаче.

Безопасность и управление секретами в пайплайне

Автоматизация увеличивает риски, если секреты скомпрометированы. Критические практики:

  • GitLab CI/CD Variables: Храните токены облаков, пароли БД, SSH-ключи как Protected и Masked переменные. Используйте разные переменные для сред.
  • HashiCorp Vault: Для сложных сценариев интегрируйте Vault. GitLab CI может получать временные секреты через JWT-аутентификацию.
  • Ansible Vault: Шифруйте чувствительные данные в playbook с помощью ansible-vault, а пароль для расшифровки передавайте через переменную GitLab CI.
  • Минимальные привилегии: Настройте IAM-роли в облаке так, чтобы у сервисного аккаунта Terraform были права только на создание необходимых ресурсов. Никогда не используйте токены с правами администратора.
  • Безопасность state-файла: Храните Terraform state в защищенном backend (S3 с шифрованием и блокировкой). Ограничьте доступ к нему.

Эти практики соответствуют принципам DevSecOps и должны быть внедрены с самого начала. Более глубокое погружение в тему безопасности пайплайнов можно найти в нашем руководстве по DevSecOps в 2026 году.

Оптимизация и расширение: GitLab Runner, кэширование и продвинутые сценарии

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

Тонкая настройка GitLab Runner для скорости и стабильности

Долгие пайплайны - частая проблема. Решения:

  • Выбор executor: Docker executor обеспечивает изоляцию и чистоту окружения. Shell executor быстрее, но требует управления зависимостями на хосте.
  • Кэширование: Настройте кэш в .gitlab-ci.yml для Terraform providers, модулей Ansible и зависимостей приложения (Python pip, npm). Это сокращает время загрузки.
cache:
  key: "${CI_COMMIT_REF_SLUG}"
  paths:
    - ${TF_ROOT}/.terraform/
    - ${ANSIBLE_ROOT}/roles/
    - ~/.cache/pip/
  • Параллельное выполнение: Независимые job (например, линтеры для разных частей кода) можно запускать параллельно, указав для них одну стадию.
  • Политика pull_policy для Docker: Используйте pull_policy: if-not-present, чтобы избежать лишней загрузки образов.

Автоматизация за пределами деплоя: патчинг, бэкапы, аудит

IaC и конфигурационный менеджмент полезны не только для деплоя. Примеры пайплайнов для рутинных задач:

  • Еженедельный патчинг: Запланированный пайплайн (GitLab Schedules), который запускает playbook Ansible для apt update && apt upgrade --security-only на всех серверах.
  • Управление бэкапами: Terraform может создавать политики снапшотов дисков через провайдера облака. Отдельный пайплайн управляет их жизненным циклом (создание, ротация, удаление).
  • Аудит конфигураций: Playbook Ansible, который собирает критичные конфигурационные файлы с серверов, сравнивает их с эталоном и генерирует отчет об отклонениях.

Этот подход превращает вашу инфраструктуру в полностью управляемую кодовую базу. Для сравнения различных инструментов и подходов к IaC обратитесь к статье Infrastructure as Code в 2026: выбор между Terraform, Ansible и Pulumi.

Заключение: от практики к стратегии

Интеграция Terraform, Ansible и GitLab CI/CD создает фундамент для воспроизводимой, надежной и быстрой доставки инфраструктуры и приложений. Ключевые выгоды: устранение дрейфа конфигураций, значительное снижение человеческих ошибок, возможность быстрого восстановления среды и соответствие требованиям compliance за счет документирования всех изменений в коде.

Для дальнейшего развития рассмотрите:

  • Terragrunt для управления сложными, многоокружными проектами Terraform.
  • Atlantis для автоматизации workflow apply через pull request в команде.
  • GitOps с ArgoCD как эволюцию подхода CI/CD для Kubernetes, где желаемое состояние описывается в Git, а инструмент автоматически приводит кластер в соответствие с ним. Сравнение подходов рассмотрено в материале GitOps и Infrastructure as Code: практическое сравнение.
  • Тестирование: Внедрение Terratest для модулей Terraform и molecule для ролей Ansible.

Начните с малого - автоматизируйте развертывание одного сервиса по представленным шаблонам. Постепенно расширяйте coverage, внедряйте мониторинг и стратегии деплоя. Это инвестиция, которая окупается стабильностью production-среды и высвобождает время для решения более сложных задач. Для структурирования работы над такими задачами может быть полезен готовый шаблон должностной инструкции DevOps-инженера на 2026 год.

Поделиться:
Сохранить гайд? В закладки браузера