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

Загрузка состояний Terraform в Object Storage

Terraform — это средство для создания и управления инфраструктурой в коде, которое дает возможность развертывать, модифицировать и удалять разнообразные ресурсы в облачных сервисах, такие как виртуальные сервера, сетевые элементы, хранилища данных и т.д. Он применяет язык настроек HCL (HashiCorp Configuration Language), который имеет декларативный и понятный человеку синтаксис. HCL позволяет задавать требуемое состояние инфраструктуры с помощью секций, параметров и формул.

Преимущества использования: 

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

Remote State

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

Механизм Remote State позволяет хранить файлы состояния в удалённом хранилище, что позволяет пользователям работать с самой свежей версией состояния и не думать о синхронизации. Terraform поддерживает следующие хранилища:

  • Terraform Cloud
  • HashiCorp Consul
  • Amason S3 (или другое S3-совместимое хранилище)
  • Google Cloud Storage
  • Azure Blob Storage
  • многие другие

Хранение состояния настраивается в конфигурации в блоке backend, например:

backend "s3" {
     endpoint   = ""
     bucket     = ""
    …
  }

Подробнее о конфигурации бэкэнда можно прочитать на сайте Terraform: Backend Configuration.

На данный момент Timeweb Cloud не поддерживает загрузку состояний в S3 для версий Terraform 1.6.0 и выше из-за изменений в структуре конфигурации.

Подготовка

Необходимые платные ресурсы

В этой статье будут созданы:

  • Две виртуальные машины (тарифы)
  • Один бакет Object Storage (тарифы)
  • Одна локальная сеть

Создаём бакет

Чтобы использовать S3 в качестве хранилища состояния, нам необходимо создать бакет. Для этого перейдём в панель управления, в раздел «Хранилище S3».

Image6

Нажмём на кнопку «Создать». Для примера возьмём минимальную конфигурацию:

Image 2023 10 23 13 22 36

В бакете, который мы только что создали, видим настройки, которые в дальнейшем укажем в файле .tf:

Image 2023 10 23 13 09 11

Пишем конфигурацию

Теперь приступим к написанию конфигурации. 

  1. Добавляем папку terraform_s3, в которой будет наш проект.
  2. Создаём там файл main.tf.
  3. По инструкции заполняем информацию о провайдере.

Должна получиться следующая структура файлов:

├── terraform_s3
│   ├── main.tf

И следующее содержимое файла main.tf:

terraform {
  required_providers {
    twc = {
      source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"
    }
  }
  required_version = ">= 1.5.3"
}

provider "twc" {
  token = "<your token>"
}

Теперь добавим настройки бэкенда в блок terraform:

  backend "s3" {
    endpoint = "s3.timeweb.com"
    region = "ru-1"
    bucket = "<bucket name>"
    key  = "states/terraform.tfstate"
    access_key = "<your access key>"
    secret_key = "<your secret key>"
    skip_region_validation = true
    skip_credentials_validation = true
    }

Параметры:

  1. endpoint — адрес S3-хранилища из панели управления.
  2. region — регион из панели управления.
  3. bucket — название бакета, где буду храниться наши конфигурации.
  4. key — путь к файлу в бакете вместе с названием файла. Например, states/<название файла>.tfstate.
  5. access_key и secret_key — ключи для доступа к бакету. Их можно получить в панели управления, на странице созданного ранее бакета
  6. skip_region_validation и skip_credentials_validation — флаги, с помощью которых мы пропускаем валидацию региона и ключей доступа на стороне AWS. Они нужны, так как мы используем не оригинальный AWS S3, а другое облако.

Вот так должен выглядеть полный код файла main.tf:

terraform {
  required_providers {
    twc = {
      source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"
    }
  }
  required_version = ">= 1.5.3"

  backend "s3" {
    endpoint = "s3.timeweb.com"
    region = "ru-1"
    bucket = "<bucket name>"
    key  = "states/terraform.tfstate"
    access_key = "<your access key>"
    secret_key = "<your secret key>"
    skip_region_validation = true
    skip_credentials_validation = true
    }
}

provider "twc" {
  token = "<your token>"
}

После всех настроек выполним команду terraform init:

Image1

Защита данных

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

  1. Можно установить переменные окружения AWS_ACCESS_KEY_ID и AWS_SECRET_ACCESS_KEY с соответствующими значениями ключей доступа к бакету. Тогда Terraform будет автоматически читать эти переменные при работе с бэкэндом.
  2. Использование параметров командной строки. Можно использовать параметр -backend-config при выполнении команды init:
