- Что такое источник данных в Terraform
- Получаем id образа виртуальной машины
- Пример с базой данных
- Выводы
Когда мы используем подход «инфраструктура как код», мы стремимся описывать кодом все инфраструктурные решения. В идеале вся наша облачная инфраструктура должна быть описана в Terraform. Тогда мы сможем легко управлять зависимостями ресурсов друг от друга.
На практике такое возможно не всегда. Например, можно прийти к использованию Terraform, когда на проекте уже развернута работающая инфраструктура в облаке. Мигрировать ее в Terraform будет трудозатратно — потребуется описать в Terraform все компоненты с актуальными параметрами, а затем импортировать каждый компонент в состояние Terraform.
Если мы не мигрируем старую инфраструктуру, нам нужно научить взаимодействовать новую инфраструктуру, описанную в Terraform, со старой. Например, у нас в облаке уже есть кластер баз данных, и мы хотим обеспечить доступ к нему с новых серверов, которые создаем через Terraform:
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
, которую он сможет использовать для подключения приложения к кластеру БД:
При этом источник данных будет всегда предоставлять скрипту актуальную информацию. Даже если в какой-то момент мы удалим кластер postgresql14
и создадим новый с таким же именем, нам ничего не потребуется менять в коде Terraform. Источник данных dbcluster
будет по имени получать актуальную информацию о новом кластере.
Выводы
Источники данных — это необходимый инструмент, если управлять инфраструктурой через Terraform приходится только частично, а другая часть инфраструктуры недоступна для управления.
Каждый провайдер Terraform предоставляет перечень источников данных, которые можно использовать для получения информации о ресурсах провайдера. Если у нужного нам объекта есть Terraform-провайдер и соответствующий источник данных, мы можем при выполнении операций Terraform запрашивать информацию об этом объекте и использовать ее в настройке нашей инфраструктуры.
Так мы можем получать информацию о виртуальных машинах, кластерах БД, сетях, DNS-записях и других ресурсах, которые не описаны в нашем проекте Terraform.
Область применения источников данных этим не ограничена. Например, существуют специальные источники данных, которые могут использовать для получения информации сторонние tfstate. Есть источники данных, которые умеют работать с локальными файлами и архивами. С помощью источников данных вполне возможно организовать управление секретами Terraform.
Главное в источниках данных — они позволяют в проекте Terraform получать актуальную информацию о состоянии внешних для инфраструктуры объектов и использовать эту информацию в нашей инфраструктуре.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.