Skip to content

Імпорт ресурсів AWS RDS за допомогою Terraform

Written by:

Igor Gorovyy
DevOps Engineer Lead & Senior Solutions Architect
LinkedIn

Using terraform for import aws rds

Огляд процесу

У цій статті розглянемо процес імпорту існуючих баз даних AWS RDS в інфраструктурний код Terraform. Це важливий етап у забезпеченні підходу Infrastructure as Code (IaC) для керування хмарними ресурсами.

Коли компанія заощаджує кошти і водночас планує Disaster Recovery Plan (DRP), найпростішим сценарієм буде бекап та відновлення ресурсів. У випадку хмарної інфраструктури ресурси зазвичай відновлюються в іншому регіоні.

Ця стаття не покриває інші стратегії а підходи nbge stand-by, active-activeт DRP, оскільки це не є основною темою. Основним наміром є показати "дешево та сердито ..." механізм terraform import та його використання для імпорту ресурсів RDS.

При відновленні ресурсів виникає необхідність покриття кодом Terraform нового середовища. Механізм імпорту ресурсів у Terraform дозволяє швидко та безпечно відновити ресурси.

До версії Terraform 1.6 імпорт вимагав ручного керування станом (state) і контролю за тим, куди переміщуються ресурси. Це могло призводити до потенційних помилок. Починаючи з версії 1.6, Terraform надає більш просту та надійну систему керування імпортом ресурсів, що значно спрощує процес відновлення інфраструктури у DRP-сценаріях.

Схема процесу імпорту

graph TD;
    A[Існуючий ресурс AWS RDS] -->|Команда import| B[Імпорт у Terraform]
    B -->|Генерація конфігурації| C[Створення main.tf]
    C -->|Перевірка змін| D[terraform plan]
    D -->|Застосування змін| E[terraform apply]
    E -->|Ресурс під управлінням Terraform| F[Готовий RDS]

Для чого потрібен імпорт?

Імпорт існуючих ресурсів дозволяє:

  • Централізувати керування інфраструктурою за допомогою Terraform
  • Відстежувати зміни конфігурацій через систему контролю версій
  • Уникати ручного налаштування ресурсів та зменшувати ризик помилок
  • Спрощувати розгортання та масштабування систем
  • Забезпечувати ефективне відновлення після інцидентів або аварій

Основні кроки імпорту ресурсів RDS

1. Відстеження змін

  • Збереження стану інфраструктури
  • Terraform використовує файл terraform.tfstate для збереження поточного стану ресурсів.
  • Це дозволяє уникнути розбіжностей між фактичним станом у хмарі та конфігурацією у коді.

  • Запобігання конфліктам

  • Використання механізмів блокування змін (terraform plan) дозволяє уникнути одночасних конфліктних оновлень ресурсів.
  • Це особливо корисно при спільній роботі кількох інженерів.

  • Історія модифікацій

  • Використання Git або інших систем контролю версій допомагає відстежувати внесені зміни та швидко повертатися до попередніх конфігурацій.
  • Логування змін у Terraform дозволяє відслідковувати причини та наслідки кожної модифікації.

2. Автоматизація процесів

  • CI/CD інтеграція
  • Terraform можна інтегрувати з системами автоматизації, такими як GitHub Actions, GitLab CI/CD, Jenkins або AWS CodePipeline.
  • Це дозволяє автоматично застосовувати зміни після проходження тестів.

  • Автоматичне тестування

  • terraform validate перевіряє коректність синтаксису конфігурацій.
  • terraform plan дозволяє оцінити майбутні зміни перед їх застосуванням.
  • terratest використовується для модульного тестування інфраструктури.

  • Планові оновлення

  • Використання автоматизованих процесів оновлення інфраструктури дозволяє своєчасно застосовувати оновлення без ризику збоїв.
  • Застосування terraform apply -auto-approve у контрольованих середовищах спрощує оновлення конфігурацій.

  • Автоматичне розгортання

  • За допомогою модулів Terraform можна стандартизовано розгортати нові середовища без ручного втручання.
  • Автоматичне розгортання дозволяє зменшити час виходу продукту на ринок.

