Рано или поздно большинство зрелых проектов приходят к необходимости использовать как виртуальные машины, так и выделенные серверы. Это логично, поскольку под разные задачи требуются разные вычислительные ресурсы. Однако затем возникает проблема управления физическим оборудованием.

В этой статье подробно разберем концепцию, которая позволяет взаимодействовать с выделенными серверами так же легко, как с облачными. На практическом примере развернем гибридную инфраструктуру в разных дата-центрах исключительно средствами Terraform. Объединим разрозненные хосты в общую приватную сеть.

Привет! На связи Сергей, системный администратор в Selectel. Надеюсь, этот обзор будет полезен системным администраторам, DevOps-инженерам, архитекторам и всем, кто хочет избавиться от путаницы в процессах и управлять пулом гибридных вычислительных ресурсов через один инструмент.

Содержание
Bare metal cloud
Terraform Selectel и Selectel Bare Metal Cloud
Управление разметкой
Управление локальной сетью
Глобальный роутер
Пример проекта

Итак, поехали. Для начала — небольшой ликбез по основным терминам.

IaC (Infrastructure as Code, инфраструктура как код) — подход, при котором автоматизируется управление ресурсами через машиночитаемые конфигурационные файлы. Сюда же относятся инструменты версионирования (GitHub, GitLab) пайплайны CI/CD (Gitlab Runner, Jenkins) и концепция GitOps, когда репозиторий выступает единственным источником истины.

Главная цель такого подхода  — сделать код:

  • прозрачным — через общий удаленный репозиторий для всей команды;

  • воспроизводимым — каждое исполнение дает идентичный результат;

  • версионируемым — с возможностью легкого отката или аудита изменений;

  • автоматизируемым — чтобы инфраструктурные изменения можно было предсказуемо доставлять в целевую среду.

Terraform — инструмент декларативного управления инфраструктурой. Простыми словами, это классическая реализация IaC, основанная на всех описанных выше принципах, но применяемая не к коду приложения, а к инфраструктурным ресурсам через API провайдера.

На практике обычно это выглядит примерно так. Есть некое облако с точкой входа через API. С помощью манифестов Terraform декларируется желаемое состояние — например, создать заданное количество виртуальных машин с определенными параметрами. После создания эти хосты передаются дальше по цепочке в менеджер конфигураций — например, Ansible, Salt, Puppet или Chef.

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

Bare metal cloud

Понимая назначение Terraform, становится ясно, что с его помощью можно легко поддерживать полноценные проекты на виртуальных облачных машинах. Однако пока в стороне остались выделенные серверы и гибридная инфраструктура. 

Дело в том, что в отличии от облака, автоматизировать управление физическими машинами значительно сложнее. В облаке есть (весьма условно) некий абстрактный пул однородных ресурсов, в которые образы копируются почти моментально, не взаимодействуя с железом напрямую. Выделенные же серверы — это множество различных вариантов аппаратных конфигураций.

Для автоматизации необходим полный цикл управления питанием (через IPMI, iDRAC и т. д.) и сетевой загрузкой (с помощью PXE). Из-за особенностей управления физическим оборудованием тема администрирования выделенных серверов в контексте IaC затрагивается не очень часто.

Итак, что же такое Bare Metal Cloud? Это концепция, когда физические серверы, в логике взаимодействия с ними пользователя, расцениваются как виртуальные машины. Разумеется, есть некоторые нюансы, но в целом подход реализуется при выполнении следующих условий.

  • У серверов есть управляющий API — «под капотом» связываются множество элементов: автонастройка портов на реальных свитчах, модули Out-of-Band, в том числе для управления питанием, сетевая загрузка PXE и сама система автоматического провижининга, о которой ниже.

  • Система автоматический доставки — специальное приложение, которое, получив команду, самостоятельно устанавливает и настраивает сервер — точно так же, как это происходит в облаке. В результате оперативно предоставляется готовый к работе и доступный по сети хост.

  • Модель Pay-as-you-go — схема оплаты только за используемые ресурсы, что подразумевает тарифы с гранулярностью меньше месяца — например, с возможностью арендовать сервер на один день.

В случае, если инфраструктура провайдера отвечает этим требованиям, открывается возможность управлять такими серверами через IaC. Но вернемся к гибридному проекту.

