Задание:

a) Создайте все необходимые инстансы:

  • i. Cloud-HA01, Cloud-HA02: 1vCPU, 512 МБ ОЗУ, 10 ГБ размер диска;
  • ii. Cloud-DB01, Cloud-DB02 , Cloud-WEB01, Cloud-WEB02: 1vCPU, 1 ГБ ОЗУ, 10 ГБ размер диска;
  • iii. В качестве операционной системы используйте Альт Starterkit (оптимизированная сборка под облака), шаблон alt-p10-cloud-x86_64 (размер: 385 МиБ).

i. Обеспечьте правильное подключение создаваемых инстансов к соответствующим виртуальным сетям в рамках заданной топологии (см. Топология L-3).

i. Доступ ко всем инстансам должен быть реализован по протоколу SSH только с виртуальной машины Cloud-ADM на основе открытых ключей;

2. Имена инстансов, виртуальных сетей, и балансировщика нагрузки должны соответствовать именованиям, указанным в Топологии (см. Топология L-3).

Основные моменты на что стоит обратить внимание перед написанием скрипта с использованием Terraform:

  • Чтобы с инстанса Cloud-ADM был доступ по SSH до всех создаваемых инстансов, используется cloud-init.yml

    • в данном файле можно как передать содержимое публичного ключа - сегенрированного на инстансе Cloud-ADM, так и задать пароль для пользователя altlinux, если это необходимо;

    • например:
#cloud-config
chpasswd:
  expire: false
  users:
  - {name: altlinux, password: <PASSWORD>, type: text}
  ssh_pwauth: false

users:
  - name: altlinux
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: wheel
    shell: /bin/bash
    ssh_authorized_keys: 
      - ssh-rsa <PUBLIC_KEY>
  • Для добавления нескольких интерфейсов - network с указанием port - указывается необходимое количество раз;

Вариант реализации:

Cloud-ADM:

  • Вся дальнейшая работа реализуется в контексте директории /home/altlinux/bin/terraform:
cd /home/altlinux/bin/terraform
  • Создадим файл 'instance.tf', в котором последовательно будем описывать всё что касается создаваемых инстансов в контексте данного задания:
vim instance.tf
  • Добавляем следующее содержимое:
    • см. комментарии в коде;
# Создание инстанса Cloud-HA01
resource "openstack_compute_instance_v2" "cloud_ha01" {
  name            = "Cloud-HA01"
  flavor_id       = var.flavor_id_512ram_1vcpu
  user_data       = file("cloud-init.yml")

  block_device {
    uuid                  = var.image_id
    source_type           = "image"
    volume_size           = 10
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.port_externalnet_ha01.id
  }

  network {
    port = openstack_networking_port_v2.port_internalnet_ha01.id
  }

  network {
    port = openstack_networking_port_v2.port_management_ha01.id
  }
}

# Создание инстанса Cloud-HA02
resource "openstack_compute_instance_v2" "cloud_ha02" {
  name            = "Cloud-HA02"
  flavor_id       = var.flavor_id_512ram_1vcpu
  user_data       = file("cloud-init.yml")

  block_device {
    uuid                  = var.image_id
    source_type           = "image"
    volume_size           = 10
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.port_externalnet_ha02.id
  }

  network {
    port = openstack_networking_port_v2.port_internalnet_ha02.id
  }

  network {
    port = openstack_networking_port_v2.port_management_ha02.id
  }
}

# Создание инстанса Cloud-WEB01
resource "openstack_compute_instance_v2" "cloud_web01" {
  name            = "Cloud-WEB01"
  flavor_id       = var.flavor_id_1ram_1vcpu
  user_data       = file("cloud-init.yml")

  block_device {
    uuid                  = var.image_id
    source_type           = "image"
    volume_size           = 10
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.port_internalnet_web01.id
  }

  network {
    port = openstack_networking_port_v2.port_management_web01.id
  }
}