terraform init -backend-config="access_key=1234" -backend-config="secret_key=1234" 

Создаём инфраструктуру

В файле main.tf опишем создание виртуальной машины и локальной сети:

  1. Укажем ОС.
data "twc_os" "example-os" {
  name = "ubuntu"
 version = "22.04"
}
  1. Укажем пресет.
data "twc_presets" "example-preset" {
  price_filter {
    from = 300
    to = 400
  }
}
  1. Добавим VPC.
resource "twc_vpc" "example-vpc" {
  name = "Example VPC"
  description = "Some example VPC"
  subnet_v4 = "192.168.0.0/24"
  location = "ru-1"
}
  1. Опишем конфигурацию сервера.
resource "twc_server" "example-server-with-local-network" {
  name = "Example server with local network"
  os_id = data.twc_os.example-os.id

  preset_id = data.twc_presets.example-preset.id

  local_network {
    id = twc_vpc.example-vpc.id
  }
}
  1. Добавим идентификатор приватной сети в выходные параметры, чтобы мы могли использовать его в других конфигурациях
output "tw-vpc" {
    value = twc_vpc.example-vpc.id
}

Содержимое конфигурации main.tf будет выглядеть так:

terraform {
  required_providers {
    twc = {

      source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"
    }
  }
  required_version = ">= 1.5.3"

  backend "s3" {
    endpoint = "s3.timeweb.com"
    region = "ru-1"
    bucket = "<bucket name>"
    key  = "states/terraform.tfstate"
    access_key = "<your access key>"
    secret_key = "<your secret key>"
    skip_region_validation = true
    skip_credentials_validation = true
    }
}

provider "twc" {
  token = "<your token>"
}

data "twc_os" "example-os" {
  name = "ubuntu"
  version = "22.04"
}

data "twc_presets" "example-preset" {
  price_filter {
    from = 300
    to = 400
  }
}

resource "twc_vpc" "example-vpc" {
  name = "Example VPC"
  description = "Some example VPC"
  subnet_v4 = "192.168.0.0/24"
  location = "ru-1"
}

resource "twc_server" "example-server-with-local-network" {
  name = "Example server with local network"
  os_id = data.twc_os.example-os.id

  preset_id = data.twc_presets.example-preset.id

  local_network {
    id = twc_vpc.example-vpc.id
  }
}

output "tw-vpc" {
    value = twc_vpc.example-vpc.id
}

Выполним команду terraform validate:

D067189e 35ec 4bc3 8060 765d5f9ffb79

Затем terraform plan:

A8ecc713 91cf 44ab 9110 E1fd97806e32

И terraform apply:

41ef13cf F6e3 42c9 B98b 0ceacdb3b9dd

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

Проверка и использование состояния

В панели управления можно проверить наличие файла состояния в бакете:

Image7

Теперь попробуем использовать сохранённое состояние в другой конфигурации. 

Добавим новую папку remote-state:

mkdir remote-state
cd remote-state

Добавим файл remote-state.tf и заполним его следующим образом:

terraform {
  required_providers {
    twc = {
      source = "tf.timeweb.cloud/timeweb-cloud/timeweb-cloud"
    }
  }
  required_version = ">= 1.5.3"
}

provider "twc" {
  token = "<your token>"
}

data "terraform_remote_state" "vpc" {
  backend = "s3"
    config = {
    endpoint = "s3.timeweb.com"
    region = "ru-1"
    bucket = "<bucket name>"
    key  = "states/terraform.tfstate"
    skip_region_validation = true
    skip_credentials_validation = true
    access_key = "<your access key>"
    secret_key = "<your secret key>"
    }
}

data "twc_os" "example-os" {
  name = "ubuntu"
  version = "22.04"
}

data "twc_presets" "example-preset" {
  price_filter {
    from = 300
    to = 400
  }
}

resource "twc_server" "example-server-with-local-network" {
  name = "Example server with local network"
  os_id = data.twc_os.example-os.id
  preset_id = data.twc_presets.example-preset.id

  local_network {
    id = data.terraform_remote_state.vpc.outputs.tw-vpc
  }
}

В этом примере мы используем outputs из предыдущего файла main.tf для получения идентификатора локальной сети, и добавляем в эту сеть новый VPS.

Выполним команды:

  • terraform init
  • terraform validate
  • terraform plan 
  • terraform apply

Будет создан второй сервер в нужной локальной сети:

Image4

Чтобы удалить созданные ресурсы, выполните команду terraform destroy сначала во второй конфигурации, а затем в первой.

Полезные ссылки

Была ли статья полезна?

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