HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-26
1 <p>Когда мы используем подход "инфраструктура как код", мы стремимся описывать кодом все инфраструктурные решения. В идеале вся наша облачная инфраструктура должна быть описана в Terraform. Тогда мы сможем легко управлять зависимостями ресурсов друг от друга.</p>
1 <p>Когда мы используем подход "инфраструктура как код", мы стремимся описывать кодом все инфраструктурные решения. В идеале вся наша облачная инфраструктура должна быть описана в Terraform. Тогда мы сможем легко управлять зависимостями ресурсов друг от друга.</p>
2 <p>На практике такое возможно не всегда. Например, можно прийти к использованию Terraform, когда на проекте уже развернута работающая инфраструктура в облаке. Мигрировать ее в Terraform будет трудозатратно - потребуется описать в Terraform все компоненты с актуальными параметрами, а затем импортировать каждый компонент в состояние Terraform.</p>
2 <p>На практике такое возможно не всегда. Например, можно прийти к использованию Terraform, когда на проекте уже развернута работающая инфраструктура в облаке. Мигрировать ее в Terraform будет трудозатратно - потребуется описать в Terraform все компоненты с актуальными параметрами, а затем импортировать каждый компонент в состояние Terraform.</p>
3 <p>Если мы не мигрируем старую инфраструктуру, нам нужно научить взаимодействовать новую инфраструктуру, описанную в Terraform, со старой. Например, у нас в облаке уже есть кластер баз данных, и мы хотим обеспечить доступ к нему с новых серверов, которые создаем через Terraform:</p>
3 <p>Если мы не мигрируем старую инфраструктуру, нам нужно научить взаимодействовать новую инфраструктуру, описанную в Terraform, со старой. Например, у нас в облаке уже есть кластер баз данных, и мы хотим обеспечить доступ к нему с новых серверов, которые создаем через Terraform:</p>
4 <p>Terraform видит только те ресурсы, которые сам создал в рамках проекта. Чтобы получить информацию о кластере баз данных, созданном снаружи проекта, нам потребуется отдельный инструмент - источник данных.</p>
4 <p>Terraform видит только те ресурсы, которые сам создал в рамках проекта. Чтобы получить информацию о кластере баз данных, созданном снаружи проекта, нам потребуется отдельный инструмент - источник данных.</p>
5 <p>В этом уроке мы познакомимся с источниками данных и выясним, какие проблемы они решают. Также мы научимся использовать их для получения информации о внешней инфраструктуре.</p>
5 <p>В этом уроке мы познакомимся с источниками данных и выясним, какие проблемы они решают. Также мы научимся использовать их для получения информации о внешней инфраструктуре.</p>
6 <p><strong>Data source</strong>в Terraform - это способ получать актуальную информацию о состоянии существующих облачных ресурсов. Мы можем описывать в проекте источники, чтобы обращаться к чему-то, что не создано и не управляется в проекте Terraform.</p>
6 <p><strong>Data source</strong>в Terraform - это способ получать актуальную информацию о состоянии существующих облачных ресурсов. Мы можем описывать в проекте источники, чтобы обращаться к чему-то, что не создано и не управляется в проекте Terraform.</p>
7 <p>Например, с помощью источников мы можем получить информацию о конкретном образе виртуальной машины из каталога облака. Или узнать внешний IP виртуальной машины, чтобы создать под него DNS-запись.</p>
7 <p>Например, с помощью источников мы можем получить информацию о конкретном образе виртуальной машины из каталога облака. Или узнать внешний IP виртуальной машины, чтобы создать под него DNS-запись.</p>
8 <p>Разберем, почему мы не можем все описать ресурсами Terraform:</p>
8 <p>Разберем, почему мы не можем все описать ресурсами Terraform:</p>
9 <ul><li>Есть старая облачная инфраструктура, которую мы пока не готовы мигрировать в Terraform</li>
9 <ul><li>Есть старая облачная инфраструктура, которую мы пока не готовы мигрировать в Terraform</li>
10 <li>Некоторыми ресурсами управляет сам провайдер. Они не могут быть описаны в вашей инфраструктуре как ресурсы</li>
10 <li>Некоторыми ресурсами управляет сам провайдер. Они не могут быть описаны в вашей инфраструктуре как ресурсы</li>
11 <li>Облако и его Terraform-провайдер развиваются несинхронно. В облаке могут реализовать новый нужный инструмент, а ресурс для него в Terraform может появиться только через месяц. Сначала мы подключаем инструмент, а его описание в коде происходит позже</li>
11 <li>Облако и его Terraform-провайдер развиваются несинхронно. В облаке могут реализовать новый нужный инструмент, а ресурс для него в Terraform может появиться только через месяц. Сначала мы подключаем инструмент, а его описание в коде происходит позже</li>
12 <li>Если строить сложную инфраструктуру, можно использовать несколько проектов Terraform. Их ресурсы будут управляться независимо друг от друга, но при этом они должны взаимодействовать друг с другом</li>
12 <li>Если строить сложную инфраструктуру, можно использовать несколько проектов Terraform. Их ресурсы будут управляться независимо друг от друга, но при этом они должны взаимодействовать друг с другом</li>
13 </ul><p>Источники данных в большинстве таких ситуаций играют роль связующих звеньев. Они позволяют инфраструктуре взаимодействовать с окружающим миром.</p>
13 </ul><p>Источники данных в большинстве таких ситуаций играют роль связующих звеньев. Они позволяют инфраструктуре взаимодействовать с окружающим миром.</p>
14 <p>Далее рассмотрим простой и частый сценарий, в котором может использоваться источник данных.</p>
14 <p>Далее рассмотрим простой и частый сценарий, в котором может использоваться источник данных.</p>
15 <h2>Получаем id образа виртуальной машины</h2>
15 <h2>Получаем id образа виртуальной машины</h2>
16 <p>Начнем с<a>источника данных</a>, который предоставит информацию об образе Ubuntu 22.04 из библиотеки Yandex Cloud. Образы в большинстве облаков относятся к ресурсам, которыми управляет сам провайдер:</p>
16 <p>Начнем с<a>источника данных</a>, который предоставит информацию об образе Ubuntu 22.04 из библиотеки Yandex Cloud. Образы в большинстве облаков относятся к ресурсам, которыми управляет сам провайдер:</p>
17 <p>Это стандартный для Terraform формат описания источника данных. Мы обозначаем источник ключевым словом data, далее в кавычках пишем "yandex_compute_image" - тип источника из спецификации провайдера. Дальше указываем имя "img", по которому ресурсы и другие объекты смогут обращаться к источнику.</p>
17 <p>Это стандартный для Terraform формат описания источника данных. Мы обозначаем источник ключевым словом data, далее в кавычках пишем "yandex_compute_image" - тип источника из спецификации провайдера. Дальше указываем имя "img", по которому ресурсы и другие объекты смогут обращаться к источнику.</p>
18 <p>При выполнении terraform apply Terraform обратится к облаку и попытается найти образ по заданному ключу. В нашем случае он будет искать образ из семейства<em>ubuntu-2204-lts</em>. Если он найдет его, то сохранит найденную информацию в объект data. После этого инфраструктура Terraform сможет использовать ее.</p>
18 <p>При выполнении terraform apply Terraform обратится к облаку и попытается найти образ по заданному ключу. В нашем случае он будет искать образ из семейства<em>ubuntu-2204-lts</em>. Если он найдет его, то сохранит найденную информацию в объект data. После этого инфраструктура Terraform сможет использовать ее.</p>
19 <p>Посмотрим, что сохранил Terraform в источник. Для этого воспользуемся блоком<em>output</em>:</p>
19 <p>Посмотрим, что сохранил Terraform в источник. Для этого воспользуемся блоком<em>output</em>:</p>
20 <p>Мы передали в value полное содержимое источника img. Чтобы обратиться к содержимому источника данных, мы используем конструкцию data.&lt;TYPE&gt;.&lt;NAME&gt;, где:</p>
20 <p>Мы передали в value полное содержимое источника img. Чтобы обратиться к содержимому источника данных, мы используем конструкцию data.&lt;TYPE&gt;.&lt;NAME&gt;, где:</p>
21 <ul><li>TYPE - тип источника данных</li>
21 <ul><li>TYPE - тип источника данных</li>
22 <li>NAME - имя источника</li>
22 <li>NAME - имя источника</li>
23 </ul><p>Запустим terraform apply, не подтверждая выполнение, и посмотрим, что происходит:</p>
23 </ul><p>Запустим terraform apply, не подтверждая выполнение, и посмотрим, что происходит:</p>
24 <p>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.</p>
24 <p>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.</p>
25 <p>Еще до применения изменений Terraform сходил в облако, нашел ресурс образа с заданным значением family и сохранил информацию о нем. Мы можем обращаться к полям источника в ресурсах, используя конструкцию вида data.&lt;TYPE&gt;.&lt;NAME&gt;.&lt;FIELD&gt;.</p>
25 <p>Еще до применения изменений Terraform сходил в облако, нашел ресурс образа с заданным значением family и сохранил информацию о нем. Мы можем обращаться к полям источника в ресурсах, используя конструкцию вида data.&lt;TYPE&gt;.&lt;NAME&gt;.&lt;FIELD&gt;.</p>
26 <p>Например, мы можем передать виртуальной машине id образа из нашего источника img таким образом:</p>
26 <p>Например, мы можем передать виртуальной машине id образа из нашего источника img таким образом:</p>
27 <p>В данном случае мы достаем из источника data.yandex_compute_image.img значение id, которое он получил в момент запуска команды terraform apply.</p>
27 <p>В данном случае мы достаем из источника data.yandex_compute_image.img значение id, которое он получил в момент запуска команды terraform apply.</p>
28 <p>Так источник данных помог привязать инфраструктуру Terraform к объекту, который существует снаружи.</p>
28 <p>Так источник данных помог привязать инфраструктуру Terraform к объекту, который существует снаружи.</p>
29 <p>Теперь разберем сценарий, описанный в начале урока. Попробуем подключить новые виртуальные машины к существующему в облаке кластеру баз данных.</p>
29 <p>Теперь разберем сценарий, описанный в начале урока. Попробуем подключить новые виртуальные машины к существующему в облаке кластеру баз данных.</p>
30 <h2>Пример с базой данных</h2>
30 <h2>Пример с базой данных</h2>
31 <p>Рассмотрим практический пример с кластером баз данных. Допустим, у нас в облаке уже развернут кластер БД с именем<em>postgresql14</em>. Мы воспользуемся источником данных, чтобы узнать, как к нему подключаться. Далее передадим информацию об этом новому виртуальному серверу.</p>
31 <p>Рассмотрим практический пример с кластером баз данных. Допустим, у нас в облаке уже развернут кластер БД с именем<em>postgresql14</em>. Мы воспользуемся источником данных, чтобы узнать, как к нему подключаться. Далее передадим информацию об этом новому виртуальному серверу.</p>
32 <p>Опишем источник данных, который извлечет информацию о кластере:</p>
32 <p>Опишем источник данных, который извлечет информацию о кластере:</p>
33 <p>Источник типа yandex_mdb_postgresql_cluster возвращает сложную структуру данных. С ней можно ознакомиться в<a>документации источника</a>либо вывести содержимое источника с помощью output, как делали выше.</p>
33 <p>Источник типа yandex_mdb_postgresql_cluster возвращает сложную структуру данных. С ней можно ознакомиться в<a>документации источника</a>либо вывести содержимое источника с помощью output, как делали выше.</p>
34 <p>Нам сейчас не нужна вся структура, а нужно конкретное поле data.yandex_mdb_postgresql_cluster.dbcluster.host.0.fqdn. Оно содержит имя хоста для подключения к кластеру.</p>
34 <p>Нам сейчас не нужна вся структура, а нужно конкретное поле data.yandex_mdb_postgresql_cluster.dbcluster.host.0.fqdn. Оно содержит имя хоста для подключения к кластеру.</p>
35 <p>Возьмем у кластера имя для подключения и добавим его в переменные окружения новой создаваемой в Terraform виртуальной машины:</p>
35 <p>Возьмем у кластера имя для подключения и добавим его в переменные окружения новой создаваемой в Terraform виртуальной машины:</p>
36 <p>В user-data с помощью конструкции EOF мы описали bash-скрипт, который при запуске виртуальной машины добавит строку export DB_HOST=&lt;путь к Managed DB&gt; в /etc/environment.</p>
36 <p>В user-data с помощью конструкции EOF мы описали bash-скрипт, который при запуске виртуальной машины добавит строку export DB_HOST=&lt;путь к Managed DB&gt; в /etc/environment.</p>
37 <p>Имена переменных и логические конструкции Terraform внутри скрипта мы оборачиваем в ${...}. Так мы используем интерполяцию, чтобы Terraform до выполнения операций получил значения data.yandex_mdb_postgresql_cluster.dbcluster.host.0.fqdn и file("~/.ssh/id_rsa.pub") и сконвертировал их в строки.</p>
37 <p>Имена переменных и логические конструкции Terraform внутри скрипта мы оборачиваем в ${...}. Так мы используем интерполяцию, чтобы Terraform до выполнения операций получил значения data.yandex_mdb_postgresql_cluster.dbcluster.host.0.fqdn и file("~/.ssh/id_rsa.pub") и сконвертировал их в строки.</p>
38 <p>В итоге после запуска в env сервера будет переменная DB_HOST, которую он сможет использовать для подключения приложения к кластеру БД:</p>
38 <p>В итоге после запуска в env сервера будет переменная DB_HOST, которую он сможет использовать для подключения приложения к кластеру БД:</p>
39 <p>При этом источник данных будет всегда предоставлять скрипту актуальную информацию. Даже если в какой-то момент мы удалим кластер postgresql14 и создадим новый с таким же именем, нам ничего не потребуется менять в коде Terraform. Источник данных dbcluster будет по имени получать актуальную информацию о новом кластере.</p>
39 <p>При этом источник данных будет всегда предоставлять скрипту актуальную информацию. Даже если в какой-то момент мы удалим кластер postgresql14 и создадим новый с таким же именем, нам ничего не потребуется менять в коде Terraform. Источник данных dbcluster будет по имени получать актуальную информацию о новом кластере.</p>
40 <h2>Выводы</h2>
40 <h2>Выводы</h2>
41 <p>Источники данных - это необходимый инструмент, если управлять инфраструктурой через Terraform приходится только частично, а другая часть инфраструктуры недоступна для управления.</p>
41 <p>Источники данных - это необходимый инструмент, если управлять инфраструктурой через Terraform приходится только частично, а другая часть инфраструктуры недоступна для управления.</p>
42 <p>Каждый провайдер Terraform предоставляет перечень источников данных, которые можно использовать для получения информации о ресурсах провайдера. Если у нужного нам объекта есть Terraform-провайдер и соответствующий источник данных, мы можем при выполнении операций Terraform запрашивать информацию об этом объекте и использовать ее в настройке нашей инфраструктуры.</p>
42 <p>Каждый провайдер Terraform предоставляет перечень источников данных, которые можно использовать для получения информации о ресурсах провайдера. Если у нужного нам объекта есть Terraform-провайдер и соответствующий источник данных, мы можем при выполнении операций Terraform запрашивать информацию об этом объекте и использовать ее в настройке нашей инфраструктуры.</p>
43 <p>Так мы можем получать информацию о виртуальных машинах, кластерах БД, сетях, DNS-записях и других ресурсах, которые не описаны в нашем проекте Terraform.</p>
43 <p>Так мы можем получать информацию о виртуальных машинах, кластерах БД, сетях, DNS-записях и других ресурсах, которые не описаны в нашем проекте Terraform.</p>
44 <p>Область применения источников данных этим не ограничена. Например, существуют специальные источники данных, которые могут использовать для получения информации сторонние<em>tfstate</em>. Есть источники данных, которые умеют работать с локальными файлами и архивами. С помощью источников данных вполне возможно организовать управление секретами Terraform.</p>
44 <p>Область применения источников данных этим не ограничена. Например, существуют специальные источники данных, которые могут использовать для получения информации сторонние<em>tfstate</em>. Есть источники данных, которые умеют работать с локальными файлами и архивами. С помощью источников данных вполне возможно организовать управление секретами Terraform.</p>
45 <p>Главное в источниках данных - они позволяют в проекте Terraform получать актуальную информацию о состоянии внешних для инфраструктуры объектов и использовать эту информацию в нашей инфраструктуре.</p>
45 <p>Главное в источниках данных - они позволяют в проекте Terraform получать актуальную информацию о состоянии внешних для инфраструктуры объектов и использовать эту информацию в нашей инфраструктуре.</p>