Сценарий terraform для развертывания виртуальной машины в VK Cloud
В рамках данной инструкции мы рассмотрим сценарий terraform, который нам позволит создать в облаке VK виртуальную машину. Также я попробую более подробно описать данный сценарий.
Подготовка
Прежде чем приступить к созданию и запуску сценария, нам нужно установить и инициализировать terraform.
Для начала нам нужно установить пакет unzip. В зависимости от типа Linux, это выполняется разными командами.
а) Для Deb (Ubuntu / Debian / Astra Linux):
apt install unzip
б) Для RPM (Rocky / CentOS / РЕД ОС):
yum install unzip
Зеркала для загрузки Terraform с официального сайта могут быть заблокированы. Но у VK Cloud есть свои копии. Переходим на страницу загрузки Terraform от Mail Ru Group. Смотрим на версию пакета, который мы хотим установить. Например, на момент обновления данной инструкции, это была версия 1.5.2 — создаем переменную:
TR_VER=1.5.2
Скачиваем архив:
wget https://hashicorp-releases.mcs.mail.ru/terraform/${TR_VER}/terraform_${TR_VER}_linux_amd64.zip
Распаковываем его в каталог /usr/local/bin:
unzip terraform_${TR_VER}_linux_amd64.zip -d /usr/local/bin/
Создадим каталог, в котором будет находиться сценарий terraform:
mkdir -p /opt/terraform/vkcloud
Перейдем в него:
cd /opt/terraform/vkcloud
Создадим файл в каталоге пользователя, под которым мы работаем и будем запускать сценарий:
vi ~/.terraformrc
- provider_installation {
- network_mirror {
- url = "https://terraform-mirror.mcs.mail.ru"
- include = ["registry.terraform.io/*/*"]
- }
- direct {
- exclude = ["registry.terraform.io/*/*"]
- }
- }
* данное содержимое вставляем без изменений. По умолчанию, установка провайдера выполняется из репозитория hashicorp, однако, он может быть заблокирован на территории России, поэтому мы переопределяем путь по которому выполняются запросы.
Теперь создадим main-файл для инициализации настроек:
vi main.tf
- terraform {
- required_providers {
- vkcs = {
- source = "vk-cs/vkcs"
- }
- }
- }
- provider "vkcs" {
- username = "foo.bar@mail.ru"
- password = "vk cloud password"
- project_id = "project id"
- region = "RegionOne"
- }
Где:
2 - 6 | Описание для провайдера. В нашем примере указан только source — исходный адрес провайдера (является его глобальным идентификатором). Он также указывает основное место, откуда Terraform может его загрузить. |
9 - 14 | Индивидуальные настройки для подключения к провайдеру. |
10 | Указываем учетную запись, под которой мы логинимся на сервис VK Cloud |
11 | Пароль для учетной записи сервиса VK Cloud |
12 | Идентификатор проекта (смотрим в личном кабинете VK Cloud) |
13 | Регион (по умолчанию, RegionOne. Уточняем в личном кабинете) |
Теперь можно выполнить инициализацию — установку провайдера и выполнение подключения к хостинг-провайдеру.
terraform init
Мы должны увидеть:
...
Terraform has been successfully initialized!
...
Мы готовы, чтобы создать сценарий для развертывания виртуальной машины в VK Cloud.
Сценарий
Для написания сценария нам понадобится дополнительная информация, которую удобнее всего получить с помощью запросов openstack cli. Инструкцию по установке и использованию последнего читайте на странице Работа с OpenStack CLI в Linux.
И так, создаем файл:
vi variables.tf
- variable "image_flavor" {
- type = string
- default = "Ubuntu-22.04-202208"
- }
- variable "compute_flavor" {
- type = string
- default = "Basic-1-2-20"
- }
- variable "key_pair_name" {
- type = string
- default = "ssh-dmosk"
- }
- variable "availability_zone_name" {
- type = string
- default = "MS1"
- }
* данный файл описывает переменные, которые мы будем использовать в сценарии.
1 - 4 | Задаем название образа, который будет использоваться для диска. |
3 | В нашем примере виртуальная машина должна будет создаваться из образа с Ubuntu 22.04 |
6 - 9 | Шаблон виртуальной машины. |
8 | Базовый шаблон: 1 ядро, 2 Гб оперативной памяти, 20 Гб дискового пространства. |
11 - 14 | Пара ключей для подключения по SSH. |
13 | Название для ключа SSH, который должен быть загружен в облако. |
16 - 19 | Имя зоны доступности |
Подробную информацию о том, какие значения можно подставить в данные переменные можно узнать в личном кабинете VK Cloud или с помощью openstack cli:
openstack image list
openstack flavor list
openstack keypair list
openstack availability zone list
Создадим файл с описанием сети:
vi network.tf
- data "vkcs_networking_network" "extnet" {
- name = "ext-net"
- }
- resource "vkcs_networking_network" "network" {
- name = "net"
- }
- resource "vkcs_networking_subnet" "subnetwork" {
- name = "subnet_1"
- network_id = vkcs_networking_network.network.id
- cidr = "192.168.122.0/24"
- }
- resource "vkcs_networking_router" "router" {
- name = "router"
- admin_state_up = true
- external_network_id = data.vkcs_networking_network.extnet.id
- }
- resource "vkcs_networking_router_interface" "db" {
- router_id = vkcs_networking_router.router.id
- subnet_id = vkcs_networking_subnet.subnetwork.id
- }
- resource "vkcs_networking_secgroup" "secgroup" {
- name = "security_group"
- description = "terraform security group"
- }
- resource "vkcs_networking_secgroup_rule" "ssh_rule" {
- direction = "ingress"
- ethertype = "IPv4"
- port_range_max = 22
- port_range_min = 22
- protocol = "tcp"
- remote_ip_prefix = "0.0.0.0/0"
- security_group_id = vkcs_networking_secgroup.secgroup.id
- description = "Open SSH (22) Port"
- }
- resource "vkcs_networking_port" "port" {
- name = "port_1"
- admin_state_up = "true"
- network_id = vkcs_networking_network.network.id
- fixed_ip {
- subnet_id = vkcs_networking_subnet.subnetwork.id
- ip_address = "192.168.122.20"
- }
- }
- resource "vkcs_networking_port_secgroup_associate" "port" {
- port_id = vkcs_networking_port.port.id
- enforce = "false"
- security_group_ids = [
- vkcs_networking_secgroup.secgroup.id,
- ]
- }
Описание действий:
1 - 3 | Запрашиваем данные по внешней сети ext-net. Результаты доступны в переменной extnet. |
5 - 7 | Создаем ресурс для внутренней сети. Имя последней будет net, а данные с информацией в переменной network. |
9 - 13 | Создаем подсеть. |
10 | Название подсети subnet_1. |
11 | Будет являться частью сети net, которую мы создали выше (5-7). |
12 | Адрес подсети 192.168.122.0/24. |
15 - 19 | Создаем виртуальный маршрутизатор. Привязываем его к внешней сети через сеть ext-net. |
21 - 24 | Привязываем подсеть subnet_1 к маршрутизатору router. |
26 - 29 | Создаем группу безопасности security_group. |
31 - 40 | Создаем правило доступа на брандмауэре. |
34, 35 | Задаем порт доступа. В нашем примере 22 (SSH). |
37 | Ограничиваем адреса, с которых можно подключиться. В нашем примере, без ограничений. |
38 | Привязываем правило к созданной ранее группе безопасности security_group. |
42 - 51 | Создаем сетевой порт. |
43 | Имя для порта будет port_1. |
45 | Порт будет ассоциирован с внутренней сетью net. |
48 | Используем подсеть subnet_1. |
49 | Выделяем фиксированный адрес 192.168.122.20. |
53 - 59 | Связываем группу безопасности security_group с портом port_1. |
И, наконец, создаем файл с описанием виртуальной машины:
vi instance.tf
- data "vkcs_compute_flavor" "compute" {
- name = var.compute_flavor
- }
- data "vkcs_images_image" "compute" {
- name = var.image_flavor
- }
- resource "vkcs_compute_instance" "compute" {
- name = "compute-name"
- flavor_id = data.vkcs_compute_flavor.compute.id
- key_pair = var.key_pair_name
- security_groups = ["default","ssh"]
- availability_zone = var.availability_zone_name
- block_device {
- uuid = data.vkcs_images_image.compute.id
- source_type = "image"
- destination_type = "volume"
- volume_type = "ceph-ssd"
- volume_size = 8
- boot_index = 0
- delete_on_termination = true
- }
- network {
- uuid = vkcs_networking_network.network.id
- }
- depends_on = [
- vkcs_networking_network.network,
- vkcs_networking_subnet.subnetwork
- ]
- }
- resource "vkcs_networking_floatingip" "fip" {
- pool = data.vkcs_networking_network.extnet.name
- }
- resource "vkcs_compute_floatingip_associate" "fip" {
- floating_ip = vkcs_networking_floatingip.fip.address
- instance_id = vkcs_compute_instance.compute.id
- }
- output "instance_fip" {
- value = vkcs_networking_floatingip.fip.address
- }
Описание сценария:
1 - 3 | Получаем значение ранее созданной переменной compute_flavor, которая содержит название шаблона для виртуальной машины. |
5 - 7 | Читаем переменную image_flavor и образом диска, который нужно использовать при создании сервера. |
9 - 34 | Создаем виртуальную машину. |
10 | Задаем имя компьютеру compute-name. |
11 | В качестве шаблона конфигурации виртуальной машины используем Basic-1-2-20. Его мы определили на уровне создания переменных. |
12 | Ранее была определена ключевая пара для подключения по SSH. |
13 | Указываем, какие будем использовать группы безопасности для создаваемой машины. |
16 - 24 | Создаем диск для виртуальной машины. |
17 | В качестве образа используем Ubuntu 22.04. |
21 | Размер диска 8 Гб. |
26 - 28 | Указываем, что на сервере будет использоваться локальная сеть net. |
30 - 33 | Инстанс не будет создан, пока не будут созданы такие ресурсы, как сеть и подсеть. |
36 - 38 | Создаем динамический внешний IP-адрес. |
40 - 43 | Делаем привязку созданного сервера с динамическим адресом. |
45 - 47 | Выводим внешних адрес. |
Теперь можно запускать наш сценарий:
terraform apply
Утилита проведет анализ и выведет список изменений, которые будут проделаны на хостинге. Подтверждаем эти действия:
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Ждем выполнения операций. Готово.
Заходим на хостинг и проверяем, что изменения выполнены в соответствии с заданными алгоритмами сценария.
Если инфраструктура нам не нужна, удаляем все выполненные настройки командой:
terraform destroy
Также необходимо подтверждение:
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes