Terraform для управления облачной инфраструктурой Beget

Для управления облачной инфраструктурой Beget помимо панели управления и API можно использовать Terraform.

Terraform-провайдер Beget представляет собой альтернативный метод управления облачными ресурсами, позволяя декларативно описать желаемое состояние, после чего Terraform самостоятельно создаст, изменит или удалит описанные ресурсы. Подобный подход позволяет легко управлять и версионировать состояние облачной инфраструктуры.

На данный момент Terraform-провайдер Beget позволяет управлять жизненным циклом:

  • виртуальных серверов и их снапшотов;
  • бакетов S3;
  • собственных образов виртуальных серверов;
  • приватных сетей;
  • дополнительных IPv4-адресов;
  • SSH-ключей.

Также вы можете получать информацию о:

  • доступных конфигурациях серверов;
  • реквизитах доступа к бакетам S3;
  • собственных образах виртуальных серверов;
  • лицензиях ISP Manager;
  • приватных сетях;
  • регионах;
  • доступном для установки ПО из Marketplace.

Актуальный список возможностей, ресурсов и источников данных для Terraform, а также примеры использования вы можете найти в нашем репозитории на GitHub:

Примеры конфигураций

Предположим, мы хотим создать 2 сервера в одной приватной сети с конфигурациями:

  1. Регион Санкт-Петербург (ru1), 1 ядро CPU, линейка CPU – Standard 3+ GHz (normal_cpu), 1 ГБ оперативной памяти, 20 ГБ дискового пространства.
  2. Регион Санкт-Петербург (ru1), линейка CPU – High-Freq 5+ Ghz (high_cpu), 2 ядра CPU, 4 ГБ оперативной памяти, 50 ГБ дискового пространства.

Файл плана инфраструктуры в таком случае может выглядеть следующим образом:

main.tf
# Добавляем Terraform-провайдера Beget
terraform {
  required_providers {
    beget = {
      source = "tf.beget.com/beget/beget"
    }
  }
}
# Задаем ключ API облака Beget, необходимый для работы провайдера
provider "beget" {
  token = "JWT_token"
}
# Создаем ресурс публичного SSH-ключа
resource "beget_ssh_key" "devops" {
  name       = "Terraform machine key"
  # Можно указать как путь до файла ключа с помощью file(), так и сам ключ в виде строки
  public_key = file("/home/betutorial/.ssh/id_ed25519.pub")
}
# Создаем ресурс приватной сети в нужном регионе
resource "beget_private_network" "ru1" {
  region = "ru1"
}
# Источники данных позволяют получить необходимую для установки ПО информацию – например, его ID
data "beget_software" "gitea" {
  slug = "gitea"
}
# В некоторых случаях для установки ПО требуются дополнительные данные.
# Узнать доступные переменные и являются ли они обязательными можно следующим способом:
locals {
  gitea_vars = {
    for v in data.beget_software.gitea.variables :
    v.variable => {
      label       = v.label
      required    = v.is_required
      description = v.description
    }
  }
}
# Для вывода значений переменных используется конструкция output:
output "gitea_variables" {
  value = local.gitea_vars
}
# Создаем ресурс виртуального сервера
resource "beget_compute_instance" "gitea" {
  name        = "Gitea"
  description = "Gitea server, provisioned with Terraform"
  hostname    = "gitea-ru1"
  region      = "ru1"
  # Список добавляемых на сервер ключей SSH, для создания сервера требуется как минимум один 
  access = {
    ssh_keys = [beget_ssh_key.devops.id]
  }
  # Конфигурация VPS
  configuration = {
    cpu_class = "normal_cpu"
    cpu       = 1
    ram_mb    = 1 * 1024
    disk_mb   = 20 * 1024
  }
  image = {
    software = {
      # Для установки ПО обязательно указать его ID, чтобы его получить, можно использовать data source beget_software
      id = data.beget_software.gitea.id
      # Объект с дополнительными переменными устанавливаемого ПО
      # Для некоторого ПО они могут быть обязательны – например, для установки Gitea требуется указать домен, а также email и пароль администратора
      vars = {
        beget_fqdn           = "gitea.betutorial.ru"
        beget_email          = "example@betutorial.ru"
        beget_gitea_password = "5gnA41#1f"
      }
    }
  }
  # Добавляем сервер в приватную сеть
  private_networks = {
    (beget_private_network.ru1.id) = {
      # При необходимости можно явно указать приватный IP сервера
      address = "10.0.0.10"    
    }
  }
}


