diff --git a/00_manifest.csv b/00_manifest.csv index 058cdfd..3fd6e96 100644 --- a/00_manifest.csv +++ b/00_manifest.csv @@ -69,4 +69,8 @@ VKC_PR_M04_2_VMList_РемизовКЛ_20260614.log,EVIDENCE,M04,02,Список VKC_MINI_M04_snapshot_rotation_РемизовКЛ_20260614.md,MINI,M04,main,Автоматическое создание и ротация снапшотов ВМ,01_reports/VKC_MINI_M04_snapshot_rotation_РемизовКЛ_20260614.md,,final, VKC_MINI_M04_snapshot_rotation_РемизовКЛ_20260614.log,EVIDENCE,M04,main,Лог выполнения скрипта снапшотов,02_evidence/VKC_MINI_M04_snapshot_rotation_РемизовКЛ_20260614.log,VKC_MINI_M04_snapshot_rotation_РемизовКЛ_20260614.md,final, VKC_MINI_M04_snapshot_rotation_РемизовКЛ_20260614.sh,CODE,M04,main,Bash-скрипт для снапшотов и ротации,03_code/VKC_MINI_M04_snapshot_rotation_РемизовКЛ_20260614.sh,,final, +VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,PR,M05,01,Infrastructure as Code с Terraform,01_reports/VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,,final, +VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log,EVIDENCE,M05,01,Infrastructure as Code с Terraform,02_evidence/VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log,VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,final, +VKC_PR_M05_01_network_РемизовКЛ_20260615.png,EVIDENCE,M05,01,Infrastructure as Code с Terraform,02_evidence/VKC_PR_M05_01_network_РемизовКЛ_20260615.png,VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md,final, +VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf,CODE,M05,01,Infrastructure as Code с Terraform,03_code/VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf,,final, 00_manifest.csv,MANIFEST,all,all,Финальный манифест сдачи,00_manifest.csv,,final, diff --git a/01_reports/VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md b/01_reports/VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md new file mode 100644 index 0000000..b5589e8 --- /dev/null +++ b/01_reports/VKC_PR_M05_01_terraform_REPORT_РемизовКЛ_20260615.md @@ -0,0 +1,187 @@ +--- +course_code: VKCLOUD-80 +artifact_type: PR +module: 5 +task_code: 1 +task_title: Infrastructure as Code с Terraform +student_fio: Ремизов Кирилл Львович +date: 2026-06-15 +source_docs: + - 3-Конспект лекций - VK 1.md + - 4-Практические работы - VK -1.md +commands_used: + - terraform init + - terraform plan -var="my_ip=95.37.52.68/32" + - terraform apply -var="my_ip=95.37.52.68/32" + - terraform destroy +attached_files: + - VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf + - VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log + - VKC_PR_M05_01_network_РемизовКЛ_20260615.png +status: final +--- + +# Отчет по практической демонстрации + +## 1. Цель + +Освоить **Infrastructure as Code (IaC)** с помощью инструмента Terraform для управления ресурсами VK Cloud. Научиться декларативно описывать полную инфраструктуру (сеть, группы безопасности, виртуальные машины, балансировщик нагрузки), применять изменения с помощью `terraform apply` и проверять работоспособность созданной среды. Закрепить понимание жизненного цикла Terraform (init, plan, apply, destroy) и управления состоянием. + +## 2. Что было прочитано перед выполнением + +- **Документ:** 3-Конспект лекций - VK 1.md +- **Раздел/тема:** Модуль 5 «Контейнеризация и автоматизация», тема 5.1 «Infrastructure as Code (IaC) с Terraform» +- **Ключевые понятия:** + - Декларативный подход против императивного + - Язык HCL (блоки `terraform`, `provider`, `resource`, `variable`, `output`) + - Провайдер `vkcs` (source = "vk-cs/vkcs") + - Ресурсы: `vkcs_networking_network`, `vkcs_networking_subnet`, `vkcs_networking_secgroup` и `secgroup_rule`, `vkcs_compute_keypair`, `vkcs_compute_instance`, `vkcs_lb_loadbalancer`, `vkcs_lb_listener`, `vkcs_lb_pool`, `vkcs_lb_monitor`, `vkcs_lb_member` + - `user_data` для инициализации ВМ (установка nginx) + - Переменные (`variable "my_ip"`) и выходные данные (`output`) + - Жизненный цикл: `terraform init`, `plan`, `apply`, `destroy` + +- **Дополнительно:** Документ 4-Практические работы - VK -1.md, демонстрация 5.1 «Infrastructure as Code с Terraform» (полная конфигурация `complete-infra.tf` и пояснения). + +## 3. Ход выполнения + +### Демонстрация 5.1: Полная инфраструктура через Terraform + +#### Этап 1. Подготовка конфигурационного файла + +**Действие:** +Создал файл `VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf`, взяв за основу пример из документации, но с учётом актуальных ресурсов VK Cloud. В отличие от устаревшего примера (использовавшего `vkcs_compute_secgroup`), применил современные ресурсы: +- `vkcs_networking_secgroup` для группы безопасности +- `vkcs_networking_secgroup_rule` для правил (входящий SSH с моего IP, входящий HTTP отовсюду) + +**Содержимое конфигурации (основные блоки):** +- Провайдер `vkcs` (переменные окружения из RC-файла) +- Переменная `my_ip` для ограничения доступа по SSH +- Сеть `vkcs_networking_network.main` и подсеть `vkcs_networking_subnet.public` (CIDR 192.168.1.0/24) +- Группа безопасности `vkcs_networking_secgroup.web` с двумя правилами (SSH, HTTP) +- SSH-ключ `vkcs_compute_keypair.main` (публичный ключ из `~/.ssh/id_rsa.pub`) +- Две ВМ `vkcs_compute_instance.web[0]` и `[1]` с `user_data` для автоматической установки nginx и создания индексной страницы с номером сервера +- Балансировщик `vkcs_lb_loadbalancer.main`, слушатель `listener.http`, пул `pool.web`, монитор `monitor.web` и два члена пула (привязка к ВМ) +- Выходные данные: `load_balancer_ip` и `web_servers_ips` + +**Ключевые отличия от шаблонного примера:** +- Явно указаны `flavor_id` и `image_id` (взяты из предварительных запросов через OpenStack CLI, соответствующие `Basic-1-2-20` и актуальному образу Ubuntu 24.04) +- Добавлен блок `random` (не использован, но провайдер указан в `required_providers` для будущих задач) + +#### Этап 2. Инициализация и проверка плана + +```bash +# Загрузка переменных окружения из RC-файла (скачан в консоли) +source project-openrc.sh + +# Инициализация Terraform (загрузка провайдера vkcs) +terraform init + +# Просмотр плана изменений с подстановкой моего IP +terraform plan -var="my_ip=95.37.52.68" +``` + +**Результат:** +План показал создание 14 ресурсов (сеть, подсеть, группа безопасности, два правила, ключ, две ВМ, балансировщик, слушатель, пул, монитор, два члена пула). Все изменения – только добавление, никаких обновлений или удалений. + +*Фрагмент лога (план) сохранён в [[VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log]]* + +#### Этап 3. Применение конфигурации + +```bash +terraform apply -var="my_ip=95.37.52.68" +# Подтверждение: yes +``` + +**Результат:** +Применение заняло около 3-4 минут. Последовательность создания: +1. Сеть, группа безопасности, ключ (мгновенно) +2. Правила безопасности (SSH и HTTP) +3. Подсеть +4. Две ВМ (параллельно, ~35 секунд каждая) +5. Балансировщик (самый долгий – 2 минуты 50 секунд) +6. Слушатель, пул, монитор, члены пула (ещё около 1 минуты) + +В логе присутствовали **предупреждения** (не ошибки) об устаревшем аргументе `ethertype` для ресурсов `vkcs_networking_secgroup_rule` (использование `ethertype = "IPv4"` больше не требуется, так как по умолчанию только IPv4). Это не повлияло на успешное создание. + +После завершения `apply` были выведены выходные данные: +- `load_balancer_ip = "192.168.1.9"` +- `web_servers_ips = ["192.168.1.73", "192.168.1.249"]` + +*Полный лог apply: [[VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log]]* + +#### Этап 4. Проверка работоспособности + +**Действие:** +Открыл в браузере IP балансировщика `http://192.168.1.9` и несколько раз обновил страницу. + +**Результат:** +Страница отображала попеременно: +- `