Существует множество сценариев, когда крупный проект нуждается как в виртуальных машинах (для балансировщиков, фронтенда, микросервисов), так и в физических серверах (для баз данных, высоконагруженных компонентов приложений с прямым доступом к железу, для популярных сегодня LLM).

Здесь часто возникает диссонанс: виртуальные хосты описаны в репозитории и управляются через код, а физические — арендуются и настраиваются системными администраторами вручную.

Из-за отсутствия систем автоматического провижининга на выделенных серверах, процесс их появления в инфраструктуре проекта остается частично ручным и не полностью покрывается возможностями IaC. Зачастую администратор проекта заказывает у провайдера сервер, после чего операционная система устанавливается самостоятельно — либо силами самого заказчика, либо инженерами дата-центра. 

В любом случае этап затягивается, а поскольку никак не отражается в коде, то все особенности установки сервера остаются в голове одного человека. Как следствие, в проекте используются два вида хостов с двумя совершенно разными процессами создания. 

Возникает путаница, множится число точек входа, усложняется администрирование. В идеальной ситуации рост проекта не должен приводить к пропорциональному усложнению управления им.

Теоретическая идея Bare Metal Cloud с привязкой выделенных серверов к Terraform позволила бы управлять таким гибридным проектом через один инструмент. А что если я скажу, что это вовсе не теоретическая идея?

Арендуйте физический сервер с запуском от 2 минут

Замена комплектующих — бесплатно. Все ресурсы — только ваши.

Арендовать →

Terraform Selectel и Selectel Bare Metal Cloud

Наши выделенные серверы уже довольно давно вплотную работают в рамках железного облака. У них есть и свой API, и система автоматического провижининга. Так же подавляющее большинство конфигураций доступно для заказа с посуточной оплатой. 

Мы разработали свой Terraform-провайдер, исходный код которого открыт на GitHub, а также доступен для скачивания в рабочий проект с TerraformHub:

terraform {
  required_providers {
    selectel  = {
      source  = "selectel/selectel"
    }
  }
}

Наш Terraform‑провайдер способен управлять в том числе и выделенными серверами. Логика работы выглядит следующим образом. Основным ресурсом служит Selectel_dedicated_server_v1, в полях которого указываются ключевые параметры сервера:

  • конфигурация,

  • тариф оплаты,

  • имя хоста и пароль,

  • SSH‑ключи и многие другие настройки.

В последних версиях плагина добавились две важные функции. Остановимся на них подробнее.

Управление разметкой

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

В отличие от виртуальных машин, физические накопители требуют самостоятельной конфигурации партиций под конкретные задачи. Безусловно, для множества типовых ситуаций достаточно стандартной установки ОС на RAID1 без дополнительных разделов, хотя вариантов кастомизации может быть бесчисленное множество.

Появилась возможность программно настроить как RAID‑массивы, так и отдельные разделы с помощью блока partitions_config в ресурсе selectel_dedicated_server_v1.

Управление локальной сетью

Второе нововведение — полноценное управление локальными сетями. Теперь можно создавать L2-сети и назначать IP-адреса хостам через атрибуты вроде private_subnet_id. Практический пример — ниже. Сейчас важно отметить, что встроенный функционал позволяет создать в одной локации несколько серверов при помощи Terraform и соединить их в приватную L2‑сеть. 

Однако для интеграции с ресурсами других дата‑центров или облаком этого недостаточно. Для такой схемы потребуется создать L3‑связность. Настроить ее можно используя Terraform и услугу «Глобальный роутер».

Глобальный роутер

Глобальный роутер — это виртуальный L3-маршрутизатор. Подключив к нему необходимые подсети, создается единое адресное пространство, связывающее пулы и локации. Объединяются разрозненные виртуальные и физические машины в ту самую распределенную гибридную инфраструктуру, о которой мы говорили вначале.

Управлять этой услугой (создавать маршрутизатор и подключать сети) также можно прямо из кода с помощью Terraform-провайдера. Подробности — в нашей документации.

Пример проекта

Создадим небольшой проект. В качестве демонстрации гибридной архитектуры исключительно средствами Terraform развернем выделенный сервер и виртуальную машину в разных дата-центрах. Для надежного взаимодействия связываться они будут приватной сетью.

В рабочую директорию проекта добавим провайдер и все необходимые для авторизации атрибуты. Подробности — в документации

# Список провайдеров и атрибуты для их авторизации.

terraform {
 required_providers {
   selectel  = {
     source  = "selectel/selectel"
   }
   openstack = {
     source  = "terraform-provider-openstack/openstack"
   }
 }
}

