Interview Questions

Terraform

Редактировать на GitHub
Теоретические вопросыВ чём отличие Ansible и Terraform, если через Ansible теперь тоже можно создавать инфраструктуру?Что такое провайдер?Что такое ресурс?Что такое tfstate?Что такое configuration drift (дрейф конфигурации)?Как блокировать tfstate, чтобы несколько пользователей не изменяли инфраструктуру одновременно?Как перенести ресурс, созданный через GUI, в код Terraform?В чём отличие между condition (тернарным оператором) и lookup в Terraform?Практические вопросыТы написал код в Terraform, выполнил terraform plan и вышел. После этого твой коллега добавил свой код, выполнил plan и тоже вышел. Теперь тебе нужно применить свою инфраструктуру — будут ли ошибки?У вас есть 20 серверов, созданных с помощью Terraform, но вы хотите удалить только один из них. Можно ли уничтожить один ресурс, не внося изменения в конфигурационные файлы?Какие есть best practices для “ухода” за Terraform tfstate?У вас есть несколько сред — dev, stage, prod — и вы хотите использовать один и тот же код Terraform для всех. Как это сделать?

Теоретические вопросы

В чём отличие Ansible и Terraform, если через Ansible теперь тоже можно создавать инфраструктуру?

Да, через Ansible сегодня можно создавать инфраструктуру — у него есть модули для разных провайдеров. Но принципиальное отличие остаётся в подходе и архитектуре инструментов:

  • Terraform — это инструмент декларативного описания инфраструктуры. Он хранит состояние (state), понимает, что уже создано, и вносит только нужные изменения. Это делает его идеальным для управления большими облачными средами
  • Ansible — остаётся инструментом процедурного конфигурирования. Он выполняет задачи пошагово, не отслеживая текущее состояние ресурсов. При помощи модулей он может создавать те же виртуалки или сети, но не управляет изменениями и зависимостями так эффективно, как Terraform.

Итог: Да, Ansible может делать то же, что Terraform, но Terraform делает это лучше и безопаснее для инфраструктуры, а Ansible удобнее для настройки и конфигурации систем после их создания.

Что такое провайдер?

Провайдер (provider) — это плагин, через который Terraform взаимодействует с внешними системами: облаками, виртуализацией, API и другими сервисами.

Он отвечает за создание, изменение и удаление ресурсов конкретного типа — например, виртуальных машин, сетей, DNS-записей и т.п.

Что такое ресурс?

Ресурс (resource) — это основной строительный блок в Terraform, описывающий конкретный объект инфраструктуры, который нужно создать, изменить или удалить.

Каждый ресурс управляется через провайдер и представляет реальный объект во внешней системе — например:

  • виртуальную машину,
  • сетевой интерфейс,
  • S3-бакет,
  • DNS-запись,
  • Kubernetes pod и т.д.

Что такое tfstate?

tfstate — это файл состояния Terraform, который хранит актуальное описание созданной инфраструктуры.

Terraform использует этот файл, чтобы понимать:

  • какие ресурсы уже существуют,
  • какие параметры у них заданы,
  • что нужно создать, изменить или удалить при следующем запуске terraform apply.

По умолчанию файл называется terraform.tfstate и создаётся в рабочей директории, но его можно хранить удалённо (в S3, GCS, etcd, Consul и т.д.) — это обязательно при командной работе.

Важно знать:

  • tfstateединственный источник правды о состоянии инфраструктуры.
  • При повреждении или потере файла Terraform не сможет корректно рассчитать изменения.
  • Для командной работы используют remote backend и state locking (блокировку состояния).

Что такое configuration drift (дрейф конфигурации)?

Configuration drift — это расхождение между описанием инфраструктуры в коде (Terraform, Ansible и т.д.) и её фактическим состоянием в реальности.

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

Примеры дрейфа:

  • кто-то изменил параметры VM через консоль;
  • удалили ресурс вручную, но он всё ещё описан в коде;
  • поменяли сетевые настройки, которых нет в Terraform.

Как Terraform с этим работает:

  • Команда terraform plan обнаруживает дрейф — она сравнивает содержимое tfstate с текущим состоянием инфраструктуры через API провайдеров.
  • Если есть расхождения, Terraform предложит действия (create, update, delete), чтобы привести реальность в соответствие с кодом.

Как избежать:

  • Не вносить ручные изменения в инфраструктуру.
  • Хранить tfstate централизованно (remote backend).
  • Делать регулярные terraform plan для проверки.

