Основы Terraform
Управление распределенной архитектурой требует значительных трудозатрат и финансовых вложений. Для автоматизации этого процесса можно использовать различные самописные скрипты, но лучше воспользоваться готовыми решениями с открытым исходным кодом. Одним из наиболее известных решений для автоматизации управления инфраструктурой является Terraform. Это Open source решение для управления IaC от компании Hashicorp, разработанное в 2014 году. Решение придерживается декларативного стиля управления инфраструктурой, то есть, вы описываете в конфигурационном файле финальное состояние инфраструктуры, а Terraform приводит её к этому состоянию. В качестве примера можно привести автоматическое развертывание пула виртуальных машин, например для проведения обучения работе с каким-либо ПО.
Ручное создание пары десятков виртуалок может занять целый день, а с помощью Terraform это займет менее часа.
Для того, чтобы описание работы с Terraform не было «сферическим конем в вакууме», мы в качестве наглядного примера, рассмотрим практический пример создания экземпляра EC2 в AWS.
Язык HCL
Для автоматизации работы с инфраструктурой Terraform использует собственный язык написания конфигурационных файлов Hashicorp Configuration Language (HCL). По сути, этот язык описывает желаемое состояние инфраструктуры в конфигурационном файле.
Сначала немного поговорим о синтаксисе языка HCL. Для описания того или иного создаваемого элемента необходимо подготовить блок, содержащий заключенные в фигурных скобках названия переменных, и их значения, передаваемые функциям.
Как и в большинстве языков программирования, в HCL используются аргументы для присвоения значений переменным. В Terraform эти переменные являются атрибутами, связанными с определенным типом блока. Таким образом, весь код HCL состоит из подобных блоков.
Приступим к написанию конфигурационного файла. В первой строке файла мы указываем слово terraform. Хотя этот параметр считается необязательным, настоятельно рекомендуется его указывать. Далее идет открывающая фигурная скобка. Соответственно в последней строке конфигурационного файла должна быть закрывающая скобка.
Например:
terraform {
…
}
А блок кода может иметь следующий вид:
provider "aws” {
region = "us-west-1”
}
А синтаксически правильный, хотя и практически бесполезный вариант всего конфига будет иметь следующий вид:
terraform {
provider "aws” {
region = "us-west-1”
}
}
Вот собственно и все, что нам необходимо знать о синтаксисе HCL. Далее немного поговорим о том, как построено хранение конфигурационных файлов в Terraform.
Хранение файлов
Все конфигурационные файлы Terraform должны размещаться в одном каталоге. Так, для того примера, который мы будем рассматривать далее мы можем создать каталог под названием EC2. По умолчанию Terraform предполагает, что все файлы с .tf*расширениями в данном каталоге являются частью конфигурации, независимо от имен файлов.
Для грамотной организации больших конфигурации потребуются три файла:
variables.tf — для всех объявленных входных переменных.
provider.tf — для объявленных поставщиков, которых вы используете.
main.tf — для объявления фактических ресурсов, которые будут созданы.
Однако, такая структура не является обязательной. Мы можем поместить весь наш код в один файл и все будет корректно работать. В рамках примера из сегодняшней статьи мы будем использовать только main.tf.
Далее перейдем к рассмотрению смысловых составляющих кода, то есть к наполнению файлов кодом.
Простой пример
Итак, напомню, наша задача развернуть экземпляр EC2 в облаке AWS. В рамках этой статьи мы будем разворачивать экземпляр только с базовыми настройками. Для более глубокого погружения у нас будет следующая статья.
Теперь давайте подробнее поговорим о том, как подготовить необходимые конфигурационные данные. Прежде всего, нам необходимо определиться с теми провайдерами, которых мы будем использовать. Поскольку мы собираемся развернуть экземпляр EC2 на AWS, нам нужно объявить необходимых поставщиков:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
В первой строке, напомним, мы открываем блок terraform, который хотя и не является обязательным с точки зрения синтаксиса системы, но рекомендуется его указывать, особенно когда вы создаете инфраструктуру на удаленной системе.
Вложенный блок required providers, определяет требуемых провайдеров. Нам потребуется поставщик aws с указанными параметрами source и version.
Несколько слов о провайдерах и их взаимодействии с Terraform. Для того, чтобы Terraform поддерживал ту или иную технологию, на серверах Terraform должен быть установлен плагин от соответствующего провайдера, содержащий собственный набор конфигураций, типов ресурсов и источников данных. Здесь можно провести некоторые аналогии с библиотеками в языках высокого уровня.
Далее у нас идет описание самого провайдера, аналогичное примеру, представленному в начале статьи. В поле region мы указываем желаемый регион.
provider "aws" {
region = "us-west-1”
}
Значение имеет строковый тип, поэтому оно заключено в пару двойных кавычек (»). Плагин провайдера содержит набор ресурсов, которые мы можем использовать в своей конфигурации. В нашем примере провайдер aws предоставляет ресурс aws_instance, с помощью которого мы создаем экземпляр с именем myec2.
resource "aws_instance” "myec2” {
ami = "ami-00831fc7c1e3ddc60”
instance_type = "t2.micro”
}
Далее нам необходимо заполнить атрибуты, используемые ресурсом aws_instance. Первый атрибут — ami это идентификатор образа машины Amazon для экземпляра EC2. Второй атрибут instance_type — это атрибут, который определяет размер создаваемой машины. В рамках данной статьи мы не будем подробно рассматривать тему значений экземпляров, отметим лишь, что t2.micro является наиболее дешевым вариантом (надеюсь вы помните, что в облаках за каждый запущенный экземпляр виртуалки нужно платить) для экспериментов с облачными решениями.
С базовыми настройками ресурса мы закончили. Но сейчас мы «приколотили» значения жестко, а для полноценного использования Terraform лучше использовать переменные. Давайте их объявим для тех блоков, которые мы уже рассмотрели.
variable "region" {
default = "us-west-1"
description = "AWS Region"
}
variable "ami" {
default = "ami-00831fc7c1e3ddc60"
description = "Amazon Machine Image ID for Ubuntu Server 20.04"
}
variable "type" {
default = "t2.micro"
description = "Size of VM"
}
Мы объявили три переменные region, ami и type. Теперь мы применим значения этих переменных в нашем конфигурационном файле. На значения переменных можно ссылаться с помощью var.
.
Но Terraform позволяет не только присваивать значения переменным, но и получать значения, после преобразований, с помощью функции output.
Соберем нашу конфигурацию в виде единого файла main.tf
.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 3.0"
}
}
}
provider "aws" {
region = var.region
}
variable "region" {
default = "us-west-1"
description = "AWS Region"
}
variable "ami" {
default = "ami-00831fc7c1e3ddc60"
description = "Amazon Machine Image ID for Ubuntu Server 20.04"
}
variable "type" {
default = "t2.micro"
description = "Size of VM"
}
resource "aws_instance" "myec2" {
ami = var.ami
instance_type = var.type
tags = {
name = "Demo System"
}
}
output "instance_id" {
instance = aws_instance.demo.id
}
Сохраним данную конфигурацию в файле и перейдем к выполнению команд для работы с Terraform.
Три основные команды
Перед началом применения нашей конфигурации необходимо инициализировать провайдера и установить плагин AWS. Это можно сделать с помощью команды:
terraform init
Результатом успешного выполнения команды является сообщение об успешной инициализации, аналогичное приведенному на рисунке.
После этого нам необходимо произвести валидацию подготовленного ранее конфигурационного файла. За выполнение этой задачи отвечает команда
terraform plan
В случае, если валидация прошла успешно и никаких ошибок выявлено не было, мы можем применить нашу конфигурацию с помощью команды
terraform apply
Результатом успешного выполнения этой команды будет создание экземпляра EC2 в облаке Amazon.
Заключение
Как видно, работать с кодом в инфраструктуре IaC не слишком сложно. Однако сегодня мы рассмотрели только базовый пример создания экземпляра и многие интересные функции HCL пока остались за кадром.
В следующей статье мы усложним нашу инфраструктуру, наделив нашу создаваемую виртуальную инфраструктуру различными полезными настройками.
Статья подготовлена в преддверии старта курса DevOps практики и инструменты. Узнать подробнее о курсе и зарегистрироваться на бесплатный урок можно по ссылке ниже.