3. Масштабованість

  • Гнучкість розгортання
  • Terraform підтримує параметризовані змінні, що дозволяє легко адаптувати конфігурації під різні середовища (dev, staging, production).
  • Використання модулів дозволяє уникнути дублювання коду.

  • Мультирегіональність

  • Terraform дозволяє керувати інфраструктурою у різних регіонах AWS з однієї конфігурації.
  • Використання provider з alias дозволяє легко розгортати ресурси у кількох регіонах. В нашому випадку ми переносимо ресурси в регіон "Blue" (provider = aws.Blue ) і там імпортуэмо ресурси до коду.

  • Клонування середовищ

  • Terraform підтримує terraform workspace, що дозволяє створювати незалежні середовища для тестування, не впливаючи на продакшен.
  • Можливість швидкого копіювання конфігурацій дозволяє легко створювати нові екземпляри інфраструктури.

Приклади коду

Імпорт існуючого RDS у Terraform

terraform plan -generate-config-out=generated-resources.tf
terraform import aws_db_instance.example_db my-existing-db

Оголошення ресурсу RDS у Terraform

import {
  provider = aws.Blue  
  to = aws_db_instance.product1-dev-service1-migrated
  id = "product1-dev-service1-migrated"
}

import {
  provider = aws.Blue  
  to = aws_db_instance.product1-dev-service2-migrated
  id = "product1-dev-service2-migrated"
}

import {
  provider = aws.Blue  
  to = aws_db_instance.product1-dev-service3-migrated
  id = "product1-dev-service3-migrated"
}

import {
  provider = aws.Blue  
  to = aws_db_instance.product1-dev-service4-migrated
  id = "product1-dev-service4-migrated"
}

import {
  provider = aws.Blue  
  to = aws_db_instance.product1-service5-migrated
  id = "product1-service5-migrated"
}
# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.

# __generated__ by Terraform
resource "aws_db_instance" "product1-dev-service1-migrated" {
  provider                              = aws.Blue
  allocated_storage                     = 100
  allow_major_version_upgrade           = null
  apply_immediately                     = null
  auto_minor_version_upgrade            = false
  availability_zone                     = "eu-west-1a"
  backup_retention_period               = 5
  backup_target                         = "region"
  backup_window                         = "20:31-21:01"
  ca_cert_identifier                    = "rds-ca-rsa2048-g1"
  character_set_name                    = null
  copy_tags_to_snapshot                 = false
  custom_iam_instance_profile           = null
  customer_owned_ip_enabled             = false
  db_name                               = "owner"
  db_subnet_group_name                  = "multiregion-dev-vpc-blue"
  dedicated_log_volume                  = false
  delete_automated_backups              = true
  deletion_protection                   = true
  domain                                = null
  domain_auth_secret_arn                = null
  domain_fqdn                           = null
  domain_iam_role_name                  = null
  domain_ou                             = null
  enabled_cloudwatch_logs_exports       = []
  engine                                = "postgres"
  engine_lifecycle_support              = "open-source-rds-extended-support"
  engine_version                        = jsonencode(16.6)
  final_snapshot_identifier             = null
  iam_database_authentication_enabled   = false
  identifier                            = "product1-dev-service4-migrated"
  identifier_prefix                     = null
  instance_class                        = "db.t4g.large"
  iops                                  = 3000
  kms_key_id                            = "arn:aws:kms:eu-west-1:294***********8:key/1*********-8**f-4**0-8**1-**********b"
  license_model                         = "postgresql-license"
  maintenance_window                    = "wed:01:55-wed:02:25"
  manage_master_user_password           = null
  master_user_secret_kms_key_id         = null
  max_allocated_storage                 = 0
  monitoring_interval                   = 0
  monitoring_role_arn                   = null
  multi_az                              = false
  nchar_character_set_name              = null
  network_type                          = "IPV4"
  option_group_name                     = "default:postgres-16"
  parameter_group_name                  = "multiregion-rds-service4-pg-16"
  password                              = null # sensitive
  performance_insights_enabled          = false
  performance_insights_kms_key_id       = null
  performance_insights_retention_period = 0
  port                                  = 5432
  publicly_accessible                   = false
  replica_mode                          = null
  replicate_source_db                   = null
  skip_final_snapshot                   = true
  snapshot_identifier                   = null
  storage_encrypted                     = true
  storage_throughput                    = 125
  storage_type                          = "gp3"
  tags                                  = {}
  tags_all                              = {}
  timezone                              = null
  upgrade_storage_config                = null
  username                              = "service1"
  vpc_security_group_ids                = ["sg-0fe****************6"]
}

