CDKTF 0.11 и Python: пишем IaC без HCL на реальном примере Proxmox-провайдера
Terraform CDK 0.11 стабилизировал Python-привязки - тестируем CDKTF как альтернативу HCL для команд с Python-бэкграундом на примере модуля для Proxmox.
Terraform CDK (CDKTF) 0.11 (июнь 2022): стабилизация TypeScript/Python провайдеров, улучшенный CLI workflow
Terraform CDK, он же CDKTF, развивается уже больше года, но в релизе 0.11 что-то щёлкнуло - Python-провайдеры наконец перестали быть экспериментом на бумаге и стали чем-то, что можно брать на пилот. Мы и взяли.
Контекст такой: часть наших клиентов переходит на Proxmox как основную платформу виртуализации. IaC для Proxmox через Terraform и провайдер Telmate/proxmox - это HCL, который работает, но требует освоения синтаксиса. У части команд бэкграунд чисто Python, и HCL для них - ещё один язык, который нужно выучить. Логичный вопрос: зачем, если можно писать инфраструктуру на Python?
Что изменилось в CDKTF 0.11
До 0.11 генерация Python-привязок для провайдеров работала нестабильно: часть атрибутов терялась, типизация была частичной, CLI мог упасть при синтезе сложного стека. Для небольших экспериментов - сойдёт, для реального использования - раздражает.
В 0.11 HashiCorp переработала механизм генерации привязок. Ключевые изменения по существу:
- Генерация провайдеров через
cdktf provider addстала надёжной: правильно обрабатываются вложенные блоки, списки, computed-атрибуты. - CLI workflow -
cdktf synth,cdktf plan,cdktf deploy- работает предсказуемо и не теряет контекст между вызовами. - Размер пакетов уменьшился: провайдеры теперь разбиваются на отдельные модули, не нужно тащить всё целиком.
Это не значит, что всё идеально. CDKTF 0.11 - всё ещё пре-1.0. Но разница с 0.9-0.10 ощутима.
Структура пилота
Брали реальную задачу: описать типовую VM для application-сервера на Proxmox. То, что в HCL выглядит как 40 строк .tf-файла, мы хотели написать на Python с нормальными абстракциями - классом, дефолтами, переиспользованием.
Инициализация проекта:
cdktf init --template=python --local
cdktf provider add "telmate/proxmox@~>2.9.11"
cdktf provider add скачивает провайдер и генерирует Python-пакет с привязками. На Proxmox-провайдере генерация заняла около двух минут - провайдер нетривиальный по схеме.
Пример модуля
Вот упрощённая версия того, что получилось. Класс AppServerVM оборачивает ресурс ProxmoxVirtualMachine и задаёт дефолты для нашего типового профиля:
from constructs import Construct
from cdktf import TerraformStack
from cdktf_cdktf_provider_proxmox.virtual_machine import VirtualMachine, VirtualMachineDisk, VirtualMachineNetwork
class AppServerVM(Construct):
def __init__(
self,
scope: Construct,
id: str,
*,
node: str,
hostname: str,
cores: int = 4,
memory: int = 4096,
disk_size: str = "40G",
vlan_id: int = 100,
template: str = "almalinux-8-cloud",
):
super().__init__(scope, id)
VirtualMachine(
self,
"vm",
name=hostname,
target_node=node,
clone=template,
cores=cores,
memory=memory,
disk=[VirtualMachineDisk(
size=disk_size,
type="scsi",
storage="local-lvm",
)],
network=[VirtualMachineNetwork(
bridge="vmbr0",
model="virtio",
tag=vlan_id,
)],
os_type="cloud-init",
ipconfig0=f"ip=dhcp",
)
В стеке это используется так:
class InfraStack(TerraformStack):
def __init__(self, scope: Construct, ns: str):
super().__init__(scope, ns)
# Провайдер
ProxmoxProvider(self, "proxmox",
pm_api_url="https://pve01.example.com:8006/api2/json",
pm_api_token_id=os.environ["PM_TOKEN_ID"],
pm_api_token_secret=os.environ["PM_TOKEN_SECRET"],
)
AppServerVM(self, "app-01",
node="pve01",
hostname="app-01.example.com",
cores=8,
memory=8192,
)
AppServerVM(self, "app-02",
node="pve02",
hostname="app-02.example.com",
) # дефолты 4 core / 4G
Это уже ближе к тому, как команды пишут Python-код: дефолты в сигнатуре, переиспользование через класс, читаемость без знания HCL.
Что реально сработало
Абстракции естественны. Python-класс с дефолтными аргументами - понятная модель для любого питониста. HCL-модули с переменными делают то же самое, но через другой синтаксис, который нужно изучать отдельно.
Тесты. Это главный аргумент. К Python-коду можно написать юнит-тесты через pytest. Мы проверяем, что стек синтезируется корректно, что все ресурсы присутствуют, что параметры передаются правильно. В HCL аналог - только сторонние инструменты вроде Terratest, и это отдельная боль.
Переиспользование через пакеты. Класс AppServerVM можно упаковать в Python-пакет и использовать в нескольких проектах. Версионирование - стандартный pyproject.toml.
Где пока трудно
Честно: не всё гладко.
Генерация под нестандартные провайдеры. Proxmox-провайдер Telmate - не первоклассный. Часть атрибутов в схеме объявлена нечётко, и генерация иногда даёт привязки с Any-типами вместо нормальных. Не критично, но теряется статическая типизация именно там, где провайдер написан небрежно.
cdktf synth медленный. Синтез стека - это выполнение Python и генерация JSON с ресурсами. На больших стеках это заметно. HCL terraform plan работает быстрее.
Отладка через синтезированный JSON. Когда что-то идёт не так на уровне Terraform (уже после синтеза), нужно смотреть в cdktf.out/ и читать сгенерированный HCL/JSON. Это дополнительный слой между кодом и ошибкой.
Вывод на сейчас
CDKTF 0.11 - рабочий инструмент для пилота. Не для всех и не для всего, но для команды с Python-бэкграундом, которая разворачивает типовую инфраструктуру на Proxmox или другой платформе с Terraform-провайдером, это реальная альтернатива изучению HCL.
Мы продолжаем пилот - задействуем тот же подход на втором клиенте с другим профилем инфраструктуры. Если паттерн подтвердится, будем включать CDKTF Python в стандартный инструментарий для managed-сопровождения проектов, где команда уже пишет на Python.
HCL никуда не денется - он остаётся основным путём для Terraform. Но то, что теперь есть вменяемая альтернатива для определённого профиля команд, - это хорошая новость.
- Terraform 1.1 и блок moved: рефакторинг модулей без боли со state · 18 января 2022
- Proxmox VE 7.x как альтернатива VMware vSphere: первый пилот на 20 ВМ · 22 марта 2022