Структура манифеста TerraformBeta

Манифест Terraform описывает конфигурацию инфраструктуры для развертывания инстанса image-based приложения в Marketplace. Язык описания — HashiCorp Configuration Language (HCL).

В манифесте используются следующие элементы:

  • variables — входные переменные для конфигурации ресурсов.
  • resources — ресурсы, позволяющие управлять объектами инфраструктуры. Например, создать ВМ. При описании ресурсов можно указывать зависимости с помощью блока depends on. Ресурс не будет создан, если не выполняется хотя бы одна зависимость.
  • data-sources — источники данных, позволяющие получить определенную информацию от провайдера Terraform, например, получить доступные типы ВМ или получить результаты выполнения скриптов.
  • outputs — выходные параметры, результаты выполнения манифеста.

Провайдеры ресурсов и источников данных Terraform

Имя

Описание

Обозначение в манифесте

VK CS

Содержит ресурсы и источники данных для описания инфраструктуры сервиса.

Полный перечень ресурсов и источников данных приведен в официальной документации провайдера.

Примеры манифестов, описывающих создание ресурсов, приведены в практических руководствах по использованию Terraform

vkcs

VK CS Infra (iVK CS)

Содержит ресурсы и источники данных, расширяющие возможности провайдера VK CS, например, позволяющие отслеживать состояние инстанса сервиса, запускать скрипты и использовать их результаты в процессе развертывания. Для скриптов поддерживаются языки Bash и Python.

Ресурсы и источники данных описаны в справочнике по провайдеру VK CS Infra (iVK CS)

ivkcs

Null

Ресурсы провайдера используются для запуска внешних процессов или действий, не связанных напрямую с ресурсами инфраструктуры

null

Random

Ресурсы провайдера используются, чтобы генерировать пароли для доступа к инстансу сервиса. Подробнее — в официальной документации провайдера

random

Time

Ресурсы провайдера используются для настройки взаимодействия по времени между другими ресурсами, например, для создания паузы или временной метки

time

Компоненты манифеста Terraform

Схема манифеста Terraform, описывающего шаги развертывания сервиса на ВМ в VK Cloud:

pic1

Конкретные шаги развертывания сервиса зависят от требующейся для вашего сервиса инфраструктуры и ее настроек.

Основные компоненты манифеста Terraform:

  1. Описание входных переменных для конфигурации ресурсов, в том числе специальной переменной instance_uuid, которая содержит идентификатор развертывания сервиса.
  2. Описание инфраструктуры развертывания сервиса.
  3. Описание выходных параметров.

Опциональные компоненты, которые описываются с помощью ресурсов провайдера iVK CS:

Пример манифеста Terraform

Ниже приведен манифест для развертывания сервиса Grafana на одной ВМ с использованием:

  • внешних IP-адресов;
  • DNS облачной платформы;
  • мониторинга доступности адреса.
