Replace auto-carved private subnets with explicit admin-supplied CIDRs
private_supernet/private_subnet_prefix_length/private_interface_count
(which auto-derived per-router-per-role micro-subnets via cidrsubnet())
are replaced by a single required variable, private_network_cidrs: one
CIDR per shared private network that router VMs get an interface into,
supplied explicitly by the admin - no auto-carving. Each router gets its
own port/IP inside every listed network (cidrhost(cidr, router_index+2)),
closer to the original lan_net design but generalized to N networks and
N routers. network-init.sh.tpl needed no changes - it already matches
interfaces by CIDR membership regardless of whether the CIDR is shared.
Also fixes a testing gap found along the way: `terraform validate` does
not enforce variable validation{} blocks for externally-supplied values
in this terraform version - only `plan`/`apply` do. The test suite now
exercises those validations for real via `terraform plan` against an
isolated, provider-free copy of variables.tf.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011hXR2ftXZZhJ4Y3XuSoR8r
This commit is contained in:
1 parent
5979a9a58b
commit
1ef4b12143
8 files changed
+290
-150
No files matched your search
+10
-3
@@ -17,15 +17,22 @@ username = "<ваш VK Cloud логин>"
|
||||
password = "<пароль>"
|
||||
project_id = "<ваш project_id>"
|
||||
ssh_key_name = "<имя загруженного SSH-ключа>"
|
||||
|
||||
private_network_cidrs = [
|
||||
"10.90.0.0/29",
|
||||
"10.90.0.8/29",
|
||||
]
|
||||
```
|
||||
|
||||
`private_network_cidrs` — обязательная переменная без значения по умолчанию: один CIDR-префикс на каждую приватную сеть, к которой будут подключены интерфейсы роутеров (один префикс = одна общая сеть = один приватный интерфейс на роутер). Автоматической нарезки нет — префиксы не должны пересекаться и должны вмещать минимум `router_count + 2` адреса.
|
||||
|
||||
## 3. (Опционально) масштабирование
|
||||
|
||||
По умолчанию: 2 роутера × 3 интерфейса (1 публичный + 2 приватных). Меняется без правки кода — либо раскомментировать нужные строки в `terraform.tfvars`, либо через переменные окружения:
|
||||
По умолчанию: 2 роутера × 3 интерфейса (1 публичный + 2 приватных, по числу префиксов в `private_network_cidrs`). Меняется без правки кода — либо через `terraform.tfvars`, либо через переменные окружения:
|
||||
|
||||
```bash
|
||||
export TF_VAR_router_count=4
|
||||
export TF_VAR_private_interface_count=3
|
||||
export TF_VAR_private_network_cidrs='["10.90.0.0/28","10.90.0.16/28","10.90.0.32/28"]'
|
||||
```
|
||||
|
||||
## 4. Развернуть
|
||||
@@ -41,7 +48,7 @@ terraform apply
|
||||
|
||||
## 5. Настроить Ansible
|
||||
|
||||
> ⚠️ Важно: `ansible/inventory.ini` и роли (`base`/`frr_router`/`keepalived`) пока жёстко рассчитаны на **2** роутера с интерфейсами `eth0`/`eth1` (VRRP-схема) — под новую N-роутерную/3-NIC архитектуру ещё не адаптированы. Для дефолтных значений (`router_count=2`, `private_interface_count=2`) впишите реальные `wan_ip`/`lan_ip`/GRE/BGP-параметры роутеров в `inventory.ini` вручную. При масштабировании выше 2 роутеров или интерфейсов Ansible-слой нужно дорабатывать отдельно.
|
||||
> ⚠️ Важно: `ansible/inventory.ini` и роли (`base`/`frr_router`/`keepalived`) пока жёстко рассчитаны на **2** роутера с интерфейсами `eth0`/`eth1` (VRRP-схема) — под новую N-роутерную/N-NIC архитектуру ещё не адаптированы. Для дефолтных значений (`router_count=2`, 2 записи в `private_network_cidrs`) впишите реальные `wan_ip`/`lan_ip`/GRE/BGP-параметры роутеров в `inventory.ini` вручную. При масштабировании выше 2 роутеров или интерфейсов Ansible-слой нужно дорабатывать отдельно.
|
||||
|
||||
```bash
|
||||
cd ansible
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# План внедрения: явная передача префиксов приватных сетей
|
||||
|
||||
Дата: 2026-09-03
|
||||
|
||||
## Проблема
|
||||
|
||||
Приватные подсети роутеров нарезались автоматически (`private_supernet` + `private_subnet_prefix_length` + `private_interface_count` → `cidrsubnet()`). Администратор должен явно передавать все адресные префиксы — по одному CIDR на каждую приватную сеть, к которой подключаются маршрутизаторы. Автоматической нарезки быть не должно.
|
||||
|
||||
Модель меняется: вместо N×router_count изолированных микроподсетей — N **общих** приватных сетей (по числу переданных префиксов), в каждой свой порт/IP на роутер (аналогично исходной `lan_net`/`lan_port1/2`, но обобщено на произвольное число сетей и роутеров).
|
||||
|
||||
## Шаги
|
||||
|
||||
1. `terraform/variables.tf`: удалить `private_supernet`, `private_subnet_prefix_length`, `private_interface_count`; добавить обязательную `private_network_cidrs` (list(string), без default, 3 validation-блока: непустой список, валидные CIDR, уникальность).
|
||||
2. `terraform/main.tf`: `router_priv_net`/`router_priv_subnet` — `for_each` по ролям (одна сеть на роль); `router_priv_port` — `for_each` по (роутер×роль), `fixed_ip = cidrhost(role_cidr, router_index + 2)`. `templatefile()` берёт CIDR из `local.private_network_cidr[role]`.
|
||||
3. `terraform/scripts/network-init.sh.tpl` — без изменений (сопоставление по CIDR-принадлежности не зависит от того, общий CIDR или уникальный).
|
||||
4. `terraform.tfvars` — рабочий пример `private_network_cidrs` вместо удалённых переменных.
|
||||
5. `terraform/tests/test_terraform_delivery.py` — обновить тесты под новую переменную/локали, убрать carving-коллизии, добавить проверку непересечения и вместимости CIDR.
|
||||
6. `README.md`/`docs/QUICKSTART.md` — обновить описание.
|
||||
7. Summary-документ по завершении.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `terraform fmt -check -recursive`.
|
||||
- Реальные `terraform init`/`validate` (локальный filesystem-mirror провайдера) на нескольких сочетаниях `router_count`/`private_network_cidrs`.
|
||||
- `venv/bin/pytest terraform/tests -v`.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Summary: явная передача префиксов приватных сетей
|
||||
|
||||
Дата: 2026-09-03
|
||||
План: [2026-09-03-explicit-private-network-cidrs-plan.md](2026-09-03-explicit-private-network-cidrs-plan.md)
|
||||
|
||||
## Что сделано
|
||||
|
||||
### `terraform/variables.tf`
|
||||
Удалены `private_supernet`, `private_subnet_prefix_length`, `private_interface_count`. Добавлена обязательная (без default) переменная `private_network_cidrs` (`list(string)`) с тремя validation-блоками: список не пуст, каждый элемент — валидный IPv4 CIDR (`can(cidrhost(c, 0))`), элементы уникальны.
|
||||
|
||||
### `terraform/main.tf`
|
||||
Модель изменена: вместо N×router_count изолированных микроподсетей (по одной на каждую пару "роутер+роль", auto-carved через `cidrsubnet()`) — N **общих** приватных сетей, по одной на каждый CIDR из `private_network_cidrs`. `router_priv_net`/`router_priv_subnet` теперь `for_each` только по ролям (`local.private_network_cidr`, карта role→CIDR); `router_priv_port` — `for_each` по (роутер×роль), с `fixed_ip = cidrhost(role_cidr, router_index + 2)` (`.2`=router1, `.3`=router2, ...). `templatefile()` берёт CIDR напрямую из `local.private_network_cidr[role]`.
|
||||
|
||||
### `terraform/scripts/network-init.sh.tpl`
|
||||
Не менялся — сопоставление интерфейсов по CIDR-принадлежности не зависит от того, общий CIDR или уникальный per-роутер.
|
||||
|
||||
### `terraform.tfvars`
|
||||
Заменены закомментированные `private_supernet`/`private_subnet_prefix_length`/`private_interface_count` на рабочий (не закомментированный, т.к. обязательный) пример:
|
||||
```hcl
|
||||
private_network_cidrs = [
|
||||
"10.90.0.0/29",
|
||||
"10.90.0.8/29",
|
||||
]
|
||||
```
|
||||
|
||||
### `terraform/tests/test_terraform_delivery.py`
|
||||
Существенно переработан (32 теста вместо 32 — состав изменился):
|
||||
- убраны carving-коллизии (`cidrsubnet`-реимплементация) — авто-нарезки больше нет;
|
||||
- добавлен `test_tfvars_private_network_cidrs_do_not_overlap_and_have_room_for_routers` — офлайн-проверка (`ipaddress`) примера из `terraform.tfvars`: без пересечений, вмещает `router_count + 2` адресов;
|
||||
- добавлены `test_private_network_cidrs_validation_is_enforced` и `test_router_count_validation_is_enforced` — **реальная** проверка срабатывания `validation`-блоков через `terraform plan` на изолированной копии одного `variables.tf` (без провайдера, без обращений к облаку);
|
||||
- параметризованный `test_terraform_init_and_validate_against_real_provider_schema` обновлён под `private_network_cidrs` (JSON-список через `TF_VAR_*`).
|
||||
|
||||
### `README.md` / `docs/QUICKSTART.md`
|
||||
Убрано описание авто-нарезки и "8192 блоков" (в README также устранён случайно задвоенный абзац из предыдущего шага). Добавлено описание новой модели (общие сети, явные префиксы) и актуальный пример `TF_VAR_private_network_cidrs`.
|
||||
|
||||
## Важная находка в процессе
|
||||
|
||||
**`terraform validate` не проверяет пользовательские `validation { ... }`-блоки переменных** для значений, заданных извне (`-var`/`TF_VAR_*`/tfvars) — эмпирически подтверждено на минимальном изолированном примере (без единого resource/provider) с этим бинарём Terraform (v1.16.1): `validate` даёт `Success!` даже для заведомо невалидных значений (`router_count=0`, дублирующиеся CIDR, пустой список, некорректный CIDR-синтаксис), тогда как `terraform plan` с теми же значениями корректно завершается ошибкой `Invalid value for variable`. Это касается не только новой переменной, но и ранее написанной `router_count >= 1`.
|
||||
|
||||
Из-за этого предыдущий вывод (в summary от 2026-09-03 про GitHub-зеркало провайдера) о том, что "реальный `terraform validate` подтверждает корректность конфигурации" был верен только в части совместимости со схемой провайдера — но не проверял ничего про custom variable validation. Это исправлено: теперь validation-блоки проверяются через `terraform plan` на изолированной копии `variables.tf` (без провайдера, без облака) — см. новые тесты выше.
|
||||
|
||||
## Верификация
|
||||
|
||||
- `venv/bin/terraform fmt -check -recursive` → чисто.
|
||||
- Реальные `terraform init`/`validate` (через локальный filesystem-mirror провайдера) на 3 сочетаниях `router_count`/`private_network_cidrs`, включая дефолт из `terraform.tfvars` → все успешны.
|
||||
- Реальный `terraform plan` на изолированном `variables.tf` — 4 негативных/позитивных сценария для `private_network_cidrs` и 3 для `router_count` → validation срабатывает корректно в обе стороны.
|
||||
- `venv/bin/pytest terraform/tests -v` → **32 passed**.
|
||||
Reference in new issue
Block a user