Зарегистрируйтесь, чтобы продолжить обучение

Источники данных Terraform: Основы

Когда мы используем подход «инфраструктура как код», мы стремимся описывать кодом все инфраструктурные решения. В идеале вся наша облачная инфраструктура должна быть описана в Terraform. Тогда мы сможем легко управлять зависимостями ресурсов друг от друга.

На практике такое возможно не всегда. Например, можно прийти к использованию Terraform, когда на проекте уже развернута работающая инфраструктура в облаке. Мигрировать ее в Terraform будет трудозатратно — потребуется описать в Terraform все компоненты с актуальными параметрами, а затем импортировать каждый компонент в состояние Terraform.

Если мы не мигрируем старую инфраструктуру, нам нужно научить взаимодействовать новую инфраструктуру, описанную в Terraform, со старой. Например, у нас в облаке уже есть кластер баз данных, и мы хотим обеспечить доступ к нему с новых серверов, которые создаем через Terraform:

dscase

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

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

Что такое источник данных в Terraform

Data source в Terraform — это способ получать актуальную информацию о состоянии существующих облачных ресурсов. Мы можем описывать в проекте источники, чтобы обращаться к чему-то, что не создано и не управляется в проекте Terraform.

Например, с помощью источников мы можем получить информацию о конкретном образе виртуальной машины из каталога облака. Или узнать внешний IP виртуальной машины, чтобы создать под него DNS-запись.

Разберем, почему мы не можем все описать ресурсами Terraform:

  • Есть старая облачная инфраструктура, которую мы пока не готовы мигрировать в Terraform
  • Некоторыми ресурсами управляет сам провайдер. Они не могут быть описаны в вашей инфраструктуре как ресурсы
  • Облако и его Terraform-провайдер развиваются несинхронно. В облаке могут реализовать новый нужный инструмент, а ресурс для него в Terraform может появиться только через месяц. Сначала мы подключаем инструмент, а его описание в коде происходит позже
  • Если строить сложную инфраструктуру, можно использовать несколько проектов Terraform. Их ресурсы будут управляться независимо друг от друга, но при этом они должны взаимодействовать друг с другом

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

Далее рассмотрим простой и частый сценарий, в котором может использоваться источник данных.

Получаем id образа виртуальной машины

Начнем с источника данных, который предоставит информацию об образе Ubuntu 22.04 из библиотеки Yandex Cloud. Образы в большинстве облаков относятся к ресурсам, которыми управляет сам провайдер:

data "yandex_compute_image" "img" {
  family = "ubuntu-2204-lts"
}

Это стандартный для Terraform формат описания источника данных. Мы обозначаем источник ключевым словом data, далее в кавычках пишем "yandex_compute_image" — тип источника из спецификации провайдера. Дальше указываем имя "img", по которому ресурсы и другие объекты смогут обращаться к источнику.

При выполнении terraform apply Terraform обратится к облаку и попытается найти образ по заданному ключу. В нашем случае он будет искать образ из семейства ubuntu-2204-lts. Если он найдет его, то сохранит найденную информацию в объект data. После этого инфраструктура Terraform сможет использовать ее.

Посмотрим, что сохранил Terraform в источник. Для этого воспользуемся блоком output:

output "show-img" {
  value = data.yandex_compute_image.img
}

Мы передали в value полное содержимое источника img. Чтобы обратиться к содержимому источника данных, мы используем конструкцию data.<TYPE>.<NAME>, где:

  • TYPE — тип источника данных
  • NAME — имя источника

Запустим terraform apply, не подтверждая выполнение, и посмотрим, что происходит:

data.yandex_compute_image.img: Reading...
data.yandex_compute_image.img: Read complete after 0s [id=fd8k3a6rj9okseiqrl3k]

Changes to Outputs:
  + show-img = {
      + created_at    = "2023-05-29T10:50:23Z"
      + description   = "ubuntu 22.04 lts"
      + family        = "ubuntu-2204-lts"
      + folder_id     = "standard-images"
      + id            = "fd8k3a6rj9okseiqrl3k"
      + image_id      = "fd8k3a6rj9okseiqrl3k"
      + name          = "ubuntu-22-04-lts-v20230529"
      + os_type       = "linux"
      ...
    }

You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.

Еще до применения изменений Terraform сходил в облако, нашел ресурс образа с заданным значением family и сохранил информацию о нем. Мы можем обращаться к полям источника в ресурсах, используя конструкцию вида data.<TYPE>.<NAME>.<FIELD>.

Например, мы можем передать виртуальной машине id образа из нашего источника img таким образом:

resource "yandex_compute_instance" "vm" {
  name        = "test"
  ...
  boot_disk {
    initialize_params {
      image_id = data.yandex_compute_image.img.id
    }
  }
  ...
}

В данном случае мы достаем из источника data.yandex_compute_image.img значение id, которое он получил в момент запуска команды terraform apply.

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

Теперь разберем сценарий, описанный в начале урока. Попробуем подключить новые виртуальные машины к существующему в облаке кластеру баз данных.

Пример с базой данных

Рассмотрим практический пример с кластером баз данных. Допустим, у нас в облаке уже развернут кластер БД с именем postgresql14. Мы воспользуемся источником данных, чтобы узнать, как к нему подключаться. Далее передадим информацию об этом новому виртуальному серверу.

Опишем источник данных, который извлечет информацию о кластере:

data "yandex_mdb_postgresql_cluster" "dbcluster" {
  name = "postgresql14"
}

Источник типа yandex_mdb_postgresql_cluster возвращает сложную структуру данных. С ней можно ознакомиться в документации источника либо вывести содержимое источника с помощью output, как делали выше.

Нам сейчас не нужна вся структура, а нужно конкретное поле data.yandex_mdb_postgresql_cluster.dbcluster.host.0.fqdn. Оно содержит имя хоста для подключения к кластеру.

Возьмем у кластера имя для подключения и добавим его в переменные окружения новой создаваемой в Terraform виртуальной машины:

resource "yandex_compute_instance" "vm" {
  ...

  metadata = {
    user-data = <<-EOF
    #!/bin/bash
    echo 'export DB_HOST="${data.yandex_mdb_postgresql_cluster.dbcluster.host.0.fqdn}"' >> /etc/environment
    EOF

    ssh-keys = "ubuntu:${file("~/.ssh/id_rsa.pub")}"
  }
}

В user-data с помощью конструкции EOF мы описали bash-скрипт, который при запуске виртуальной машины добавит строку export DB_HOST=<путь к Managed DB> в /etc/environment.

Имена переменных и логические конструкции Terraform внутри скрипта мы оборачиваем в ${...}. Так мы используем интерполяцию, чтобы Terraform до выполнения операций получил значения data.yandex_mdb_postgresql_cluster.dbcluster.host.0.fqdn и file("~/.ssh/id_rsa.pub") и сконвертировал их в строки.

В итоге после запуска в env сервера будет переменная DB_HOST, которую он сможет использовать для подключения приложения к кластеру БД:

env

При этом источник данных будет всегда предоставлять скрипту актуальную информацию. Даже если в какой-то момент мы удалим кластер postgresql14 и создадим новый с таким же именем, нам ничего не потребуется менять в коде Terraform. Источник данных dbcluster будет по имени получать актуальную информацию о новом кластере.

Выводы

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

Каждый провайдер Terraform предоставляет перечень источников данных, которые можно использовать для получения информации о ресурсах провайдера. Если у нужного нам объекта есть Terraform-провайдер и соответствующий источник данных, мы можем при выполнении операций Terraform запрашивать информацию об этом объекте и использовать ее в настройке нашей инфраструктуры.

Так мы можем получать информацию о виртуальных машинах, кластерах БД, сетях, DNS-записях и других ресурсах, которые не описаны в нашем проекте Terraform.

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

Главное в источниках данных — они позволяют в проекте Terraform получать актуальную информацию о состоянии внешних для инфраструктуры объектов и использовать эту информацию в нашей инфраструктуре.


Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Для полного доступа к курсу нужен базовый план

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

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»
Изображение Тото

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