provider "selectel" {
 domain_name = "123456"
 username    = "user"
 password    = "password"
 auth_region = "ru-9"
 auth_url    = "https://cloud.api.selcloud.ru/identity/v3/"
}

provider "openstack" {
 auth_url    = "https://cloud.api.selcloud.ru/identity/v3"
 domain_name = "123456"
 tenant_id   = selectel_vpc_project_v2.terraform.id
 user_name   = "user"
 password    = "password"
 region      = "ru-9"
}

# Инфраструктурный проект внутри панели Selectel

resource "selectel_vpc_project_v2" "terraform" {
  name = "terraform"
}

После выполнения цепочки команд terrafrom initterrafrom planterraform apply у нас появится новый проект terraform, который полностью управляется из самого Terraform. В нем же настраиваются доступы пользователей, чтобы в рамках одного аккаунта управлять сразу несколькими командами с разделением прав. Однако эта тема заслуживает отдельной статьи.  

Команда terraform init подготовит рабочую среду и установит необходимые плагины провайдеров.

Команда  terraform apply применит конфигурацию и создаст проект в панели управления.

Проверим успешность выполнения в личном кабинете.

Появился пустой проект terraform, в котором пока еще ничего нет.

Теперь перейдем непосредственно к созданию нашей распределенной гибридной инфраструктуры. Для начала опишем глобальный роутер и связанные с ним подсети в нужных локациях и пулах — там, где у нас будут хосты:

# Глобальный роутер global_router_1

resource "selectel_global_router_router_v1" "global_router_1" {
  name = "terraform_router"
}

# Создание подсети сервера 1 и ее добавление в роутер

resource "selectel_dedicated_private_subnet_v1" "subnet_1" {
  location_id = data.selectel_dedicated_location_v1.server_location_1.locations[0].id
  vlan        = "X"
  subnet      = "10.0.0.0/16"
}

resource "selectel_global_router_dedicated_network_v1" "global_router_dedicated_network_1" {
  router_id = selectel_global_router_router_v1.global_router_1.id
  zone_id   = data.selectel_dedicated_location_v1.server_location_1.locations[0].id
  vlan      = "X"
  name      = "spb-3"
}

resource "selectel_global_router_dedicated_subnet_v1" "global_router_dedicated_subnet_1" {
  network_id        = selectel_global_router_dedicated_network_v1.global_router_dedicated_network_1.id
  cidr              = "10.0.0.0/16"
  gateway           = "10.0.0.1"
  service_addresses = ["10.0.0.253", "10.0.0.254"]
  name              = "spb-3"
}

# Создание подсети VPC и ее добавление в роутер

data "selectel_global_router_zone_v1" "zone_1" {
  name    = "ru-9"
  service = "vpc"
}

resource "openstack_networking_network_v2" "vpc_network_1" {
  name           = "vpc_network_1"
  admin_state_up = "true"
}

resource "openstack_networking_subnet_v2" "vpc_subnet_1" {
  name       = "vpc_subnet_1"
  network_id = openstack_networking_network_v2.vpc_network_1.id
  cidr       = "10.1.0.0/16"
}

resource "selectel_global_router_vpc_network_v1" "global_router_vpc_network_1" {
  router_id     = selectel_global_router_router_v1.global_router_1.id
  zone_id       = data.selectel_global_router_zone_v1.zone_1.id
  os_network_id = openstack_networking_network_v2.vpc_network_1.id
  project_id    = selectel_vpc_project_v2.terraform.id
  name          = "ru-9"
}

resource "selectel_global_router_vpc_subnet_v1" "global_router_vpc_subnet_1" {
  network_id        = selectel_global_router_vpc_network_v1.global_router_vpc_network_1.id
  os_subnet_id      = openstack_networking_subnet_v2.vpc_subnet_1.id
  cidr              = "10.1.0.0/16"
  gateway           = "10.1.0.1"
  service_addresses = ["10.1.0.253", "10.1.0.254"]
  name              = "ru-9"
}

Теперь, когда с сетевой частью разобрались, можем создать сами хосты, виртуалку и выделенный сервер.

Виртуалка:

data "openstack_images_image_v2" "debian" {
  name        = "Debian 12 (Bookworm) 64-bit"
  most_recent = true
  visibility  = "public"
}

# В локальной сети VPC созданной выше добавим порт с адресом

