Инструкция описывает, как создать виртуальную машину в облаке Cloud.ru Evolution и все зависимые ресурсы.
Установите Terraform и настройте провайдер, если он еще не установлен.
Создайте рабочую папку для проекта и проинициализируйте провайдер командой terraform init.
Для развертывания виртуальной машины в рабочей папке должны находиться следующие файлы:
Файл | Описание |
|---|---|
vm.tf | Основная конфигурация Terraform — содержит все ресурсы, переменные и провайдер. Единственный обязательный файл для запуска terraform apply. |
cloud-init.yaml.tpl | Шаблон cloud-init для первоначальной настройки ВМ (создание пользователя, SSH-ключи, hostname). Используется в vm.tf через функцию templatefile. |
inventory.sh | Вспомогательный скрипт — генерирует inventory.yaml для Ansible на основе terraform output. Не участвует в развертывании, используется после создания ВМ. |
Создайте в папке проекта файл cloud-init.yaml.tpl со следующим содержимым:
#cloud-configusers:- name: ubuntussh-authorized-keys:- ${ssh_public_key}groups: sudoshell: /bin/bashsudo: ['ALL=(ALL) NOPASSWD:ALL']# Сгенерируйте пароль командой:# MacOS: openssl passwd -6 "YourPassword123!"# Linux: mkpasswd -m sha-512 "YourPassword123!"passwd: "<YOUR_PASSWORD>"lock_passwd: falsehostname: ${vm_name}manage_etc_hosts: true
В поле passwd вставьте хеш пароля, сгенерированный одной из команд выше.
Создайте в папке проекта файл inventory.sh и сделайте его исполняемым (chmod +x inventory.sh):
#!/bin/bash# Получаем значения из Terraform outputVM_INTERNAL_IP=$(terraform output -raw vm_internal_ip 2>/dev/null)EXTERNAL_IP=$(terraform output -raw external_ip 2>/dev/null)if [ -z "$VM_INTERNAL_IP" ] || [ -z "$EXTERNAL_IP" ]; thenecho "Ошибка: не удалось получить IP адреса. Запустите terraform apply" >&2exit 1ficat << EOFall:hosts:evo-vm:ansible_host: ${EXTERNAL_IP}ansible_user: ubuntuansible_python_interpreter: auto_silentansible_ssh_private_key_file: ~/.ssh/id_rsa_agentansible_ssh_common_args: '-o StrictHostKeyChecking=no'children:cloudru_evolution:hosts:evo-vm:internal_ip: ${VM_INTERNAL_IP}EOF
Скрипт запускается после успешного terraform apply и генерирует файл inventory для Ansible.
Создайте файл vm.tf и скопируйте в него код, приведенный ниже. Вставьте свои значения в переменных.
# =============================================================================# vm.tf — полная конфигурация terraform для создания ВМ# со всеми зависимыми ресурсами на платформе Cloud.ru Evolution# =============================================================================terraform {required_providers {cloudru = {source = "cloud.ru/cloudru/cloud"version = "2.0.0"}}}# =============================================================================# Переменные — заполните своими значениями# =============================================================================variable "project_id" {type = stringdescription = "Идентификатор проекта из console.cloud.ru"default = "" # <-- ВСТАВЬТЕ ВАШ PROJECT ID}variable "auth_key_id" {type = stringdescription = "Идентификатор ключа доступа сервисного аккаунта"sensitive = truedefault = "" # <-- ВСТАВЬТЕ ВАШ AUTH KEY ID}variable "auth_secret" {type = stringdescription = "Секрет ключа доступа сервисного аккаунта"sensitive = truedefault = "" # <-- ВСТАВЬТЕ ВАШ AUTH SECRET}variable "vpc_id" {type = stringdescription = "Идентификатор VPC"default = "" # <-- ВСТАВЬТЕ ВАШ VPC ID}variable "my_ip_cidr" {type = stringdescription = "CIDR вашего IP-адреса для доступа по SSH (например 1.2.3.4/32)"default = "0.0.0.0/32" # <-- ВСТАВЬТЕ ВАШ IP В ФОРМАТЕ CIDR}variable "subnet_address" {type = stringdescription = "CIDR подсети"default = "10.0.0.0/24" # <-- ИЗМЕНИТЕ ПРИ НЕОБХОДИМОСТИ}variable "vm_name" {type = stringdescription = "Имя виртуальной машины"default = "tf-evo-vm"}variable "ssh_public_key_path" {type = stringdescription = "Путь к публичному SSH ключу"default = "~/.ssh/id_rsa.pub"}variable "disk_size" {type = numberdescription = "Размер диска в ГБ"default = 20}variable "disk_type" {type = stringdescription = "Тип диска"default = "SSD"}variable "flavor" {type = stringdescription = "Flavor ВМ"default = "gen-1-1"}variable "zone" {type = stringdescription = "Зона доступности"default = "ru.AZ-1"}# =============================================================================# Провайдер# =============================================================================provider "cloudru" {project_id = var.project_idauth_key_id = var.auth_key_idauth_secret = var.auth_secretendpoints = {iam_endpoint = "iam.api.cloud.ru:443"compute_endpoint = "compute.api.cloud.ru:443"}}# =============================================================================# Источники данных# =============================================================================data "cloudru_evolution_compute_image_collection" "ubuntu" {project_id = var.project_idpage_size = 100}# =============================================================================# Конфигурация cloud-init# =============================================================================locals {cloud_config = templatefile("${path.module}/cloud-init.yaml.tpl", {ssh_public_key = file(var.ssh_public_key_path)vm_name = var.vm_name})}# =============================================================================# Подсеть# =============================================================================resource "cloudru_evolution_compute_subnet" "example" {project_id = var.project_idname = "tf-evo-subnet"zone_identifier = {name = var.zone}description = "Подсеть для ВМ"subnet_address = var.subnet_addressrouted_network = truedefault = falsevpc_id = var.vpc_iddns_servers = {value = ["8.8.4.4", "8.8.8.8"]}}# =============================================================================# Группа безопасности# =============================================================================resource "cloudru_evolution_compute_security_group" "example" {project_id = var.project_idname = "tf-evo-sg"zone_identifier = {name = var.zone}description = "Группа безопасности для ВМ"}# =============================================================================# Правила группы безопасности# =============================================================================# SSH (22) — доступ только с вашего IPresource "cloudru_evolution_compute_security_group_rule" "ingress_ssh" {security_group_id = cloudru_evolution_compute_security_group.example.iddirection = "TRAFFIC_DIRECTION_INGRESS"ether_type = "ETHER_TYPE_IPV4"ip_protocol = "IP_PROTOCOL_TCP"port_range = "22:22"description = "SSH доступ с моего IP"remote_ip_prefix = var.my_ip_cidr}# HTTPS (443) — доступ отовсюдуresource "cloudru_evolution_compute_security_group_rule" "ingress_https" {security_group_id = cloudru_evolution_compute_security_group.example.iddirection = "TRAFFIC_DIRECTION_INGRESS"ether_type = "ETHER_TYPE_IPV4"ip_protocol = "IP_PROTOCOL_TCP"port_range = "443:443"description = "HTTPS доступ отовсюду"remote_ip_prefix = "0.0.0.0/0"}# Исходящий TCPresource "cloudru_evolution_compute_security_group_rule" "egress_tcp" {security_group_id = cloudru_evolution_compute_security_group.example.iddirection = "TRAFFIC_DIRECTION_EGRESS"ether_type = "ETHER_TYPE_IPV4"ip_protocol = "IP_PROTOCOL_TCP"port_range = "1:65535"description = "Разрешить весь исходящий TCP"remote_ip_prefix = "0.0.0.0/0"}# Исходящий UDPresource "cloudru_evolution_compute_security_group_rule" "egress_udp" {security_group_id = cloudru_evolution_compute_security_group.example.iddirection = "TRAFFIC_DIRECTION_EGRESS"ether_type = "ETHER_TYPE_IPV4"ip_protocol = "IP_PROTOCOL_UDP"port_range = "1:65535"description = "Разрешить весь исходящий UDP"remote_ip_prefix = "0.0.0.0/0"}# =============================================================================# Диск# =============================================================================resource "cloudru_evolution_compute_disk" "example" {project_id = var.project_idname = "tf-evo-disk"size = var.disk_sizezone_identifier = {name = var.zone}disk_type_identifier = {name = var.disk_type}description = "Загрузочный диск для ВМ"bootable = trueimage_id = [for img in data.cloudru_evolution_compute_image_collection.ubuntu.images : img.id if img.name == "ubuntu-22.04"][0]encrypted = falsereadonly = falseshared = false}# =============================================================================# Сетевой интерфейс# =============================================================================resource "cloudru_evolution_compute_interface" "example" {project_id = var.project_idname = "tf-evo-interface"zone_identifier = {name = var.zone}description = "Сетевой интерфейс для ВМ"subnet_id = cloudru_evolution_compute_subnet.example.idinterface_security_enabled = truesecurity_groups_identifiers = {value = [{id = cloudru_evolution_compute_security_group.example.id}]}external_ip_specs = {new_external_ip = true}type = "INTERFACE_TYPE_REGULAR"}# =============================================================================# Виртуальная машина# =============================================================================resource "cloudru_evolution_compute_vm" "example" {project_id = var.project_idname = var.vm_namezone_identifier = {name = var.zone}flavor_identifier = {name = var.flavor}description = "ВМ, созданная через Terraform"disk_identifiers = [{disk_id = cloudru_evolution_compute_disk.example.id}]network_interfaces = [{interface_id = cloudru_evolution_compute_interface.example.id}]cloud_init_userdata = base64encode(local.cloud_config)}# =============================================================================# Вывод значений# =============================================================================output "vm_id" {description = "ID виртуальной машины"value = cloudru_evolution_compute_vm.example.id}output "vm_name" {description = "Имя виртуальной машины"value = cloudru_evolution_compute_vm.example.name}output "vm_internal_ip" {description = "Внутренний IP адрес"value = cloudru_evolution_compute_interface.example.ip_address}output "external_ip" {description = "Внешний IP адрес"value = cloudru_evolution_compute_interface.example.external_ip.ip_address}
Перед запуском заполните переменные в блоке variables файла vm.tf.
Переменная | Описание | Где получить |
|---|---|---|
project_id | Идентификатор проекта | Консоль Cloud.ru — страница проекта |
auth_key_id | Идентификатор ключа доступа сервисного аккаунта | Консоль Cloud.ru — раздел сервисных аккаунтов |
auth_secret | Секрет ключа доступа сервисного аккаунта | Выдается при создании ключа доступа |
vpc_id | Идентификатор VPC | Консоль Cloud.ru — раздел сетей |
my_ip_cidr | CIDR вашего IP-адреса для SSH-доступа | Ваш внешний IP в формате x.x.x.x/32 |
Переменная | По умолчанию | Описание |
|---|---|---|
subnet_address | 10.0.0.0/24 | CIDR создаваемой подсети |
vm_name | tf-evo-vm | Имя виртуальной машины |
ssh_public_key_path | `` ~/.ssh/id_rsa.pub`` | Путь к публичному SSH-ключу |
disk_size | 20 | Размер загрузочного диска в ГБ |
disk_type | SSD | Тип диска |
flavor | gen-1-1 | Флейвор (конфигурация) ВМ |
zone | ru.AZ-1 | Зона доступности |
Инициализируйте Terraform и запустите создание ресурсов:
terraform init && terraform apply
Проверьте план создания ресурсов и подтвердите, введя yes.
После успешного завершения Terraform выведет IP-адреса созданной ВМ:
Outputs:vm_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"vm_name = "tf-evo-vm"vm_internal_ip = "10.0.0.x"external_ip = "x.x.x.x"
После создания ВМ подключитесь к ней по SSH:
ssh ubuntu@<external_ip>
Где <external_ip> — внешний IP-адрес из вывода Terraform.
Если вы планируете использовать Ansible для дальнейшей настройки ВМ, сгенерируйте inventory-файл:
./inventory.sh > inventory.yaml
Для удаления всех созданных ресурсов выполните:
terraform destroy
Проверьте список ресурсов, которые будут удалены, и подтвердите, введя yes.