Перейти к основному содержимому

Лучшие практики при использовании Terraform

· 8 мин. чтения

1. Обзор

Ранее мы рассмотрели основные понятия и использование Terraform . Теперь давайте углубимся и рассмотрим некоторые из лучших практик использования этого популярного инструмента DevOps.

2. Организация файлов ресурсов

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

Лучший подход — воспользоваться преимуществом того факта, что внутри модуля Terraform прочитает любой файл « .tf » и обработает его содержимое . Порядок, в котором мы объявляем ресурсы в них, не имеет значения — в конце концов, это работа Terraform. Мы должны держать их в порядке, чтобы мы могли лучше понять, что происходит.

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

  • variable.tf : сюда помещаются все входные переменные модуля, а также их значения по умолчанию, если это применимо.
  • main.tf : здесь мы будем размещать определения наших ресурсов. Предполагая, что мы используем принцип единой ответственности , его размер должен оставаться под контролем.
  • модули: если наш модуль содержит какие-либо подмодули, они пойдут сюда .
  • outputs.tf : здесь должны быть экспортированные элементы данных.
  • provider.tf: используется только в каталоге верхнего уровня, объявляет, какие провайдеры мы будем использовать в проекте, включая их версии.

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

Кроме того, по мере развития нашего модуля мы должны следить за размером файла main.tf. Хорошим признаком того, что нам следует подумать о реорганизации его в подмодули, является то, что он начинает увеличиваться в размерах. На этом этапе мы должны реорганизовать его, переместив тесно связанные ресурсы, такие как экземпляр EC2 и подключенный том EBS, во вложенные модули. В конце концов, есть вероятность, что наш файл main.tf верхнего уровня содержит только ссылки на модули, сшитые вместе.

3. Использование модулей

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

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

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

Давайте взглянем на пример макета каталога проекта Terraform, в котором используется этот принцип:

$ tree .
├── main.tf
├── modules
│   ├── ingress
│   │   └── www.petshop.com.br
│   │   ├── main.tf
│   │   ├── outputs.tf
│   │   └── variables.tf
... other services omitted
│   └── SvcFeedback
│   ├── main.tf
│   ├── outputs.tf
│   └── variables.tf
├── outputs.tf
├── terraform.tfvars
└── variables.tf

Здесь мы использовали модули для каждого важного аспекта нашей инфраструктуры: базы данных, входа, обмена сообщениями, внешних служб и серверных служб. В этом макете каждая папка, содержащая файлы .tf , представляет собой модуль, содержащий три файла:

  • variable.tf — Входные переменные для модуля
  • main.tf — определения ресурсов
  • outputs.tf — определения выходных атрибутов

Преимущество этого соглашения заключается в том, что потребители модуля могут сразу перейти к его «контракту» — переменным и выводам — если они хотят, пропуская детали реализации.

4. Конфигурация провайдера

Большинство провайдеров в Terraform требуют, чтобы мы предоставили допустимые параметры конфигурации, чтобы он мог манипулировать ресурсами . Например, провайдеру AWS нужен ключ/секрет доступа и регион, чтобы он мог получить доступ к нашей учетной записи и выполнять задачи.

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

4.1. Использование переменных для настройки поставщика

В этом подходе мы определяем переменную проекта для каждого требуемого параметра поставщика:

variable "aws_region" {
type = string
}
variable "aws_access_key" {
type = string
}a
variable "aws_secret_key" {
type = string
}

Теперь мы используем их в объявлении нашего провайдера :

provider "aws" {
region = var.aws_region
access_key = var.aws_access_key
secret_key = var.aws_secret_key
}

Наконец, мы предоставляем фактические значения, используя файл .tfvar :

aws_access_key="xxxxx"
aws_secret_key="yyyyy"
aws_region="us-east-1"

Мы также можем комбинировать файлы .tfvar и переменные среды при выполнении команд Terraform, таких как plan или apply :

$ export TF_VAR_aws_region="us-east-1"
$ terraform plan -var="access_key=xxxx" -var-file=./aws.tfvars

Здесь мы использовали сочетание переменных среды и аргументов командной строки для передачи значений переменных. Помимо этих источников, Terraform также просматривает переменные, определенные в файле terraform.tfvars и любом файле с расширением « .auto.tfvars» в папке проекта .

4.2. Использование конфигурации для конкретного поставщика

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

5. Государственное управление

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

  • Всегда используйте правило исключения для файлов *.tfstate в нашем файле конфигурации VCS. Для Git это может быть глобальное правило исключения или файл .gitignore нашего проекта.
  • Примите как можно скорее удаленный бэкэнд вместо локального бэкэнда по умолчанию. Кроме того, перепроверьте ограничения доступа к выбранному бэкенду.

Переход от серверной части состояния по умолчанию — локальных файлов — к удаленной — простая задача. Нам просто нужно добавить определение бэкэнда в один из файлов нашего проекта:

terraform {
backend "pg" {}
}

Здесь мы сообщаем Terraform, что он будет использовать серверную часть PostgreSQL для хранения информации о состоянии. Удаленные серверные части обычно требуют дополнительной настройки. Как и у провайдеров, рекомендуемый подход заключается в передаче необходимых параметров через переменные среды или файлы « .auto.tfvars » .

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

Приняв удаленный сервер, мы можем избежать этих проблем, поскольку удаленные серверы поддерживают концепцию блокировки. Это означает, что только один соавтор может по очереди запускать такие команды, как terraform plan или terraform apply .

Еще один способ обеспечить надлежащее управление файлами состояния — использовать выделенный сервер для запуска Terraform . Для этого мы можем использовать любые инструменты CI/CD, такие как Jenkins, GitLab и другие. Для небольших команд/организаций мы также можем использовать бесплатный уровень предложения Terraform SaaS .

6. Рабочие пространства

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

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

Имея это в виду, общепринятой практикой является называть рабочие пространства именами сред . Например, мы можем использовать такие имена, как DEV, QA и PRD, чтобы они соответствовали нашим существующим средам.

Если бы у нас было несколько команд, работающих над одним и тем же проектом, мы могли бы также указать их имена. Например, у нас может быть рабочее пространство DEV-SQUAD1 для команды, работающей над новыми функциями, и DEV-SUPPORT для другой команды, которая будет воспроизводить и исправлять производственные проблемы.

7. Тестирование

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

Типичный тест состоит из развертывания тестовой конфигурации во временной среде и запуска серии тестов для нее . Что должны охватывать тесты? Ну, это во многом зависит от специфики того, что мы создаем, но некоторые из них довольно распространены:

  • Доступность: правильно ли мы создали наши ресурсы? Достижимы ли они?
  • Безопасность. Оставили ли мы открытыми несущественные сетевые порты? Мы отключили учетные данные по умолчанию?
  • Корректность: правильно ли наш модуль использовал свои параметры? Отметил ли он какие-либо отсутствующие параметры?

На момент написания этой статьи тестирование Terraform все еще остается развивающейся темой. Мы можем писать наши тесты, используя любой фреймворк, который захотим, но те, которые ориентированы на интегрированные тесты, как правило, лучше подходят для этой задачи . Некоторые примеры включают , среди прочего , FitNesse , Spock и Protractor . Мы также можем создавать наши тесты, используя обычные сценарии оболочки, и добавлять их в наш конвейер CI/CD.

8. Заключение

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

Как обычно, весь код доступен на GitHub .