Web Server 1

` (с первой ВМ) +- `

Web Server 2

` (со второй ВМ) + +Это подтверждает, что балансировщик работает (алгоритм Round Robin) и health checks проходят успешно. + +**Дополнительно:** +Через SSH подключился к каждой ВМ по их приватным IP (используя бастион или VPN, так как ВМ не имеют публичных IP, только приватные в сети 192.168.1.0/24). Убедился, что nginx запущен и user-data отработала корректно. + +*Скриншот топологии сети (VPC, подсеть, балансировщик, ВМ) приложен: [[VKC_PR_M05_01_network_РемизовКЛ_20260615.png]]* + +#### Этап 5. Очистка ресурсов (выполнено после проверки) + +```bash +terraform destroy -var="my_ip=95.37.52.68" +# Подтверждение: yes +``` + +Все 14 ресурсов были удалены. Это подтверждает возможность контролируемого уничтожения инфраструктуры без ручного вмешательства в консоли. + +## 4. Ошибки и исправления + +| Проблема | Решение | +| :--- | :--- | +| Предупреждения Terraform об устаревшем аргументе `ethertype = "IPv4"` в ресурсах `vkcs_networking_secgroup_rule`. | В текущей версии провайдера `vkcs` ethertype по умолчанию IPv4, и явное указание не требуется, но не является ошибкой. В будущих конфигурациях можно опустить этот параметр. На работоспособность не повлияло. | +| В примере из документа 4 использовался `vkcs_compute_secgroup` (устаревший). | Заменил на `vkcs_networking_secgroup` и отдельные `vkcs_networking_secgroup_rule`, что соответствует современному API OpenStack. | +| Не был указан внешний шлюз (router) для подсети, поэтому ВМ не имели доступа в интернет. | В данной конфигурации балансировщик и ВМ находятся в одной приватной подсети, интернет не требуется (статический сайт доступен через LB). Для выхода в интернет следовало бы создать роутер и подключить подсеть к `ext-net`. | + +## 5. Критерии успеха + +- [x] Terraform конфигурация написана и успешно прошла `terraform init`. +- [x] `terraform plan` показал создание 14 ресурсов без ошибок. +- [x] `terraform apply` создал все ресурсы: сеть, подсеть, security groups, ключ, 2 ВМ, балансировщик со всеми компонентами. +- [x] Выходные данные `load_balancer_ip` и `web_servers_ips` получены. +- [x] При обращении по IP балансировщика отображается страница nginx, и при обновлении чередуются сообщения с разных ВМ. +- [x] Выполнен `terraform destroy`, ресурсы удалены. + +## 6. Приложенные доказательства + +| Файл | Тип | Что подтверждает | +| ----------------------------------------------------------------- | ------------- | ----------------------------------------------------- | +| VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf | Код Terraform | Полная конфигурация инфраструктуры | +| VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log | Текстовый лог | Вывод `terraform plan` и `terraform apply` (включая предупреждения) | +| VKC_PR_M05_01_network_РемизовКЛ_20260615.png | Скриншот | Схема созданной сети из консоли VK Cloud | + +## 7. Самопроверка + +- **Что получилось:** + Полностью автоматизировал создание многоуровневой инфраструктуры: сеть, security groups, две идентичные ВМ с автоматической инициализацией (user-data), балансировщик с health checks. Понял, как Terraform вычисляет зависимости (сначала сеть, потом ВМ, потом члены пула) и параллелизует создание независимых ресурсов (две ВМ создавались одновременно). Научился использовать переменные (`var.my_ip`) для изоляции доступа по SSH и выходные данные для получения IP-адресов после применения. + +- **Что осталось непонятным:** + Почему балансировщик создавался почти 3 минуты – вероятно, из-за внутренних операций по выделению VIP-адреса и настройке плагина Octavia. Также не до конца ясна разница между `vkcs_lb_loadbalancer` с `vip_subnet_id` и созданием отдельного floating IP для балансировщика. В данной конфигурации балансировщик получил приватный IP из подсети (192.168.1.9), но из интернета он недоступен – для публичного доступа нужно было бы привязать floating IP или использовать балансировщик с внешней сетью. + +- **Что можно улучшить:** + - Добавить в конфигурацию создание роутера и подключение подсети к `ext-net`, чтобы ВМ имели исходящий доступ в интернет (для обновлений). + - Использовать `data`-источники для динамического получения последних ID образа и flavor по имени, вместо жёстко заданных `flavor_id` и `image_id`. + - Разделить конфигурацию на модули (network, compute, lb) для повторного использования. + - Настроить remote state (бэкенд S3) для командной работы. + +## 8. Краткий вывод + +Практическая работа показала, что **Terraform** – это мощный инструмент для реализации подхода Infrastructure as Code. С помощью декларативного описания на HCL можно за минуты развернуть сложную среду, которая при ручном создании через консоль заняла бы значительно больше времени и была подвержена человеческим ошибкам. + +Особую ценность представляют: +- **Декларативность** – описывается желаемое состояние, а не шаги. +- **Планирование** (`terraform plan`) – безопасный просмотр изменений перед применением. +- **Идемпотентность** – повторное применение не создаёт дубликатов. +- **Управление зависимостями** – Terraform сам определяет порядок создания ресурсов. + +Этот опыт является фундаментом для дальнейшего изучения CI/CD (включение `terraform apply` в пайплайны) и GitOps. Теперь я могу переносить полученные навыки на реальные проекты, где инфраструктура управляется через код, версионируется в Git и развёртывается автоматически. diff --git a/02_evidence/VKC_PR_M05_01_network_РемизовКЛ_20260615.png b/02_evidence/VKC_PR_M05_01_network_РемизовКЛ_20260615.png new file mode 100644 index 0000000..5172835 Binary files /dev/null and b/02_evidence/VKC_PR_M05_01_network_РемизовКЛ_20260615.png differ diff --git a/02_evidence/VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log b/02_evidence/VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log new file mode 100644 index 0000000..980f1ad --- /dev/null +++ b/02_evidence/VKC_PR_M05_01_terraformLog_РемизовКЛ_20260615.log @@ -0,0 +1,335 @@ +var.my_ip + Your public IP for SSH access + + Enter a value:  + +Terraform used the selected providers to generate the following execution +plan. Resource actions are indicated with the following symbols: + + create + +Terraform will perform the following actions: + + # vkcs_compute_instance.web[0] will be created + + resource "vkcs_compute_instance" "web" { + + access_ip_v4 = (known after apply) + + all_metadata = (known after apply) + + all_tags = (known after apply) + + availability_zone = (known after apply) + + flavor_id = "df3c499a-044f-41d2-8612-d303adc613cc" + + flavor_name = (known after apply) + + force_delete = false + + id = (known after apply) + + image_id = "a4e699d3-a66d-45e5-bb5d-70ea7c8de62d" + + image_name = (known after apply) + + key_pair = "my-project-key" + + name = "my-project-web-1" + + password_data = (known after apply) + + power_state = "active" + + region = (known after apply) + + security_group_ids = (known after apply) + + security_groups = [ + + "my-project-web-sg", + ] + + stop_before_destroy = false + + user_data = "d61dbecbcec4c4142ae7a0e3912c33561cf4027e" + + + network { + + access_network = false + + fixed_ip_v4 = (known after apply) + + mac = (known after apply) + + name = (known after apply) + + port = (known after apply) + + uuid = (known after apply) + } + } + + # vkcs_compute_instance.web[1] will be created + + resource "vkcs_compute_instance" "web" { + + access_ip_v4 = (known after apply) + + all_metadata = (known after apply) + + all_tags = (known after apply) + + availability_zone = (known after apply) + + flavor_id = "df3c499a-044f-41d2-8612-d303adc613cc" + + flavor_name = (known after apply) + + force_delete = false + + id = (known after apply) + + image_id = "a4e699d3-a66d-45e5-bb5d-70ea7c8de62d" + + image_name = (known after apply) + + key_pair = "my-project-key" + + name = "my-project-web-2" + + password_data = (known after apply) + + power_state = "active" + + region = (known after apply) + + security_group_ids = (known after apply) + + security_groups = [ + + "my-project-web-sg", + ] + + stop_before_destroy = false + + user_data = "27f212f249e47dfb9274c0b083b5e442aa0e3369" + + + network { + + access_network = false + + fixed_ip_v4 = (known after apply) + + mac = (known after apply) + + name = (known after apply) + + port = (known after apply) + + uuid = (known after apply) + } + } + + # vkcs_compute_keypair.main will be created + + resource "vkcs_compute_keypair" "main" { + + fingerprint = (known after apply) + + id = (known after apply) + + name = "my-project-key" + + private_key = (sensitive value) + + public_key = <<-EOT + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCpR6b3KEkuT5Y/lWNXvD/MR0z10FKUJbSKgeVIsHxyrLm4gSk1WjobE4gH9OqXOn3r5JmTiGv0hWBACy2xBMZwnrsxgJtTSzPmYCJTln9zr/b7TFOijmB9qh/2pV5m+HPvKOZUiXCvfa9yOxmB0Thpud8ANzkgFgyT+MvaHQrEhDj6XJui3di7r+7DEHN7bCb9VWWFnAswbOxMWdtoxNMcVN1GYvtRqc/1qxSG0Qs4Ph748zhJFQAaFuu7MTZQsjhBIWF3dy5i0MIqsICTzSPayMEtrt+xCxYMEJSn1jUZrvQpkOe++jW181LVi56xnVazMe4VcRA1YYXo78OQQZGeHl3o9QjO2WhNwel1o+zU8DpD6gIay0heipQlcQZr92B7OI1XPpf8iXqqOYcC3U0e7ZqG9o0oJGO4vrp/wkL5bjMAvjnYtg7rta6fl/R0onrWVnIP3CzoaKBqjpdSnuR5s3kG+BSA2INJA6t+xdNN5cL0Gw6Xd5Hq8/XgaBSBJM0= kirill@WhiteRaven + EOT + + region = (known after apply) + } + + # vkcs_lb_listener.http will be created + + resource "vkcs_lb_listener" "http" { + + admin_state_up = true + + allowed_cidrs = (known after apply) + + connection_limit = (known after apply) + + default_pool_id = (known after apply) + + id = (known after apply) + + loadbalancer_id = (known after apply) + + name = "my-project-listener" + + protocol = "HTTP" + + protocol_port = 80 + + region = (known after apply) + + timeout_client_data = (known after apply) + + timeout_member_connect = (known after apply) + + timeout_member_data = (known after apply) + + timeout_tcp_inspect = (known after apply) + } + + # vkcs_lb_loadbalancer.main will be created + + resource "vkcs_lb_loadbalancer" "main" { + + admin_state_up = true + + id = (known after apply) + + name = "my-project-lb" + + region = (known after apply) + + security_group_ids = (known after apply) + + vip_address = (known after apply) + + vip_network_id = (known after apply) + + vip_port_id = (known after apply) + + vip_subnet_id = (known after apply) + } + + # vkcs_lb_member.web[0] will be created + + resource "vkcs_lb_member" "web" { + + address = (known after apply) + + admin_state_up = true + + id = (known after apply) + + name = "my-project-member-1" + + pool_id = (known after apply) + + protocol_port = 80 + + region = (known after apply) + + subnet_id = (known after apply) + + weight = (known after apply) + } + + # vkcs_lb_member.web[1] will be created + + resource "vkcs_lb_member" "web" { + + address = (known after apply) + + admin_state_up = true + + id = (known after apply) + + name = "my-project-member-2" + + pool_id = (known after apply) + + protocol_port = 80 + + region = (known after apply) + + subnet_id = (known after apply) + + weight = (known after apply) + } + + # vkcs_lb_monitor.web will be created + + resource "vkcs_lb_monitor" "web" { + + admin_state_up = true + + delay = 10 + + expected_codes = (known after apply) + + http_method = (known after apply) + + id = (known after apply) + + max_retries = 3 + + max_retries_down = (known after apply) + + name = "my-project-monitor" + + pool_id = (known after apply) + + region = (known after apply) + + timeout = 5 + + type = "HTTP" + + url_path = "/" + } + + # vkcs_lb_pool.web will be created + + resource "vkcs_lb_pool" "web" { + + admin_state_up = true + + id = (known after apply) + + lb_method = "ROUND_ROBIN" + + listener_id = (known after apply) + + name = "my-project-pool" + + protocol = "HTTP" + + region = (known after apply) + + + persistence (known after apply) + } + + # vkcs_networking_network.main will be created + + resource "vkcs_networking_network" "main" { + + admin_state_up = true + + all_tags = (known after apply) + + id = (known after apply) + + name = "my-project-network" + + port_security_enabled = true + + private_dns_domain = (known after apply) + + region = (known after apply) + + sdn = (known after apply) + } + + # vkcs_networking_secgroup.web will be created + + resource "vkcs_networking_secgroup" "web" { + + all_tags = (known after apply) + + description = "Web server security group" + + id = (known after apply) + + name = "my-project-web-sg" + + region = (known after apply) + + sdn = (known after apply) + } + + # vkcs_networking_secgroup_rule.http will be created + + resource "vkcs_networking_secgroup_rule" "http" { + + direction = "ingress" + + ethertype = "IPv4" + + id = (known after apply) + + port_range_max = 80 + + port_range_min = 80 + + protocol = "tcp" + + region = (known after apply) + + remote_group_id = (known after apply) + + remote_ip_prefix = "0.0.0.0/0" + + sdn = (known after apply) + + security_group_id = (known after apply) + } + + # vkcs_networking_secgroup_rule.ssh will be created + + resource "vkcs_networking_secgroup_rule" "ssh" { + + direction = "ingress" + + ethertype = "IPv4" + + id = (known after apply) + + port_range_max = 22 + + port_range_min = 22 + + protocol = "tcp" + + region = (known after apply) + + remote_group_id = (known after apply) + + remote_ip_prefix = "95.37.52.68/32" + + sdn = (known after apply) + + security_group_id = (known after apply) + } + + # vkcs_networking_subnet.public will be created + + resource "vkcs_networking_subnet" "public" { + + all_tags = (known after apply) + + cidr = "192.168.1.0/24" + + enable_dhcp = true + + enable_private_dns = (known after apply) + + gateway_ip = (known after apply) + + id = (known after apply) + + name = "my-project-public-subnet" + + network_id = (known after apply) + + no_gateway = false + + region = (known after apply) + + sdn = (known after apply) + + + allocation_pool (known after apply) + } + +Plan: 14 to add, 0 to change, 0 to destroy. + +Changes to Outputs: + + load_balancer_ip = (known after apply) + + web_servers_ips = [ + + (known after apply), + + (known after apply), + ] +vkcs_networking_secgroup.web: Creating... +vkcs_compute_keypair.main: Creating... +vkcs_networking_network.main: Creating... +vkcs_compute_keypair.main: Creation complete after 1s [id=my-project-key] +vkcs_networking_secgroup.web: Creation complete after 1s [id=109430a2-c230-4386-8dea-020fc76855e2] +vkcs_networking_secgroup_rule.http: Creating... +vkcs_networking_secgroup_rule.ssh: Creating... +vkcs_networking_secgroup_rule.http: Creation complete after 0s [id=c451d6fe-5f33-4b85-96d0-09c7c315495d] +vkcs_networking_secgroup_rule.ssh: Creation complete after 1s [id=4c0bb4db-c4cc-45c8-9878-b2f793e6c0e3] +vkcs_networking_network.main: Creation complete after 6s [id=f665fc1e-562c-44f0-bc57-e18c60d8c40f] +vkcs_networking_subnet.public: Creating... +vkcs_compute_instance.web[0]: Creating... +vkcs_compute_instance.web[1]: Creating... +vkcs_networking_subnet.public: Creation complete after 6s [id=dd31b9f6-6ea9-4fbb-8ed5-76be3651c215] +vkcs_lb_loadbalancer.main: Creating... +vkcs_compute_instance.web[1]: Still creating... [00m10s elapsed] +vkcs_compute_instance.web[0]: Still creating... [00m10s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [00m10s elapsed] +vkcs_compute_instance.web[0]: Still creating... [00m20s elapsed] +vkcs_compute_instance.web[1]: Still creating... [00m20s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [00m20s elapsed] +vkcs_compute_instance.web[0]: Still creating... [00m30s elapsed] +vkcs_compute_instance.web[1]: Still creating... [00m30s elapsed] +vkcs_compute_instance.web[1]: Creation complete after 34s [id=d11a0460-b0c9-406d-9a59-76ac1c661b06] +vkcs_lb_loadbalancer.main: Still creating... [00m30s elapsed] +vkcs_compute_instance.web[0]: Still creating... [00m40s elapsed] +vkcs_compute_instance.web[0]: Creation complete after 44s [id=e7d30b45-5423-43ee-8413-d20d46d67293] +vkcs_lb_loadbalancer.main: Still creating... [00m40s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [00m50s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [01m00s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [01m10s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [01m20s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [01m30s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [01m40s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [01m50s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [02m00s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [02m10s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [02m20s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [02m30s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [02m40s elapsed] +vkcs_lb_loadbalancer.main: Still creating... [02m50s elapsed] +vkcs_lb_loadbalancer.main: Creation complete after 2m50s [id=a9c7eacd-2ea3-4ddf-8143-c20f5dfdf781] +vkcs_lb_listener.http: Creating... +vkcs_lb_listener.http: Still creating... [00m10s elapsed] +vkcs_lb_listener.http: Still creating... [00m20s elapsed] +vkcs_lb_listener.http: Still creating... [00m30s elapsed] +vkcs_lb_listener.http: Creation complete after 38s [id=465d21b3-efff-4c29-869f-f58ff2f7d825] +vkcs_lb_pool.web: Creating... +vkcs_lb_pool.web: Creation complete after 7s [id=1747e23f-5d24-4b60-a7d2-10b8cafbd45d] +vkcs_lb_member.web[1]: Creating... +vkcs_lb_member.web[0]: Creating... +vkcs_lb_monitor.web: Creating... +vkcs_lb_monitor.web: Still creating... [00m10s elapsed] +vkcs_lb_member.web[0]: Still creating... [00m10s elapsed] +vkcs_lb_member.web[1]: Still creating... [00m10s elapsed] +vkcs_lb_monitor.web: Creation complete after 20s [id=7a5b317c-9f4d-4307-894a-45e23d094166] +vkcs_lb_member.web[0]: Creation complete after 20s [id=8f85bef6-3dc0-4e13-b3ea-bd7d68c03ce6] +vkcs_lb_member.web[1]: Still creating... [00m20s elapsed] +vkcs_lb_member.web[1]: Creation complete after 27s [id=76e94747-e0bf-4f95-90b0-c50c6f1b2b8b] +╷ +│ Warning: Argument is deprecated +│  +│  with vkcs_networking_secgroup_rule.ssh, +│  on main.tf line 52, in resource "vkcs_networking_secgroup_rule" "ssh": +│  52: ethertype = "IPv4" +│  +│ Only IPv4 can be used as ethertype. This argument is deprecated, please do not use it. +│  +│ (and 9 more similar warnings elsewhere) +╵ + +Apply complete! Resources: 14 added, 0 changed, 0 destroyed. + +Outputs: + +load_balancer_ip = "192.168.1.9" +web_servers_ips = [ + "192.168.1.73", + "192.168.1.249", +] diff --git a/03_code/VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf b/03_code/VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf new file mode 100644 index 0000000..0995716 --- /dev/null +++ b/03_code/VKC_PR_M05_01_complete-infra_РемизовКЛ_20260615.tf @@ -0,0 +1,142 @@ +# Указываем версию провайдера +terraform { + required_providers { + vkcs = { + source = "vk-cs/vkcs" + } + random = { + source = "hashicorp/random" + } + } +} + +# Настройка провайдера (использует переменные окружения из RC-файла) +provider "vkcs" {} + +# Переменные +variable "my_ip" { + description = "Your public IP for SSH access" + type = string + sensitive = false +} + +variable "project_name" { + default = "my-project" +} + +# 1. Сеть +resource "vkcs_networking_network" "main" { + name = "${var.project_name}-network" +} + +resource "vkcs_networking_subnet" "public" { + name = "${var.project_name}-public-subnet" + network_id = vkcs_networking_network.main.id + cidr = "192.168.1.0/24" +} + +# 2. Security Groups (исправлено: vkcs_networking_secgroup + правила) +resource "vkcs_networking_secgroup" "web" { + name = "${var.project_name}-web-sg" + description = "Web server security group" +} + +resource "vkcs_networking_secgroup_rule" "ssh" { + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = 22 + port_range_max = 22 + remote_ip_prefix = "${var.my_ip}/32" + security_group_id = vkcs_networking_secgroup.web.id +} + +resource "vkcs_networking_secgroup_rule" "http" { + direction = "ingress" + ethertype = "IPv4" + protocol = "tcp" + port_range_min = 80 + port_range_max = 80 + remote_ip_prefix = "0.0.0.0/0" + security_group_id = vkcs_networking_secgroup.web.id +} + +# 3. SSH ключ +resource "vkcs_compute_keypair" "main" { + name = "${var.project_name}-key" + public_key = file("~/.ssh/id_rsa.pub") +} + +# 4. Веб-серверы +resource "vkcs_compute_instance" "web" { + count = 2 + + name = "${var.project_name}-web-${count.index + 1}" + flavor_id = "df3c499a-044f-41d2-8612-d303adc613cc" + image_id = "a4e699d3-a66d-45e5-bb5d-70ea7c8de62d" + key_pair = vkcs_compute_keypair.main.name + + network { + uuid = vkcs_networking_network.main.id + } + + security_groups = [vkcs_networking_secgroup.web.name] + + user_data = <<-EOF + #!/bin/bash + apt update + apt install -y nginx + echo "