data "beget_software" "docker" {
  slug = "docker"
}


resource "beget_compute_instance" "gitea_runner" {
  name        = "Gitea Runner 00"
  description = "Terraform-provisioned Gitea runner"
  hostname    = "gitea-runner-ru1-00"
  region      = "ru1"
  access = {
    ssh_keys = [beget_ssh_key.devops.id]
  }
  configuration = {
    # Здесь указываем другую линейку процессора
    cpu_class = "high_cpu"
    cpu       = 2
    ram_mb    = 4 * 1024
    disk_mb   = 50 * 1024
  }
  image = {
    # Для установки некоторого ПО дополнительные данные не требуются.
    # В таком случае указывать поле vars необязательно.
    software = {
      id = data.beget_software.docker.id
    }
  }
  private_networks = {
    (beget_private_network.ru1.id) = {
      # Если поле address не указано, IP в приватной сети будет выдан автоматически
    }
  }
}
# Помимо получения информации, необходимой для создания сервера, с помощью output можно получить статус созданных ресурсов.
output "compute_instances" {
  value = [for i in [beget_compute_instance.gitea, beget_compute_instance.gitea_runner] : {
    id               = i.id
    name             = i.name
    ip_address       = i.ip_address
    software_domain  = i.software_domain
    private_networks = i.private_networks
    status           = i.status
    configuration    = i.configuration
  }]
}

Пример конфигурации с загрузкой собственного образа операционной системы и созданием виртуального сервера на его основе:

  1. Регион Москва (ru2), 2 ядра CPU, линейка CPU – Standard 3+ GHz (normal_cpu), 2 ГБ оперативной памяти, 30 ГБ дискового пространства.
main.tf
# Добавляем Terraform-провайдера Beget
terraform {
  required_providers {
    beget = {
      source = "tf.beget.com/beget/beget"
    }
  }
}
# Задаем ключ API облака Beget, необходимый для работы провайдера
provider "beget" {
  token = "JWT_token"
}
# Создаем ресурс публичного SSH-ключа
resource "beget_ssh_key" "devops" {
  name = "Terraform machine key"
  # Можно указать как путь до файла ключа с помощью file(), так и сам ключ в виде строки
  public_key = file("/home/betutorial/.ssh/id_ed25519.pub")
}


# Загружаем собственный образ в ту же локацию, где будет развернут сервер
resource "beget_compute_image" "alpine_cloud_image" {
  name   = "alpine-cloud-image"
  region = "ru2"
  source = {
    # Указываем URL, по которому доступен файл образа
    url = "https://dl-cdn.alpinelinux.org/alpine/v3.23/releases/cloud/nocloud_alpine-3.23.2-x86_64-bios-cloudinit-r0.qcow2"
  }
}


# Создаем ресурс виртуального сервера
resource "beget_compute_instance" "alpine" {
  name        = "Alpine"
  description = "Alpine Linux server, provisioned with Terraform"
  hostname    = "alpine-ru2"
  region      = "ru2"
  # Список добавляемых на сервер ключей SSH, для создания сервера требуется как минимум один
  access = {
    ssh_keys = [beget_ssh_key.devops.id]
  }
  # Конфигурация VPS
  configuration = {
    cpu_class = "normal_cpu"
    cpu       = 2
    ram_mb    = 2 * 1024
    disk_mb   = 30 * 1024
  }
  image = {
    # Указываем ID образа
    image_id = beget_compute_image.alpine_cloud_image.id
  }
}


