Привет, Хабр! Сегодня поговорим про инфраструктуру как код. Почему Terraform уже не единственный игрок в мире IaC, а Pulumi становится всё более актуальным. Я расскажу, как эти инструменты работают, чем отличаются, и почему стоит присмотреться к Pulumi, особенно, если вы хотите гибкости и мощи в управлении облаками.

Почему IaC — это важно

В наше время автоматизация инфраструктуры — это не просто модный тренд, а необходимость. Вспомните старые времена: ручная настройка серверов, бесконечные конфиги, куча времени на развёртывание. Сейчас это как копать яму лопатой, стоя на ступени экскаватора. Мир ускорился до предела: бизнес требует гибкости, быстрого масштабирования и развёртывания новых фич. Если будем настраивать каждый сервер вручную, просто не успеем за рынком. IaC решает эту проблему. Мы просто описываем инфраструктуру кодом, а машина всё делает сама. И на этом пути уже есть свои классики.

Terraform даёт понятный декларативный язык HCL, с которым легко стартовать, особенно небольшим командам и стартапам. Всё просто: описал ресурсы, запустил — и инфраструктура создаётся. Удобно, надёжно и предсказуемо.

Но есть и минус — Terraform довольно консервативен. Когда хочется сделать что-то нестандартное, приходится туго. Его шаблоны ограничивают, гибкости мало.

Знакомьтесь, Pulumi — IaC нового поколения

Но законы рынка работают везде. Если есть спрос — будут и предложения. С появлением Pulumi — IaC стал проще. Вместо собственного языка Terraform появились привычные нам языки программирования, такие как JavaScript, Python, Go, .NET. Значит, мы можем писать инфраструктуру так, как пишем приложения — с циклами, условными операторами, функциями. Хотим динамическую инфраструктуру, которая меняется в зависимости от нагрузки —  пожалуйста! Нужно интегрировать вызовы API, запускать AWS Lambda прямо из кода инфраструктуры — без проблем.

Pulumi поддерживает динамические провайдеры — это огромный плюс, потому что облачные API постоянно меняются, а ждать обновления провайдера от Terraform бывает довольно долго. С Pulumi намного быстрее адаптироваться. Достаточно написать свой провайдер и сразу использовать новые возможности облака.

Как Pulumi меняет правила игры на примере Netbox

Netbox — популярный инструмент для учёта ресурсов. У него есть Terraform-провайдер, но он довольно жёсткий и не даёт быстро добавлять свою логику, например, для кастомных плагинов. С Pulumi можно написать простой Python-код, который создаст полноценного провайдера для Netbox, и управлять виртуальными машинами, интерфейсами и IP-адресами. Без громоздких бинарных провайдеров, без долгого ожидания обновлений. Это даёт свободу быстро менять и расширять инфраструктуру под свои нужды.

Можно быстро набросать простой код. Для примера возьмём Python (потому что я знаю его лучше других), который будет выполнять нужные нам функции:

import pulumi
import os
from pulumi.dynamic import ResourceProvider, CreateResult, UpdateResult, Resource, DiffResult
import pynetbox
import json

api_url = os.getenv('NETBOX_URL')
api_token = os.getenv('NETBOX_TOKEN')

class NetboxVMProvider(ResourceProvider):
    def __init__(self, api_url, token):
        self.nb = pynetbox.api(api_url, token=token)

    def create(self, props):
        vm = self.nb.virtualization.virtual_machines.create(
            name=props["name"],
            disk=props.get("disk"),
            vcpus=props.get("vcpus"),
            memory=props.get("memory"),
            site=props.get("site"),
            tenant=props.get("tenant"),
            platform=props.get("platform"),
            status='active',
            custom_fields={
                'Environments': f'{props.get("Environments")}', 
                "ResourceID": f'{props.get("ResourceID")}'
            }
        )

        netbox_interface = self.nb.virtualization.interfaces.create(
            virtual_machine=vm.id,
            name="eth0"
        )

        netbox_ip_address = self.nb.ipam.ip_addresses.create(
            address=props.get("address"),
            assigned_object_type='virtualization.vminterface',
            assigned_object_id=netbox_interface.id,
            dns_name=props.get("dns_name"),
            status='active'
        )

        vm.update({
            'primary_ip4': netbox_ip_address.id
        })

        vm_id = vm.id
        return CreateResult(id_=str(vm_id), outs={**props, "vm_id": vm_id})

    def update(self, id, olds, news):
        vm = self.nb.virtualization.virtual_machines.get(id)
        for key, value in news.items():
            setattr(vm, key, value)
        vm.save()
        return UpdateResult(outs={**news, "vm_id": id})

    def delete(self, id, props):
        vm = self.nb.virtualization.virtual_machines.get(id)
        vm.delete()

class NetboxVM(Resource, module="NetBox", name="VirtualMachine"):
    def __init__(self, name, props, opts=None):
        super().__init__(NetboxVMProvider(api_url, api_token), name, props, opts)

Таким вот нехитрым образом у нас получается полноценный провайдер без больших бинарников провайдера от Terraform. Причем мы можем менять его прямо на ходу! В этом нам помогают:

from pulumi.dynamic import ResourceProvider, CreateResult, UpdateResult, Resource, DiffResult

Далее остаётся описать взаимодействие с созданным динамическим провайдером:

vm = NetboxVM(
    f"netboxvm-{config.name}",
    {
        "name": config.name,
        "api_url": NETBOX_URL,
        "tenant": netbox_tenant.id,
        "platform": netbox_platform.id,
        "vcpus": cpu_core_count,
        "site": netbox_site.id,
        "memory": memory_size,
        "disk": config.system_disk_size,
        "dns_name": config.name,
        "address": network.ip4_addr,
        "Environments": SYS_ENV,
        "ResourceID": instance.id
    },
    opts=pulumi.ResourceOptions(
        parent=instance,
        depends_on=instance,
        ignore_changes=["__provider"]
    )
)

И готово!

Инфраструктура как часть приложения

Ещё один важный момент: с Pulumi IaC становится частью приложения. Можно создавать инфраструктуру, которая сама подстраивается под нагрузку, автоматически разворачивает тестовые окружения, оптимизирует затраты. Например, можно настроить автоматическую отправку уведомлений сотрудникам с безопасной передачей паролей через зашифрованные ссылки — всё это прямо в коде инфраструктуры. В Terraform такие сценарии требуют сложных обходных путей и внешних скриптов. С Pulumi всё намного проще. Вы можете брать свой любимый язык, а я для примера снова воспользуюсь Python.

Представьте, что мы создали учётные записи для нового сотрудника через Pulumi. Теперь нужно оповестить его и передать все доступы. При этом нельзя отправлять его пароль, даже одноразовый, через почту, мессенджер, смс и другие незащищенные каналы. Всё-таки безопасность должна быть безопасной.

Terraform не позволит выполнить произвольный код, если у него нет подходящего провайдера, а Pulumi создан для такого. Берём и пишем простой код:

def send_email(msg_to: str, msg_from: str, subject: str, body: str) -> None:
    msg = EmailMessage()
    msg.set_content(body)
    msg['Subject'] = subject
    msg['From'] = msg_from
    msg['To'] = msg_to

    s = smtplib.SMTP("SOME_SERVER")
    s.send_message(msg)
    s.quit()


def send_secret_email(msg_to: str, url: str) -> None:
    api_url = PULUMI_CONFIG.require("secrets_url")
    api_puburl = PULUMI_CONFIG.require("secrets_puburl")
    url = url.replace(api_url, api_puburl)
    
    body = (
        "Здравствуйте!\r\n\r\n"
        f"Ваш пароль от консоли Вы можете получить по ссылке {url}.\r\n\r\n"
        "Ссылка действительна в течении недели.\r\n"
        "для авторизации нажмите на IAM User Login и введите Account name: 123123"
    )
    subject = "Your password"
    msg_from = "no-reply-pulumi@example.com"

    send_email(msg_to, msg_from, subject, body)

Этот код поместит наш сгенерированный пароль в любую систему шифрования и отправит ссылку в почту. И всё это без какого-либо вмешательства ручных действий.

Конечно, мы можем взять Terraform, покрыть его большой кучей внешних скриптов bash или Python и получить почти то же самое, но… Через Pulumi мы всё получаем из коробки. Прямо как джинн, но не из бутылки, а из коробки. И желаний не три, а сколько хочешь.

Импорт и миграция из других инструментов

Pulumi умеет импортировать конфигурации из Terraform и CloudFormation, что облегчает переход. Вы не теряете наработки, а постепенно расширяете возможности, добавляя динамику и логику.

Так как у нас в распоряжении множество языков программирования, ничего не мешает дополнять наш IaC любыми функциями:

  • взаимодействие с собственными API;

  • вызов и взаимодействие с любыми внешними приложениями посредством SDK;

  • использование Lambda в любом моменте выполнения IaC.

И это далеко не весь список преимуществ, которые мы получаем. По факту он ограничен только нашей фантазией и…

Есть нюанс — нужен опыт

Pulumi не панацея, если вы вдруг подумали, что я работаю на Pulumi Corporation и продвигаю этот проект. Во-первых, это Open Source. Во-вторых, минусы тоже есть.

Pulumi — это не про «нажать кнопку и получить». Здесь нужна команда с хорошими навыками программирования. Если в Terraform можно взять готовый шаблон и чуть подправить, то для Pulumi, как это ни прискорбно, нужно уметь писать код, проектировать архитектуру и рефакторить. Это вызов, особенно для команд, где DevOps не программисты. Но если освоить Pulumi, вы получите безграничные возможности для автоматизации и управления. Это отличная альтернатива, особенно для крупных компаний, где идеи рождаются очень быстро, а архитектура «меняется каждую минуту».

Итоги. Когда что выбрать

Terraform — простой и надёжный выбор для проектов с понятными требованиями и небольшими командами.

Pulumi — для тех, кто хочет гибкости, динамики и готов инвестировать в развитие навыков программирования. В больших компаниях с быстро меняющейся архитектурой Pulumi становится незаменимым инструментом.

В итоге, не стоит смотреть на Terraform и Pulumi как на конкурентов. Они отлично дополняют друг друга. Можно использовать Terraform для стабильных базовых задач, а Pulumi — для сложных сценариев и кастомизации. Главное понимать, что IaC — это не просто код, а инструмент, который должен работать на вас и вашу команду.

Если хотите выйти за рамки шаблонов и сделать инфраструктуру живой и адаптивной — выберите Pulumi. Если нужна простота и проверенность — Terraform остаётся отличным вариантом. Решение за вами, просто расширяйте свои возможности новыми инструментами.

https://www.pulumi.com/ - Pulumi
https://www.terraform.io/ - Terraform
https://t.me/pulumi_ru - Русскоговорящие сообщество Pulumi
https://t.me/masikmos - Автор статьи

Комментарии (2)


  1. Andy_U
    14.05.2025 10:12

    У вас все отступы в коде пропали...


    1. masikm Автор
      14.05.2025 10:12

      Спасибо. Поправил