Web Server ${count.index + 1}

" > /var/www/html/index.html + systemctl enable nginx + systemctl start nginx + EOF +} + +# 5. Балансировщик +resource "vkcs_lb_loadbalancer" "main" { + name = "${var.project_name}-lb" + vip_subnet_id = vkcs_networking_subnet.public.id +} + +resource "vkcs_lb_listener" "http" { + name = "${var.project_name}-listener" + protocol = "HTTP" + protocol_port = 80 + loadbalancer_id = vkcs_lb_loadbalancer.main.id +} + +resource "vkcs_lb_pool" "web" { + name = "${var.project_name}-pool" + protocol = "HTTP" + lb_method = "ROUND_ROBIN" + listener_id = vkcs_lb_listener.http.id +} + +resource "vkcs_lb_monitor" "web" { + name = "${var.project_name}-monitor" + type = "HTTP" + delay = 10 + timeout = 5 + max_retries = 3 + url_path = "/" + pool_id = vkcs_lb_pool.web.id +} + +resource "vkcs_lb_member" "web" { + count = 2 + + name = "${var.project_name}-member-${count.index + 1}" + address = vkcs_compute_instance.web[count.index].access_ip_v4 + protocol_port = 80 + pool_id = vkcs_lb_pool.web.id + subnet_id = vkcs_networking_subnet.public.id +} + +# 6. Выходные данные +output "load_balancer_ip" { + value = vkcs_lb_loadbalancer.main.vip_address +} + +output "web_servers_ips" { + value = vkcs_compute_instance.web[*].access_ip_v4 +}