# Terraform
---
## Terraform
- Terraform – это инструмент от компании Hashicorp, помогающий декларативно управлять инфраструктурой.
- Унифицирует работу с различными облачными и виртуальными платформами
- Описание инфраструктуры хранится в конфигурационных .tf файлах
- хранение состояния инфраструктуры (state)
---
## HCL
- JSON-like синтаксис
- Блоки и аргументы
- Переменные
- Функции
- Управляющие конструкции: циклы, условия
---
## С чего начинаем
- минимальная структура файлов
- main.tf
- outputs.tf
- variables.tf
- terraform.tfvars
- terraform init
- безопасно для повтора
- .gitignore
---
## variables.tf
- здесь описываем переменные
```bash
variable "region" {
description = "GCP - Region"
default = "europe-north1"
}
```
---
## terraform.tfvars
- здесь описываются значения переменных
- для каждого деплоя достаточно меня значения здесь
- должен быть в .gitignore
---
## основные команды
- terraform init
- terraform plan
- terraform apply
- terraform output
- terraform destroy
---
## Провайдеры
- провайдер - это плагин который добавляет в терраформ набор ресурсов и источников данных
- может использоваться несколько провайдеров одновременно
- для конкретного ресурса или модуля можно указывать мета-аругмент `provider`
---
## Провайдеры
- может использовать один провайдер под разными алиасами для разных
* провайдер без алиаса является конфигурацией по умолчанию для данного провайдера
- можно указывать требования по конкретным провайдерам и их версиям
* текущая версия и ее патчи
* указание минимально разрешенной версии
---
## provider
```
provider "aws" {
region = "us-east-1"
}
provider "aws" {
alias = "west"
region = "us-west-2"
}
resource "aws_instance" "example" {
provider = aws.west
# ...
}
```
---
## ресурсы
- основная сущность в терраформе
- предоставляется провайдером
- часто соответствует ресурсу в облаке
- набор аттрибутов определяется провайдером
- имеет набор мета-аргументов, которые не зависят от провайдера и определяют управление ресурсом на уровне обработки терраформом
---
## depends_on
- список ресурсов и/или модулей от которых зависит текущий ресурс или модуль
- указывается если нельзя указать аргумент зависящий от другого ресурса
- с модулями работает, начиная с версии 0.13
- [документация](https://www.terraform.io/language/meta-arguments/depends_on)
---
## count
- определяет кол-во экземляров ресурса или модуля
- позволяет управлять созданием/удалением ресурса
- позволяет описывать условия для создания ресурса
- описание в стейте терраформа становится списком `module.<NAME>[<INDEX>]`
- в ресурсе можно использовать переменную `count.index`
- [документация](https://www.terraform.io/language/meta-arguments/count)
---
## пример использования count
```bash
variable "create_users" {
type = list(string)
description = "List of users"
}
resource "random_password" "password" {
count = length(var.create_users)
length = 8
special = true
override_special = "_%@"
}
```
---
## Пример с условием
```bash
count = var.number_of_instances > 0 && var.disk_size > 0 ? var.number_of_instances : 0
name = "my_instance_${count.index}"
```
<!-- .element: style="font-size:40%;padding:0px" -->
---
## for_each
- проходит по каждому элементу set или map
- для прохода по списку требуется преобразования с помощью toset
- работает для ресурса, модуля, динамичского блока
- создает переменную each для доступа к элементам списка или словаря
- each.key
- each.values
- описание в стейте терраформа - `<TYPE>.<NAME>[<KEY>]`, где `<KEY>` ключ map или set
- [документация](https://www.terraform.io/language/meta-arguments/for_each)
---
## пример с динамическим блоком
```bash
resource "helm_release" "redis-k8s" {
name = var.name
namespace = var.namespace
create_namespace = var.create_namespace
repository = "https://charts.bitnami.com/bitnami"
chart = "redis"
version = var.chart_version
values = [file("${path.module}/values.yaml"), var.value]
dynamic "set" {
for_each = var.set
content {
name = set.key
value = set.value
}
}
}
```
---
## data-sources
- каждый провайдер предоставляет источники данных, также как и ресурсы
- источник данных через определенные аргументы позволяет получить данные о ресурсах облака
- доступ через конструкцию `data`
```bash
data "yandex_vpc_network" "network" {
name = var.network_name
}
data "yandex_vpc_subnet" "subnet" {
name = var.subnet_name
}
```
---
## Переменные
- Input Variables
- аргументы для ресурса или модуля
- Output Values
- значения которые можно достать из ресурса или модуля
- Local Values
- удобно использовать для промежуточных вычислений
---
## Input Variables
- каждая переменная описывается в секции `variable`
- часто используется файл variables.tf
- используются следующие аргументы для описания переменной
- default
- type
- description
- validation
- sensitive
- nullable
- передаваемые значения выставляются через `*.tfvars` файлы
---
## Типы переменных
- [документация](https://www.terraform.io/language/expressions/types)
- простые
- string
- number
- boolean
- структурные
- list(`<TYPE>`), list(any)
- set(`<TYPE>`), set(any)
- map(`<TYPE>`), map(any)
- object({`<ATTR NAME>` = `<TYPE>` ... })
- tuple([`<TYPE>`, ...])
---
## Output Values
- обычно прописываются в outputs.tf
```bash
output "host" {
value = yandex_mdb_postgresql_cluster.cluster.host[0].fqdn
description = "The database host."
}
output "password" {
value = {
for k, v in random_password.password : var.users[k].name => v.result
}
description = "The database password."
sensitive = true
}
```
---
## Local Values
- задаются в секции `locals {}`
- обращение производится через префикс `local.<name>`
```
locals {
instance_ids = concat(aws_instance.blue.*.id,
aws_instance.green.*.id)
}
locals {
private_key_path = "${var.ssh_keys_path}/${var.ssh_user}"
}
```
---
## Locals
```bash
locals {
values_yaml = {
smtp = {
host = var.smtp_host
port = var.smtp_port
login = var.smtp_login
externalSecret = {
name = var.smtp_secret_name
key = var.smtp_secret_key
}
}
service = {
port = var.service_port
}
}
}
```
---
## Locals
```bash
resource "helm_release" "postfix" {
name = var.name
namespace = var.namespace
create_namespace = var.create_namespace
chart = "${path.module}/../../../helm-charts/charts/postfix"
values = [file("${path.module}/values.yaml"),
yamlencode(local.values_yaml), var.value]
dynamic "set" {
for_each = var.set
content {
name = set.key
value = set.value
}
}
}
```
---
## Provisioner
- терраформ предоставляет набор провижинеров для выполнения действий, выходящих за рамки апи ресурсов
- file
- local-exec
- remote-exec
- также для многих облаков существует специальный аргумент для запуска стартатовых скриптов
- user-data
- metadata
- возможен запуск нескольких провиженеров
- возможен запуск провиженера без ресурса (`null-resource`)
- [документация](https://www.terraform.io/language/resources/provisioners/syntax)
---
## State
- терраформ сохраняет состояние инфраструктуры
- по умолчанию используется локальный файл
- проблематично работать командой
- можно хранить в гите
- могут быть проблемы с параллельной работой
- отсутствуют блокировки
-
---
# Практика
---
# Ваши вопросы
{"metaMigratedAt":"2023-06-17T03:04:56.284Z","metaMigratedFrom":"Content","title":"Terraform","breaks":true,"contributors":"[{\"id\":\"3385ceb9-5869-46ee-ac82-51698eb477a8\",\"add\":7894,\"del\":289}]"}