Terraform now provisions router_count IaaS Router VMs (default 2, no longer hardcoded to router1/router2), each with 1 public + private_interface_count isolated private interfaces (no shared LAN or VRRP between routers). Both counts scale via Terraform variables and TF_VAR_* environment variables. The post-install script became a Terraform template that matches interfaces to their expected subnet by CIDR instead of a fragile "first private IP" heuristic. Added an offline pytest suite (terraform/tests/) that checks the delivery's internal consistency and runs real terraform init/validate against the actual vkcs provider schema via a project-local filesystem mirror (provider binary fetched from its GitHub releases, bypassing the region-blocked HashiCorp registry) - no cloud credentials or API calls involved. terraform/versions.tf now declares the previously-missing required_providers block. Ansible (inventory.ini, base/frr_router/keepalived roles) still assumes the old 2-router/2-NIC/VRRP topology and is not yet adapted - documented as a follow-up, not addressed here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011hXR2ftXZZhJ4Y3XuSoR8r
6.8 KiB
6.8 KiB
Summary: адаптивное количество ВМ-маршрутизаторов и 3 интерфейса
Дата: 2026-09-03 План: 2026-09-03-adaptive-router-vm-count-plan.md
Что сделано
terraform/variables.tf
Добавлены переменные: router_count (default 2, >= 1), private_supernet (default 10.90.0.0/16), private_subnet_prefix_length (default 29, допустимо 28/29), router_availability_zones (default ["ME1"]).
terraform/main.tf
- Добавлен
locals.router_private_subnets— детерминированная непересекающаяся нарезка CIDR изprivate_supernetна пары (router_index × роль) черезcidrsubnet(). lan_port1/lan_port2(фиксированные порты на общей10.200.10.0/24) заменены наfor_each-ресурсыrouter_priv_net/router_priv_subnet/router_priv_port— по одной изолированной микросети на каждый (роутер, приватная роль).router1/router2заменены на единыйvkcs_compute_instance.routerсcount = var.router_count: WAN-сеть без изменений +dynamic "network"по 2 приватным портам;user_dataтеперь рендерится черезtemplatefile().lan_net/lan_subnet,private_sg,priv_srv_01/02/03не изменялись (отдельный сегмент приватных серверов).- Файл прогнан через
terraform fmt -recursive(единственные изменения — форматирование существующих строк, семантика не менялась).
terraform/scripts/network-init.sh → terraform/scripts/network-init.sh.tpl
- Файл переименован (
git mv) и превращён в Terraform-шаблон. - Все существующие bash brace-expansions (
${netmask},${partial_octet},${octets[@]}) экранированы как$${...}, чтобы Terraform не пытался их интерполировать. - WAN-детект (эвристика по первому публичному IP) не изменён.
- Приватные интерфейсы теперь определяются не эвристикой "первый приватный IP", а сопоставлением по CIDR: Terraform передаёт список
private_interfaces(по 2 записи{cidr, name}на роутер), из которого шаблонная директива%{ for pi in private_interfaces }генерирует bash-массивPRIV_TARGETS. Добавлены функцииip_to_int()/ip_in_cidr()для проверки принадлежности IP подсети. - netplan-конфиг: секция
wan-iface(eth0) без изменений; вместо единственнойlan-iface— цикл, генерирующий отдельнуюethernets-секцию на каждый найденный приватный интерфейс (eth1,eth2, ...), без default route (изолированные микросети). - Проверки/fail-hard/backup/apply/reboot логика сохранена.
terraform/terraform.tfvars
Добавлены закомментированные примеры новых переменных.
README.md
Обновлено описание архитектуры: N роутеров вместо пары, 3 интерфейса на роутер (1 публичный + 2 изолированных приватных, без общего LAN и без VRRP на роутерах), упомянуты новые переменные и то, что network-init.sh стал Terraform-шаблоном. Явно отмечено, что диаграммы (ports.svg, topology.svg) и Ansible-слой (ansible/inventory.ini, роли base/frr_router/keepalived) пока отражают старую схему — это отдельный будущий шаг.
Что осознанно не менялось
- Ansible-слой — по явному решению в рамках этого изменения.
ansible/inventory.iniи ролиbase/frr_router/keepalived/greжёстко используютeth0/eth1и только хостыrouter1/router2; с новым дизайном (N роутеров,eth1+eth2, без VRRP) они не совместимы и потребуют отдельной переработки перед реальным деплоем через Ansible. priv_srv_01/02/03иlan_net/lan_subnet— не связаны с роутерами, оставлены как есть.- Диаграммы (
img/*.svg) — не обновлялись, отражают старую топологию.
Верификация
terraform fmt -recursive— чисто (после автоформатирования).terraform init -backend=false— не выполнено: провайдерhashicorp/vkcsнедоступен из окружения (нетrequired_providersв репозитории и нет сети до его источника). Это ограничение окружения, не связанное с данным изменением — в репозитории изначально не было блокаrequired_providers.- Синтаксис
.tpl: выполнена симуляция рендерингаtemplatefile()(замена$${→${, подстановка тестовых значений вместо%{ for }-блока) +bash -n— прошло без ошибок. - Логика
ip_to_int()/ip_in_cidr()проверена отдельным bash-тестом на 7 сценариях (/29и/28, совпадения и несовпадения) — все прошли. terraform plan/applyс реальными VK Cloud credentials не выполнялись —terraform.tfvarsсодержит placeholder-значения,applyсоздаёт платные облачные ресурсы; это отдельное действие пользователя.
Известные ограничения / задел на будущее
- Ansible-слой требует отдельной доработки под 3 интерфейса и N роутеров (см. выше).
- В репозитории отсутствует
required_providers/lock-файл дляvkcs— это не связано с текущим изменением, но мешает локальнойterraform validate/init. - Диаграммы не обновлены под новую топологию.