# __generated__ by Terraform
resource "aws_db_instance" "product1-dev-service2-migrated" {
  provider                              = aws.Blue
  allocated_storage                     = 605
  allow_major_version_upgrade           = null
  apply_immediately                     = null
  auto_minor_version_upgrade            = false
  availability_zone                     = "eu-west-1a"
  backup_retention_period               = 5
  backup_target                         = "region"
  backup_window                         = "21:14-21:44"
  ca_cert_identifier                    = "rds-ca-rsa2048-g1"
  character_set_name                    = null
  copy_tags_to_snapshot                 = false
  custom_iam_instance_profile           = null
  customer_owned_ip_enabled             = false
  db_name                               = "service2"
  db_subnet_group_name                  = "multiregion-dev-vpc-blue"
  dedicated_log_volume                  = false
  delete_automated_backups              = true
  deletion_protection                   = true
  domain                                = null
  domain_auth_secret_arn                = null
  domain_fqdn                           = null
  domain_iam_role_name                  = null
  domain_ou                             = null
  enabled_cloudwatch_logs_exports       = []
  engine                                = "postgres"
  engine_lifecycle_support              = "open-source-rds-extended-support"
  engine_version                        = jsonencode(16.6)
  final_snapshot_identifier             = null
  iam_database_authentication_enabled   = false
  identifier                            = "product1-dev-service2-migrated"
  identifier_prefix                     = null
  instance_class                        = "db.m6g.large"
  iops                                  = 12000
  kms_key_id                            = "arn:aws:kms:eu-west-1:294***********8:key/1*********-8**f-4**0-8**1-**********b"
  license_model                         = "postgresql-license"
  maintenance_window                    = "sun:00:07-sun:00:37"
  manage_master_user_password           = null
  master_user_secret_kms_key_id         = null
  max_allocated_storage                 = 0
  monitoring_interval                   = 0
  monitoring_role_arn                   = null
  multi_az                              = false
  nchar_character_set_name              = null
  network_type                          = "IPV4"
  option_group_name                     = "default:postgres-16"
  parameter_group_name                  = "multiregion-rds-pg-logical-16"
  password                              = null # sensitive
  performance_insights_enabled          = false
  performance_insights_kms_key_id       = null
  performance_insights_retention_period = 0
  port                                  = 5432
  publicly_accessible                   = false
  replica_mode                          = null
  replicate_source_db                   = null
  skip_final_snapshot                   = true
  snapshot_identifier                   = null
  storage_encrypted                     = true
  storage_throughput                    = 500
  storage_type                          = "gp3"
  tags                                  = {}
  tags_all                              = {}
  timezone                              = null
  upgrade_storage_config                = null
  username                              = "service2"
  vpc_security_group_ids                = ["sg-0fe****************6"]
}