Как блокировать tfstate, чтобы несколько пользователей не изменяли инфраструктуру одновременно?

Terraform поддерживает механизм state locking — блокировку состояния, чтобы предотвратить одновременные изменения инфраструктуры несколькими пользователями или процессами.

Блокировка включается автоматически при использовании remote backend, который поддерживает lock-функциональность.

🔧 Основные способы блокировки:

BackendМеханизм блокировки
S3 + DynamoDBS3 хранит state, DynamoDB — управляет блокировками. Это самый распространённый вариант.
ConsulПоддерживает блокировку через встроенный механизм sessions.
GCS (Google Cloud Storage)Использует объектные блокировки (preconditions).
Terraform Cloud / EnterpriseВстроенная автоматическая блокировка.

Пример:

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "eu-central-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Здесь:

  • S3 хранит файл состояния,
  • DynamoDB используется для блокировки (LockID записывается в таблицу).

Если локальный backend (local) — блокировка не поддерживается, поэтому важно хранить state в удалённом бекенде при командной работе.

Как перенести ресурс, созданный через GUI, в код Terraform?

Два пути:

  1. terraform import / import-blocks — импортируем существующий объект в state, а HCL пишем сами.
  2. Генераторы кода (напр. Terraformer) — сразу получают и state, и HCL.

Классический способ (надёжный):

# 1) Инициализация
terraform init

# 2) Пишем минимальный ресурс в HCL (тип и имя)
resource "aws_s3_bucket" "logs" {}

# 3) Импортируем существующий объект по его ID
terraform import aws_s3_bucket.logs my-logs-bucket

# 4) Проверяем и дописываем конфиг до желаемого состояния
terraform plan

В новых версиях можно использовать import blocks и затем terraform plan/apply, чтобы заполнить state без terraform import.

Автогенерация кода:

  • Terraformer (GCP/AWS/Azure/K8s и др.):
    выгружает существующие ресурсы → генерирует *.tf + tfstate. Удобно для стартовой миграции.
  • Аналоги: Former2 (AWS, из CloudFormation/аккаунта), aztfy (Azure).

Замечания:

  • Импорт не создаёт конфиг (если без генераторов) — HCL нужно привести к фактическому состоянию, иначе plan покажет изменения.
  • Важно знать точный ID ресурса и тип (aws_…, google_…, azurerm_…).
  • Зависимости (depends_on, ссылки на VPC/SG и т.п.) придётся связать вручную или сгенерировать инструментом.

В чём отличие между condition (тернарным оператором) и lookup в Terraform?

Оба используются для выбора значений, но работают по-разному:

Критерийcondition (тернарный оператор)lookup()
НазначениеУсловный выбор между двумя выражениямиПолучение значения по ключу из map
Синтаксисcondition ? value_if_true : value_if_falselookup(map, key, default)
ТипЛогический оператор (if-else)Функция поиска
Примерvar.env == "prod" ? "10.0.0.1" : "10.0.0.2"lookup(var.subnets, var.env, "default-subnet")
Ошибка при отсутствии значенияНет, если условие не выполняетсяНет, если указан default
Когда использоватьКогда нужно выбрать между двумя вариантамиКогда нужно взять значение из map по ключу

Кратко:

  • condition — это if-else в одну строку.
  • lookup — это поиск значения по ключу в словаре (map) с возможностью указать значение по умолчанию.

Практические вопросы

Ты написал код в Terraform, выполнил terraform plan и вышел. После этого твой коллега добавил свой код, выполнил plan и тоже вышел. Теперь тебе нужно применить свою инфраструктуру — будут ли ошибки?

Нет, ошибок не будет, потому что команда terraform plan не вносит изменений в инфраструктуру и не модифицирует tfstate. Проблемы могут возникнуть только, если вы оба одновременно выполняете apply или используете устаревший файл плана (plan -out), после того как кто-то изменил состояние. Обычно перед apply делают новый plan, чтобы состояние было актуальным.

У вас есть 20 серверов, созданных с помощью Terraform, но вы хотите удалить только один из них. Можно ли уничтожить один ресурс, не внося изменения в конфигурационные файлы?

Да, можно. Для этого используется команда terraform destroy -target=<resource>,
которая удаляет только указанный ресурс из инфраструктуры, не трогая остальные.