# --------------------variables--------------------# Специальные переменные# Идентификатор развертывания сервисаvariable "instance_uuid" {  type    = string  default = "4a57a965-3c83-436c-80e2-428e421538cc"}variable "email" {  type    = string  default = "user@example.com"}# Внешние переменные# Размещение с внешним или внутренним IP-адресомvariable "grafana_placement" {  type    = string  default = "internal"}# Резервное копированиеvariable "backup_style" {  type    = string  default = "s3"}# Зона доступностиvariable "ds-az" {  type    = string  default = "GZ1"}# Тип ВМvariable "ds-flavor" {  type    = string  default = "a493b27d-170d-48eb-a24b-99e9b325f988"}# Идентификатор подсетиvariable "ds-subnet" {  type    = string  default = "cd4224ac-0527-4291-a8e0-afae0cee02ed"}# Тип root-дискаvariable "root_type" {  type    = string  default = "ceph-ssd"}# Размер root-диска, ГБvariable "root_size" {  type    = number  default = 10}# Тип диска для хранения данныхvariable "data_type" {  type    = string  default = "ceph-ssd"}# Размер диска для хранения данных, ГБvariable "data_size" {  type    = number  default = 1}# Идентификатор образа сервисаvariable "image_uuid" {  type        = string  default     = "8c7a6443-bb79-4f04-884a-14231f0ba6cb"  description = "grafana image"}# Порты доступа для группы безопасностиvariable "ports" {  type    = list(number)  default = [    22, 80, 443  ]  description = "ports for secgroup rule. grafana [80, 443]"}locals {  # Сокращенный вариант instance_uuid  short_name = substr(var.instance_uuid, 0, 8)  # Генерация имени хоста  hosts_name = "${local.short_name}-grafana"}# ---------------------data------------------------# Получение данных виртуальной сетиdata "vkcs_networking_subnet" subnet {  subnet_id = var.ds-subnet}# --------------------backup-----------------------# Создание бакетов S3resource "ivkcs_s3" "s3_backup" {  count = var.backup_style == "s3" ? 1 : 0  name  = "${local.hosts_name}-backup"}# --------------------security group---------------# Создание группы безопасностиresource "vkcs_networking_secgroup" "secgroup" {  name = "${local.short_name}-grafana"  sdn  = data.vkcs_networking_subnet.subnet.sdn}# Правила для группы безопасностиresource "vkcs_networking_secgroup_rule" "rules" {  count             = length(var.ports)  # Определение направления применения правил — для входящих (ingress) или исходящих (egress) соединений  direction         = "ingress"  # Список портов доступа  port_range_max    = element(var.ports, count.index)  port_range_min    = element(var.ports, count.index)  # Протокол доступа  protocol          = "tcp"  # Удаленный сетевой префикс  remote_ip_prefix  = "0.0.0.0/0"  # Индентификатор группы безопасности, для которой созданы правила  security_group_id = vkcs_networking_secgroup.secgroup.id  description       = "rule_tcp_${element(var.ports, count.index)}"}# --------------------network----------------------# Привязка IP-адреса к портуresource "vkcs_networking_port" "ports" {  name               = "${local.short_name}-grafana"  admin_state_up     = "true"  network_id         = data.vkcs_networking_subnet.subnet.network_id  sdn                = data.vkcs_networking_subnet.subnet.sdn  security_group_ids = [    vkcs_networking_secgroup.secgroup.id  ]  fixed_ip {    subnet_id = var.ds-subnet  }}# --------------------keypair----------------------# Создание ключевой парыresource "ivkcs_ssh_keypair" "keypair" {}# --------------------------vm---------------------# Создание cloud-config конфигурации. Получение данных для инициализации агента на хостеresource "ivkcs_user_data" "user_data" {  # Идентификатор развертывания сервиса  uuid      = var.instance_uuid  hosts     = [local.hosts_name]  target_os = "almalinux9"  # Ключи для доступа по SSH  ssh_authorized_keys = [    ivkcs_ssh_keypair.keypair.public_key,  ]}# Создание ВМresource "vkcs_compute_instance" "grafana" {  name              = local.hosts_name  flavor_id         = var.ds-flavor  security_groups   = [vkcs_networking_secgroup.secgroup.name]  availability_zone = var.ds-az  metadata          = { "sid" : "xaas", "product" : "grafana" }  # Root-диск  block_device {    source_type      = "volume"    destination_type = "volume"    boot_index       = 0    uuid             = vkcs_blockstorage_volume.boot.id  }  # Применение cloud-config конфигурации для настройки ВМ. Установка агента  user_data = ivkcs_user_data.user_data.user_data[0]  # Прикрепление IP-адреса к ВМ  network {    port = vkcs_networking_port.ports.id  }  # Попытка остановки ВМ перед удалением  stop_before_destroy = true  # Тайм-аут создания ВМ  timeouts {    create = "10m"  }}# --------------------volume-----------------------# Создание root-дискаresource "vkcs_blockstorage_volume" "boot" {  name              = "${local.short_name}-grafana-boot"  # Метаданные  metadata          = { "sid" : "xaas", "product" : "grafana" }  # Идентификатор образа сервиса  image_id          = var.image_uuid  volume_type       = var.root_type  size              = var.root_size  availability_zone = var.ds-az}# Создание диска данныхresource "vkcs_blockstorage_volume" "grafana_data" {  name              = "${local.short_name}-grafana-data"  # Метаданные  metadata          = { "sid" : "xaas", "product" : "grafana" }  size              = var.data_size  availability_zone = var.ds-az  volume_type       = var.data_type}# Присоединение диска данных к ВМresource "vkcs_compute_volume_attach" "attached" {  instance_id = vkcs_compute_instance.grafana.id  volume_id   = vkcs_blockstorage_volume.grafana_data.id}# -----------------------external------------------# Получение пула внешних IP-адресовresource "vkcs_networking_floatingip" "fips" {  count = var.grafana_placement == "external" ? 1 : 0  pool  = data.vkcs_networking_subnet.subnet.sdn == "neutron" ? "ext-net" : "internet"}# Назначение ВМ внешнего IP-адресаresource "vkcs_compute_floatingip_associate" "fip" {  count       = length(vkcs_networking_floatingip.fips)  floating_ip = vkcs_networking_floatingip.fips[count.index].address  instance_id = vkcs_compute_instance.grafana.id}# Создание A-записи в DNS облачной платформыresource "ivkcs_dns" "grafana" {  count  = length(vkcs_networking_floatingip.fips)  name   = "grafana-${local.short_name}"  domain = "xaas.msk.vkcs.cloud"  ip     = vkcs_networking_floatingip.fips[count.index].address}# --------------------agent-run--------------------locals {  grafana_domain   = var.grafana_placement == "external" ? "${ivkcs_dns.grafana[0].name}.${ivkcs_dns.grafana[0].domain}" : vkcs_compute_instance.grafana.access_ip_v4  grafana_root_url = var.grafana_placement == "external" ? "https://${local.grafana_domain}" : "http://${local.grafana_domain}"  # Стартовый скрипт для ресурса ivkcs_agent_exec.start  start = <<-EOT#!/bin/bashansible-playbook start.yml \  --extra-vars "lego_enabled=${var.grafana_placement == "external" ? "true" : "false"}" \  --extra-vars "lego_email=${var.email}" \  --extra-vars "backup_enabled=${var.backup_style == "s3" ? "true" : "false"}" \  --extra-vars "backup_access_token=${try(ivkcs_s3.s3_backup[0].access, "n/a")}" \  --extra-vars "backup_secret_token=${try(ivkcs_s3.s3_backup[0].secret, "n/a")}" \  --extra-vars "backup_bucket_name=${try(ivkcs_s3.s3_backup[0].name, "n/a")}_bucket" \  --extra-vars "grafana_domain=${local.grafana_domain}" \  --extra-vars "grafana_root_url=${local.grafana_root_url}"EOT}resource "ivkcs_agent_exec" "start" {  hosts = [local.hosts_name]  name  = "start_grafana"  uuid  = var.instance_uuid  step {    index   = 1    type    = "bash"    content = local.start    options {      timeout  = "20m"      cwd      = "/opt/playbooks"      attempts = 1    }  }  depends_on = [    vkcs_compute_instance.grafana,    vkcs_compute_volume_attach.attached,  ]}# --------------------health check-----------------# Мониторинг ВМresource "ivkcs_agent_check" "health" {  hosts = [local.hosts_name]  uuid  = var.instance_uuid  # Мониторинг по адресу  http_health {    method     = "GET"    protocol   = var.grafana_placement == "internal" ? "http" : "https"    host       = local.grafana_domain    path       = "/api/health"    http_codes = [200]    period     = "30s"  }  timeouts {    create = "5m"  }  depends_on = [    ivkcs_agent_exec.start,  ]}# --------------------outputs----------------------# Вывод закрытого SSH-ключа для доступа к ВМoutput "keypair" {  value     = ivkcs_ssh_keypair.keypair.private_key  # Выходной параметр содержит чувствительные данные  sensitive = true}# Вывод URL Grafanaoutput "grafana_url" {  value = local.grafana_root_url}# Вывод идентификатора бакета S3output "s3_backup" {  value = try(ivkcs_s3.s3_backup[0].id, "n/a")}