# __generated__ by Terraform
resource "aws_db_instance" "product1-service3-migrated" {
  provider                              = aws.Blue
  allocated_storage                     = 83
  allow_major_version_upgrade           = null
  apply_immediately                     = null
  auto_minor_version_upgrade            = false
  availability_zone                     = "eu-west-1a"
  backup_retention_period               = 1
  backup_target                         = "region"
  backup_window                         = "21:12-21:42"
  ca_cert_identifier                    = "rds-ca-rsa2048-g1"
  character_set_name                    = null
  copy_tags_to_snapshot                 = false
  custom_iam_instance_profile           = null
  customer_owned_ip_enabled             = false
  db_name                               = "service5"
  db_subnet_group_name                  = "multiregion-dev-vpc-blue"
  dedicated_log_volume                  = false
  delete_automated_backups              = true
  deletion_protection                   = true
  domain                                = null
  domain_auth_secret_arn                = null
  domain_fqdn                           = null
  domain_iam_role_name                  = null
  domain_ou                             = null
  enabled_cloudwatch_logs_exports       = []
  engine                                = "postgres"
  engine_lifecycle_support              = "open-source-rds-extended-support"
  engine_version                        = jsonencode(16.6)
  final_snapshot_identifier             = null
  iam_database_authentication_enabled   = false
  identifier                            = "product1-service5-migrated"
  identifier_prefix                     = null
  instance_class                        = "db.t4g.large"
  iops                                  = 3000
  kms_key_id                            = "arn:aws:kms:eu-west-1:294***********8:key/1*********-8**f-4**0-8**1-**********b"
  license_model                         = "postgresql-license"
  maintenance_window                    = "thu:01:30-thu:02:00"
  manage_master_user_password           = null
  master_user_secret_kms_key_id         = null
  max_allocated_storage                 = 0
  monitoring_interval                   = 0
  monitoring_role_arn                   = null
  multi_az                              = false
  nchar_character_set_name              = null
  network_type                          = "IPV4"
  option_group_name                     = "default:postgres-16"
  parameter_group_name                  = "multiregion-rds-dev-athena-16"
  password                              = null # sensitive
  performance_insights_enabled          = false
  performance_insights_kms_key_id       = null
  performance_insights_retention_period = 0
  port                                  = 5432
  publicly_accessible                   = false
  replica_mode                          = null
  replicate_source_db                   = null
  skip_final_snapshot                   = true
  snapshot_identifier                   = null
  storage_encrypted                     = true
  storage_throughput                    = 125
  storage_type                          = "gp3"
  tags                                  = {}
  tags_all                              = {}
  timezone                              = null
  upgrade_storage_config                = null
  username                              = "service3"
  vpc_security_group_ids                = ["sg-0fe****************6"]
}

# __generated__ by Terraform
resource "aws_db_instance" "product1-dev-service4-migrated" {
  provider                              = aws.Blue
  allocated_storage                     = 330
  allow_major_version_upgrade           = null
  apply_immediately                     = null
  auto_minor_version_upgrade            = false
  availability_zone                     = "eu-west-1a"
  backup_retention_period               = 5
  backup_target                         = "region"
  backup_window                         = "00:59-01:29"
  ca_cert_identifier                    = "rds-ca-rsa2048-g1"
  character_set_name                    = null
  copy_tags_to_snapshot                 = false
  custom_iam_instance_profile           = null
  customer_owned_ip_enabled             = false
  db_name                               = "managementaccounting"multiregion-rds-pg-audit-16
  db_subnet_group_name                  = "multiregion-dev-vpc-blue"
  dedicated_log_volume                  = false
  delete_automated_backups              = true
  deletion_protection                   = true
  domain                                = null
  domain_auth_secret_arn                = null
  domain_fqdn                           = null
  domain_iam_role_name                  = null
  domain_ou                             = null
  enabled_cloudwatch_logs_exports       = []
  engine                                = "postgres"
  engine_lifecycle_support              = "open-source-rds-extended-support"
  engine_version                        = jsonencode(16.6)
  final_snapshot_identifier             = null
  iam_database_authentication_enabled   = false
  identifier                            = "product1-dev-service3-migrated"
  identifier_prefix                     = null
  instance_class                        = "db.t4g.large"
  iops                                  = 3000
  kms_key_id                            = "arn:aws:kms:eu-west-1:294***********8:key/1*********-8**f-4**0-8**1-**********b"
  license_model                         = "postgresql-license"
  maintenance_window                    = "wed:23:11-wed:23:41"
  manage_master_user_password           = null
  master_user_secret_kms_key_id         = null
  max_allocated_storage                 = 0
  monitoring_interval                   = 0
  monitoring_role_arn                   = null
  multi_az                              = false
  nchar_character_set_name              = null
  network_type                          = "IPV4"
  option_group_name                     = "default:postgres-16"
  parameter_group_name                  = "multiregion-rds-pg-audit-16"
  password                              = null # sensitive
  performance_insights_enabled          = false
  performance_insights_kms_key_id       = null
  performance_insights_retention_period = 0
  port                                  = 5432
  publicly_accessible                   = false
  replica_mode                          = null
  replicate_source_db                   = null
  skip_final_snapshot                   = true
  snapshot_identifier                   = null
  storage_encrypted                     = true
  storage_throughput                    = 125
  storage_type                          = "gp3"
  tags                                  = {}
  tags_all                              = {}
  timezone                              = null
  upgrade_storage_config                = null
  username                              = "service4"
  vpc_security_group_ids                = ["sg-0fe****************6"]
}

