Провайдером в Terraform может быть не только облако. Любой сервис или инструмент может быть реализован в виде провайдера, если есть подходящее HTTP API. Так через Terraform можно управлять мессенджерами, Docker, кластером Kubernetes, DNS, настройкой алертов в системах мониторинга и многим другим. Ниже пример алерта для мониторинга в сервисе DataDog:
resource "datadog_monitor" "foo" {
name = "Name for monitor foo"
type = "metric alert"
message = "Monitor triggered. Notify: @hipchat-channel"
escalation_message = "Escalation message @pagerduty"
query = "avg(last_1h):avg:aws.ec2.cpu{environment:foo,host:foo} by {host} > 4"
monitor_thresholds {
warning = 2
warning_recovery = 1
critical = 4
critical_recovery = 3
}
}
Terraform постепенно превратился в универсальный инструмент управления сервисами и многими инструментами, такими как, Kubernetes. Практически все, что имеет подходящее HTTP API, может быть добавлено в Terraform.
Архитектура
Для лучшего понимания того, как применять Terraform в разных ситуациях, нужно немного посмотреть на то как он работает и почему он работает.
Высокоуровнево работа Terraform выглядит просто. Мы описываем нужные нам ресурсы в виде кода, а он выполняет необходимые HTTP-запросы, для создания этих ресурсов. А что в случае удаления или модификации ресурсов? Как Terraform понимает что ресурс уже есть и его нужно модифицировать, а не создавать заново? И здесь в игру вступает главная особенность Terraform - контроль состояния уже созданных ресурсов.
После добавления нового ресурса, Terraform записывает информацию о нем в файл terraform.tfstate. Информация о том, что из себя представляет текущая инфраструктура, называется состоянием. Главная задача состояния, соотносить ресурсы описанные в Terraform с реальной инфраструктурой.
{
"version": 4,
"terraform_version": "1.1.7",
"serial": 4,
"lineage": "8fe92982-746c-4949-3dc9-df002ccc8a59",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "hcloud_server",
"name": "devops-example-app",
"provider": "provider[\"registry.terraform.io/hetznercloud/hcloud\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"backups": false,
"datacenter": "hel1-dc2",
"delete_protection": false,
"id": "18500771",
"image": "docker-ce",
"ipv6_network": "2a01:4f9:c010:eaa9::/64",
"location": "hel1",
"name": "devops-example-app",
"server_type": "cx11",
"ssh_keys": [
"c66_92dfbc9c0eebec890868a1c4cb98977a",
"c66_8ea2516260858e697f3c80dbe578657b",
],
"status": "running",
},
"dependencies": [
"data.hcloud_ssh_keys.all_keys"
]
}
]
}
]
}
Затем, когда ресурс изменяется, Terraform сравнивает, что было и что нужно было получить. На основе этого строит план, по которому видно, как ресурсы будут изменяться, что придется добавить, изменить или удалить. И если план нас устраивает, то Terraform формирует и выполняет HTTP-запросы в API нужного сервиса или инструмента. Как только изменения сделаны, они отражаются на файле с состоянием.
Во время построения плана, Terraform сверяет состояние в файле с реальной инфраструктурой и обновляет его в случае расхождения. Это сделано на случай, если кто-то изменит инфраструктуру в обход Terraform, что считается плохой практикой. Если какой-то ресурс попал под контроль Terraform, то его изменение должно идти только через Terraform.
С другой стороны, Terraform не отслеживает ресурсы, которые были добавлены в обход. Если создать сервер руками, то Terraform его проигнорирует.
Изменение и удаление ресурсов
Благодаря наличию состояния, Terraform сам определяет как произвести изменения. Для удаления ресурса из инфраструктуры, достаточно удалить его описание из Terraform, для изменения - достаточно поменять его описание.
Изменение работает чуть сложнее. Некоторые изменения требуют пересоздания ресурса, другие нет. Это может быть связано как с физическими ограничениями, например сменой машины на более мощную, так и с ограничениями API, конкретного сервиса. Очень важно следить за этим в плане, иначе можно случайно удалить ресурс, который удалять ни в коем случае нельзя.
Но бывает и наоборот, Terraform может и пытается обновить ресурс без пересоздания, когда мы хотим пересоздания. В такой ситуации поможет команда terraform taint
, которая указывает на ресурс, требующий пересоздания:
# <address> - это адрес ресурса в конфигурации
# например hcloud_server.devops-example-app
terraform taint [options] <address>
Список всех ресурсов и их адресов можно посмотреть командой terraform state list
terraform state list
data.hcloud_ssh_keys.all_keys
hcloud_server.devops-example-app
Импортирование ресурсов
Terraform может внедряться в проект, в котором часть или вся инфраструктура уже была создана до его внедрения. В таком случае возникает задача переноса ресурса внутрь без его удаления. В terraform для этого есть механизм импорта ресурсов. В документации каждого ресурса, в самом конце показана команда, с помощью которой можно добавить существующий ресурс в Terraform. Ниже пример с виртуальной машиной:
# Виртуальная машина импортируется по id, который можно получить в интерфейсе Yandex Cloud
terraform import yandex_compute_instance.default 12342345345
Эта команда ничего не меняет в самом Yandex Cloud. С ее помощью Terraform извлекает информацию о ресурсе по API и добавляет ее в файл с состоянием.
Самостоятельная работа
-
С помощью Terraform опишите конфигурацию сервера для любого вашего приложения. Используйте любое облако на своё усмотрение. Это может быть как DigitalOcean, так и, например, Yandex Cloud.
-
Запушьте изменения на гитхаб
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.