Какие есть best practices для “ухода” за Terraform tfstate?

  • Remote backend — хранить state удалённо (например, S3/GCS/Terraform Cloud) для совместной работы и безопасности.
  • Блокировка (locking) — включить lock на время apply (S3 + DynamoDB, Consul и т.п.), чтобы избежать конфликтов.
  • Ограничение доступа — минимум прав (PoLP), отдельные роли/аккаунты, доступ только авторизованным пользователям/CI.
  • Бэкапы и версионирование — включить versioning и регулярные бэкапы, чтобы можно было восстановиться.
  • Шифрование — at rest (KMS/SSE) и in transit (TLS).
  • Изоляция стейтов — раздельные state для prod/stage/dev и для компонентов; не сваливать всё в один файл.
  • Без секретов — не хранить чувствительные данные в state; использовать внешние секрет-менеджеры.
  • Процесс примененияplan перед apply, по возможности применять только из CI/CD; избегать ручных правок state.
  • Аудит — включить логирование доступа к бэкенду и периодически проверять дрейф (terraform plan).

У вас есть несколько сред — dev, stage, prod — и вы хотите использовать один и тот же код Terraform для всех. Как это сделать?

Используйте одни и те же модули, а различия между средами выносите в переменные. Организуйте проект так, чтобы конфиг каждой среды подставлял свои значения. Для продакшена обычно выбирают модули + отдельные переменные/конфиги на среду (часто через Terragrunt). Workspaces существуют, но редко рекомендуются для изоляции prod/stage/dev.

Подход 1: Модули + переменные (рекомендуется)

  • Бизнес-логика инфраструктуры — в модуле.
  • Для каждой среды — свой набор переменных (tfvars) и/или отдельный «обёрточный» слой.
  • Изоляция по state и по учёткам (часто отдельный AWS account на среду).

Структура (вариант без Terragrunt):

infra/
├─ modules/
│  └─ vpc/
│     ├─ main.tf
│     ├─ variables.tf
│     └─ outputs.tf
└─ envs/
   ├─ dev/
   │  ├─ main.tf        # вызывает module "vpc"
   │  └─ dev.tfvars     # значения для dev
   ├─ stage/
   │  ├─ main.tf
   │  └─ stage.tfvars
   └─ prod/
      ├─ main.tf
      └─ prod.tfvars

Пример env-конфига (prod/main.tf):

module "vpc_prod" {
  source     = "../../modules/vpc"
  env        = "prod"
  cidr_block = "10.100.0.0/16"

  public_subnets  = ["10.100.12.0/24", "10.100.13.0/24", "10.100.14.0/24"]
  private_subnets = ["10.100.21.0/24", "10.100.22.0/24"]
}

Запуск:

cd infra/envs/prod
terraform init
terraform apply -var-file=prod.tfvars

Изоляция аккаунтов/ролей (AWS):

provider "aws" {
  region = "eu-central-1"

  assume_role {
    role_arn     = "arn:aws:iam::123456789012:role/RemoteAdministrator"
    session_name = "terraform-session"
  }
}

Для каждой среды используйте свой backend (или свой key в S3) и свою роль/аккаунт.

Подход 2: Terraform Workspaces (обычно не для прод-изоляции)

  • Один и тот же код, разные workspace → разные значения переменных и разные state в одном backend.
  • Подходит для лёгких вариаций (dev/test), но для prod лучше отдельные каталоги/state/аккаунты.

Пример:

terraform workspace new dev
terraform workspace new stage
terraform workspace new prod

terraform workspace select prod
terraform apply -var-file=prod.tfvars

Последнее обновление: 9 окт. 2025 г., 11:36:16

Оглавление

Теоретические вопросы
В чём отличие Ansible и Terraform, если через Ansible теперь тоже можно создавать инфраструктуру?
Что такое провайдер?
Что такое ресурс?
Что такое tfstate?
Что такое configuration drift (дрейф конфигурации)?
Как блокировать tfstate, чтобы несколько пользователей не изменяли инфраструктуру одновременно?
Как перенести ресурс, созданный через GUI, в код Terraform?
В чём отличие между condition (тернарным оператором) и lookup в Terraform?
Практические вопросы
Ты написал код в Terraform, выполнил terraform plan и вышел. После этого твой коллега добавил свой код, выполнил plan и тоже вышел. Теперь тебе нужно применить свою инфраструктуру — будут ли ошибки?
У вас есть 20 серверов, созданных с помощью Terraform, но вы хотите удалить только один из них. Можно ли уничтожить один ресурс, не внося изменения в конфигурационные файлы?
Какие есть best practices для “ухода” за Terraform tfstate?
У вас есть несколько сред — dev, stage, prod — и вы хотите использовать один и тот же код Terraform для всех. Как это сделать?