DBAtlas · Атлас эксплуатации баз данных

Развёртывание баз данных с Terraform (IaC)

Симптом

Цель: описать инфраструктуру баз данных (экземпляр, группу параметров, сеть) как код (Infrastructure as Code) с помощью Terraform; настроить процесс plan/apply, удалённое состояние (remote state) и управление дрейфом (drift).

1. Выберите и настройте провайдер (aws / google / azurerm)

Определите провайдер для используемого облака и зафиксируйте его версию. В блоке required_providers закрепите hashicorp/aws для AWS, hashicorp/google для GCP и hashicorp/azurerm для Azure. Фиксация версии обеспечивает одинаковое поведение во всей команде.

PostgreSQL

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

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

2. Настройте удалённое состояние и блокировку

Не храните файл состояния локально; для командной работы и безопасности используйте удалённый backend. Типичные варианты: backend S3 + таблица блокировок DynamoDB в AWS, backend gcs в GCP и backend azurerm (Storage Account) в Azure. Удалённое состояние предотвращает параллельные apply за счёт блокировки и делает состояние единым источником истины. Поскольку пароли могут храниться в состоянии открытым текстом, держите backend зашифрованным и с ограниченным доступом.

PostgreSQL

terraform {
  backend "s3" {
    bucket         = "company-tfstate"
    key            = "db/terraform.tfstate"
    region         = "eu-central-1"
    dynamodb_table = "tf-lock"
    encrypt        = true
  }
}

3. Определите ресурс базы данных

Опишите основной ресурс для вашего движка и облака: aws_db_instance в AWS (или aws_rds_cluster для Aurora), google_sql_database_instance в GCP, azurerm_mssql_database в Azure (для SQL Server — внутри azurerm_mssql_server). Здесь задайте движок, версию, класс, хранилище и окно бэкапа.

PostgreSQL

resource "aws_db_instance" "pg" {
  identifier        = "app-db"
  engine            = "postgres"
  engine_version    = "16"
  instance_class    = "db.t3.medium"
  allocated_storage = 50
  db_name           = "appdb"
  username          = "pgadmin"
  password          = var.db_password
  backup_retention_period = 7
}

SQL Server

resource "azurerm_mssql_database" "db" {
  name      = "appdb"
  server_id = azurerm_mssql_server.srv.id
  sku_name  = "S1"
}

4. Опишите группу параметров как код

Задавайте настройки базы данных (max_connections, work_mem, кодировка) ресурсом параметров, а не вручную в консоли. Используйте aws_db_parameter_group в AWS, settings.database_flags внутри google_sql_database_instance в GCP и ресурс конфигурации сервера в Azure. Тогда настройки версионируются и воспроизводимы.

PostgreSQL

resource "aws_db_parameter_group" "pg" {
  name   = "app-pg16"
  family = "postgres16"

  parameter {
    name  = "max_connections"
    value = "200"
  }
}
# inside aws_db_instance:
# parameter_group_name = aws_db_parameter_group.pg.name

5. Передавайте секреты через переменные и менеджер секретов

Не прописывайте пароль в файле .tf; определите его как чувствительную переменную (variable ... sensitive = true) и передавайте значение через переменную окружения TF_VAR_, менеджер секретов (AWS Secrets Manager, Vault) или секрет CI. Помните: значение записывается в файл состояния, поэтому удалённое состояние должно быть зашифровано. Самый чистый подход — вообще не передавать пароль в Terraform, а читать его из ресурса менеджера секретов.

PostgreSQL

variable "db_password" {
  type      = string
  sensitive = true
}

# CI/shell:
export TF_VAR_db_password="$(vault kv get -field=pw secret/db)"

6. Выполните процесс plan и apply

Сначала подготовьте провайдер/backend командой terraform init, посмотрите, что изменится, через terraform plan, утвердите и примените через terraform apply. Не применяйте без просмотра вывода plan; безопасный процесс в CI — публиковать 'plan' комментарием к PR и применять после утверждения человеком. Деструктивные изменения (например, пересоздание экземпляра) выявляйте по маркеру -/+ в выводе plan.

PostgreSQL

terraform init
terraform plan -out=plan.tfplan
terraform apply plan.tfplan

7. Обнаружение и устранение дрейфа

Если кто-то вручную вносит изменение в консоли, реальная инфраструктура и состояние расходятся (drift). Различия, появляющиеся в terraform plan, «когда ничего не должно было измениться», выявляют дрейф; разница читается через terraform refresh/plan. Либо перенесите изменение обратно в код, либо верните инфраструктуру к коду через apply. Запретите ручные изменения как правило; код должен быть единым источником истины.

PostgreSQL

# drift check (when no changes are expected):
terraform plan
# expect 'No changes'; any diff means drift
# bring an existing resource into state with import:
terraform import aws_db_instance.pg app-db
Открыть в DBAtlas →