resource "openstack_networking_port_v2" "port1" {
  name       = "vpc1_port"
  network_id = openstack_networking_network_v2.vpc_network_1.id

  fixed_ip {
    subnet_id = openstack_networking_subnet_v2.vpc_subnet_1.id
    ip_address = "10.1.0.20"
  }
}

resource "openstack_compute_instance_v2" "vpc1" {
  name              = "vpc1"
  image_id          = data.openstack_images_image_v2.debian.id
  flavor_id         = "1312"
  key_pair          = "key"
  availability_zone = "ru-9a"

  network {
    port = openstack_networking_port_v2.port1.id
  }
  lifecycle {
    ignore_changes = [image_id]
  }
  vendor_options {
    ignore_resize_confirmation = true
  }
}

Выделенный сервер:

data "selectel_dedicated_configuration_v1" "server_config_1" {
  project_id = selectel_vpc_project_v2.terraform.id
  deep_filter = <<EOT
    {
      "name": "BL10-SSD"
    }
  EOT
}

data "selectel_dedicated_location_v1" "server_location_1" {
  project_id = selectel_vpc_project_v2.terraform.id
  filter {
    name = "SPB-3"
  }
}

data "selectel_dedicated_os_v1" "server_os_1" {
  project_id = selectel_vpc_project_v2.terraform.id
  filter {
    name = "Debian"
    version_value = "13v2"
    configuration_id = data.selectel_dedicated_configuration_v1.server_config_1.configurations[0].id
    location_id = data.selectel_dedicated_location_v1.server_location_1.locations[0].id
  }
}

resource "selectel_dedicated_server_v1" "terraform_server_1" {
  project_id = selectel_vpc_project_v2.terraform.id
  configuration_id = data.selectel_dedicated_configuration_v1.server_config_1.configurations[0].id
  location_id = data.selectel_dedicated_location_v1.server_location_1.locations[0].id
  os_id = data.selectel_dedicated_os_v1.server_os_1.os[0].id
  price_plan_name = "1 day"
  os_host_name = "server1"
  ssh_key_name = var.ssh_key_name
  os_password = var.os_password
  add_private_vlan = true
  private_subnet_id = selectel_dedicated_private_subnet_v1.subnet_1.id
  private_subnet_ip = "10.0.0.2"
  partitions_config {
    soft_raid_config {
      name = "first-raid"
      level = "raid1"
      disk_type = "SSD SATA"
    }
    disk_partitions {
      mount        = "swap"
      size         = 5
      raid         = "first-raid"
    }
    disk_partitions {
      mount        = "/data"
      size         = 10
      raid         = "first-raid"
    }
    disk_partitions {
      mount        = "/images"
      size         = 200
      raid         = "first-raid"
    }
    disk_partitions {
      mount = "/"
      size  = -1
      raid  = "first-raid"
    }
  }
  force_update_additional_params =  true
}

Применим написанные манифесты командой terraform apply.

После отработки будет создан глобальный роутер, соединяющий облачный пул ru-9 (сеть 10.1.0.0/16) и локацию выделенных серверов в spb-3 (сеть 10.0.0.0/16).

Выделенному серверу корректно назначается внутренний адрес 10.0.0.2.

Виртуальная машина получает локальный адрес 10.1.0.20.

Зайдем на наши новые хосты и пропишем маршруты смежных подсетей друг до друга.

В реальном продакшн‑окружении (но не в рамках демонстрации) эта задача решалась бы автоматически: сразу после развертывания серверы передавались бы в систему управления конфигурациями (например, Ansible), которая настроила бы маршрутизацию.

После ручной настройки с физического сервера с локальным адресом 10.0.0.2 успешно проходит ping до виртуальной машины 10.1.0.20. L3-связность по изолированной проектной сети установлена.

Готово! Используя единственный инструмент автоматизации мы успешно развернули виртуальный хост, выделенный сервер и глобальный роутер, который объединил ресурсы разных дата‑центров. Дальнейшее развитие архитектуры упирается исключительно в воображение и нужды проекта. 

В нашем простом примере на виртуальной машине может размещаться балансировщик с фронтендом, а выделенный сервер возьмет на себя задачи бэкенда и СУБД. Разумеется, мы затронули только верхушку того, что можно сделать, используя Terraform как единую точку входа в гибридную инфраструктуру. 

Спасибо, что дочитали до конца!

Комментарии (0)