# Создание инстанса Cloud-WEB02
resource "openstack_compute_instance_v2" "cloud_web02" {
  name            = "Cloud-WEB02"
  flavor_id       = var.flavor_id_1ram_1vcpu
  user_data       = file("cloud-init.yml")

  block_device {
    uuid                  = var.image_id
    source_type           = "image"
    volume_size           = 10
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.port_internalnet_web02.id
  }

  network {
    port = openstack_networking_port_v2.port_management_web02.id
  }
}

# Создание инстанса Cloud-DB01
resource "openstack_compute_instance_v2" "cloud_db01" {
  name            = "Cloud-DB01"
  flavor_id       = var.flavor_id_1ram_1vcpu
  user_data       = file("cloud-init.yml")

  block_device {
    uuid                  = var.image_id
    source_type           = "image"
    volume_size           = 10
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.port_internalnet_db01.id
  }

  network {
    port = openstack_networking_port_v2.port_management_db01.id
  }
}

# Создание инстанса Cloud-DB02
resource "openstack_compute_instance_v2" "cloud_db02" {
  name            = "Cloud-DB02"
  flavor_id       = var.flavor_id_1ram_1vcpu
  user_data       = file("cloud-init.yml")

  block_device {
    uuid                  = var.image_id
    source_type           = "image"
    volume_size           = 10
    boot_index            = 0
    destination_type      = "volume"
    delete_on_termination = true
  }

  network {
    port = openstack_networking_port_v2.port_internalnet_db02.id
  }

  network {
    port = openstack_networking_port_v2.port_management_db02.id
  }
}
  • Выполняем проверку синтаксиса и структуры файлов конфигурации Terraform
terraform validate
  •  
    • В результате увидим ряд ошибок связанных с большим количеством не объявленных переменных.
  • Поэтому открываем файл variables.tf:
vim variables.tf
    • И объявляем все неодостающие переменные с присвоением необходимых значений:
      • см. комментарии в коде;
# ID для flavor 0,5 RAM и 1 vCPU
# узнать можно: openstack --insecure flavor list
variable "flavor_id_512ram_1vcpu" {
	type = string
	default = "100"
}

# ID для flavor 1 RAM и 1 vCPU
# узнать можно: openstack --insecure flavor list
variable "flavor_id_1ram_1vcpu" {
	type = string
	default = "f0a74551-ec6e-42cc-96e7-6403989d17ea"
}

# ID для образа alt-p10-cloud-x86_64.qcow2 (358 МиБ)
# узнать можно: openstack --insecure image list
variable "image_id" {
	type = string
	default = "05d06ced-de0e-426a-b21e-798bfa0dbaa9"
}
  • После чего, при повторной проверки синтаксиса - будет теперь уже ошибка связаная с отсутствием файла cloud-init.yml который должен быть отправлен на каждый создаваемый инстанс
  • Для этого генерируем предварительно ключевую пару SSH на инстансе Cloud-ADM:
ssh-keygen -t rsa
    • Результат:
      • также копируем содержимое открытого ключа, чтобы указать его в файле cloud-init.yml
      • таким образом, с инстанса Cloud-ADM будет реализован доступ по SSH до всех создаваемых инстансов на основе ключевой пары

  • Создаём файл cloud-init.yml:
vim cloud-init.yml
    • и помещаем в него следующее содержимое:
#cloud-config
chpasswd:
  expire: false
  users:
  - {name: altlinux, password: P@ssw0rd, type: text}
  ssh_pwauth: false

users:
  - name: altlinux
    sudo: ALL=(ALL) NOPASSWD:ALL
    groups: wheel
    shell: /bin/bash
    ssh_authorized_keys: <СОДЕРЖИМОЕ_ПУБЛИЧНОГО_КЛЮЧА_SSH>
    • например:

  • После чего, при повторной проверки синтаксиса - ошибок быть не должно:

  • Запускаем развёртывание данных ресурсов:
terraform apply
    • Подтверждаем развёртывание введя yes:

    • Результат:

  • Проверяем наличие созданных ресурсов средствами openstack-cli:
    • сразу же видим подключённые необходимые сети и адреса в соответствие с Топологией L-3

  • Проверяем наличие созданных ресурсов средствами веб-интерфейса:

Последнее изменение: вторник, 24 июня 2025, 12:54