# __generated__ by Terraform
resource "aws_db_instance" "product1-dev-service5-migrated" {
  provider                              = aws.Blue
  allocated_storage                     = 64
  allow_major_version_upgrade           = null
  apply_immediately                     = null
  auto_minor_version_upgrade            = false
  availability_zone                     = "eu-west-1a"
  backup_retention_period               = 5
  backup_target                         = "region"
  backup_window                         = "01:22-01:52"
  ca_cert_identifier                    = "rds-ca-rsa2048-g1"
  character_set_name                    = null
  copy_tags_to_snapshot                 = false
  custom_iam_instance_profile           = null
  customer_owned_ip_enabled             = false
  db_name                               = "service1"
  db_subnet_group_name                  = "multiregion-dev-vpc-blue"
  dedicated_log_volume                  = false
  delete_automated_backups              = true
  deletion_protection                   = true
  domain                                = null
  domain_auth_secret_arn                = null
  domain_fqdn                           = null
  domain_iam_role_name                  = null
  domain_ou                             = null
  enabled_cloudwatch_logs_exports       = []
  engine                                = "postgres"
  engine_lifecycle_support              = "open-source-rds-extended-support"
  engine_version                        = jsonencode(16.6)
  final_snapshot_identifier             = null
  iam_database_authentication_enabled   = false
  identifier                            = "product1-dev-service1-migrated"
  identifier_prefix                     = null
  instance_class                        = "db.t4g.large"
  iops                                  = 3000
  kms_key_id                            = "arn:aws:kms:eu-west-1:294***********8:key/1*********-8**f-4**0-8**1-**********b"
  license_model                         = "postgresql-license"
  maintenance_window                    = "tue:22:05-tue:22:35"
  manage_master_user_password           = null
  master_user_secret_kms_key_id         = null
  max_allocated_storage                 = 0
  monitoring_interval                   = 0
  monitoring_role_arn                   = null
  multi_az                              = false
  nchar_character_set_name              = null
  network_type                          = "IPV4"
  option_group_name                     = "default:postgres-16"
  parameter_group_name                  = "multiregion-rds-pg-logical-16"
  password                              = null # sensitive
  performance_insights_enabled          = false
  performance_insights_kms_key_id       = null
  performance_insights_retention_period = 0
  port                                  = 5432
  publicly_accessible                   = false
  replica_mode                          = null
  replicate_source_db                   = null
  skip_final_snapshot                   = true
  snapshot_identifier                   = null
  storage_encrypted                     = true
  storage_throughput                    = 125
  storage_type                          = "gp3"
  tags                                  = {}
  tags_all                              = {}
  timezone                              = null
  upgrade_storage_config                = null
  username                              = "service5"
  vpc_security_group_ids                = ["sg-0fe****************6"]
}

Планування та застосування змін

terraform plan
terraform apply -auto-approve

Висновок

Стратегічні переваги

  • Покращення керованості
  • Централізоване управління всіма ресурсами через єдину конфігурацію.
  • Легкість у відстеженні та контролі змін.
  • Автоматизоване оновлення та управління залежностями.

  • Оптимізація ресурсів

  • Скорочення витрат за рахунок правильного планування інфраструктури.
  • Автоматичне масштабування та ефективний розподіл ресурсів.
  • Мінімізація ризику людських помилок через автоматизоване розгортання.

Довгострокові вигоди

  • Інвестиція в майбутнє
  • Полегшене розширення інфраструктури завдяки IaC.
  • Забезпечення стабільності та повторюваності розгортань.
  • Відповідність стандартам безпеки та відповідності.

  • Операційні покращення

  • Скорочення часу на управління інфраструктурою.
  • Автоматизація процесів розгортання та оновлення.
  • Підвищення загальної надійності та доступності сервісів.

References: Hashicorp