# Помимо получения информации, необходимой для создания сервера, с помощью output можно получить статус созданных ресурсов
output "compute_instances" {
  value = {
    id               = beget_compute_instance.alpine.id
    name             = beget_compute_instance.alpine.name
    ip_address       = beget_compute_instance.alpine.ip_address
    software_domain  = beget_compute_instance.alpine.software_domain
    private_networks = beget_compute_instance.alpine.private_networks
    status           = beget_compute_instance.alpine.status
    configuration    = beget_compute_instance.alpine.configuration
  }
}


output "compute_image" {
  value = {
    id              = beget_compute_image.alpine_cloud_image.id
    disk_size_bytes = beget_compute_image.alpine_cloud_image.disk_size_bytes
    price           = beget_compute_image.alpine_cloud_image.price
    size_bytes      = beget_compute_image.alpine_cloud_image.size_bytes
    status          = beget_compute_image.alpine_cloud_image.status
  }
}

Пример конфигурации для создания бакета S3 с подключенным поддоменом и настройками CORS.

main.tf
# Добавляем Terraform-провайдера Beget
terraform {
  required_providers {
    beget = {
      source = "tf.beget.com/beget/beget"
    }
  }
}
# Задаем ключ API облака Beget, необходимый для работы провайдера
provider "beget" {
  token = "JWT_token"
}


# Создаем бакет S3
resource "beget_s3_bucket" "main" {
  name        = "S3 storage bucket"
  description = "S3 storage bucket, provisioned with Terraform"
  # На данный момент для создания бакетов S3 доступен только регион ru1
  region = "ru1"
  # Вы можете указать поддомен, по которому будут доступны ресурсы бакета. Это необязательное поле, его можно оставить пустым.
  domain = "static.betutorial.ru"


# При необходимости вы можете указать настройки CORS для бакета.
  cors = [{
    allowed_methods = ["GET", "HEAD"]
    allowed_origin  = "https://example.com"
    allowed_headers = ["*"]
    expose_headers  = ["ETag", "Content-Length"]
    max_age_seconds = 3600
    }, {
    allowed_methods = ["GET", "PUT", "POST", "DELETE"]
    allowed_origin  = "*"
    allowed_headers = ["Authorization", "Content-Type"]
    expose_headers  = ["ETag"]
    max_age_seconds = 1800
  }]
}


# Помимо получения информации, необходимой для создания сервера, с помощью output можно получить статус созданных ресурсов и другую информацию - например, реквизиты доступов к бакетам
output "bucket" {
  value = {
    id     = beget_s3_bucket.main.id
    name   = beget_s3_bucket.main.name
    domain = beget_s3_bucket.main.domain
  }
}


output "s3_credentials" {
  value = {
    url         = beget_s3_bucket.main.s3_access.url
    bucket_name = beget_s3_bucket.main.s3_access.bucket_name
    access_key  = nonsensitive(beget_s3_bucket.main.s3_access.access_key)
    secret_key  = nonsensitive(beget_s3_bucket.main.s3_access.secret_key)
  }
}


output "ftp_credentials" {
  value = {
    host     = beget_s3_bucket.main.ftp.host
    port     = beget_s3_bucket.main.ftp.port
    login    = nonsensitive(beget_s3_bucket.main.ftp.login)
    password = nonsensitive(beget_s3_bucket.main.ftp.password)
    status   = beget_s3_bucket.main.ftp.status
  }
}


output "sftp_credentials" {
  value = {
    host     = beget_s3_bucket.main.sftp.host
    port     = beget_s3_bucket.main.sftp.port
    login    = nonsensitive(beget_s3_bucket.main.sftp.login)
    password = nonsensitive(beget_s3_bucket.main.sftp.password)
    status   = beget_s3_bucket.main.sftp.status
  }
}

Подробная документация и описание структуры различных ресурсов доступны в репозитории:

Если возникнут вопросы, напишите нам, пожалуйста, тикет из панели управления аккаунта (раздел “Помощь и поддержка”), а если вы захотите обсудить Terraform или другие наши продукты с коллегами по цеху и сотрудниками Beget – ждем вас в нашем сообществе в Telegram.

Теги:

4
1056