lenec ru

← все посты

Terraform vs Pulumi: IaC-инструменты — HCL или настоящий код

11K

Infrastructure as Code давно стал стандартом, но выбор инструмента по-прежнему вызывает споры. Terraform с его HCL — проверенный лидер. Pulumi предлагает писать инфраструктуру на TypeScript, Python или Go — без нового языка. Разберём, чем они отличаются на практике и когда какой выбрать.

Философия: декларативный HCL vs настоящий код

Terraform использует HCL — декларативный DSL, где вы описываете желаемое состояние:

resource "aws_instance" "api" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.medium"

  tags = {
    Name        = "api-server"
    Environment = var.environment
  }
}

Pulumi позволяет использовать обычный язык программирования:

import * as aws from "@pulumi/aws";

const api = new aws.ec2.Instance("api", {
  ami: "ami-0c55b159cbfafe1f0",
  instanceType: "t3.medium",
  tags: {
    Name: "api-server",
    Environment: config.require("environment"),
  },
});

На простых примерах разница минимальна. Она проявляется при сложной логике: циклы, условия, динамическая генерация ресурсов. В HCL это for_each, count, dynamic блоки — работает, но читается тяжело. В Pulumi — обычный for, if, функции.

State management

Terraform хранит state в файле terraform.tfstate. Для команды нужен remote backend:

terraform {
  backend "s3" {
    bucket         = "myorg-terraform-state"
    key            = "production/api.tfstate"
    region         = "eu-west-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

Вы сами управляете S3-бакетом, DynamoDB для блокировок, шифрованием. State содержит чувствительные данные — нужна строгая политика доступа.

Pulumi предлагает managed backend (Pulumi Cloud) из коробки или self-hosted (S3, Azure Blob, GCS). Pulumi Cloud автоматически шифрует секреты и управляет блокировками. Но это зависимость от SaaS — для некоторых команд стоп-фактор.

Модули и переиспользование

Terraform modules — директории с .tf файлами, параметризованные через variables:

module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "5.5.0"

  name            = "production"
  cidr            = "10.0.0.0/16"
  azs             = ["eu-west-1a", "eu-west-1b"]
  private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
}

Pulumi использует обычные классы и функции:

class VpcStack {
  public vpc: aws.ec2.Vpc;
  public privateSubnets: aws.ec2.Subnet[];

  constructor(name: string, opts: VpcOptions) {
    this.vpc = new aws.ec2.Vpc(`${name}-vpc`, {
      cidrBlock: opts.cidr,
      enableDnsHostnames: true,
    });

    this.privateSubnets = opts.azs.map((az, i) =>
      new aws.ec2.Subnet(`${name}-private-${i}`, {
        vpcId: this.vpc.id,
        cidrBlock: opts.privateSubnets[i],
        availabilityZone: az,
      })
    );
  }
}

Преимущество Pulumi: наследование, дженерики, интерфейсы. Terraform modules ограничены плоской структурой variables/outputs.

Тестирование

Terraform: terraform validate (синтаксис), terraform plan (предпросмотр), terratest (Go, интеграционные тесты с реальными ресурсами), terraform test (встроенный с 1.6, assertions на plan).

Pulumi — unit-тесты на родном языке без создания ресурсов:

import { describe, it, expect } from "vitest";

describe("API infrastructure", () => {
  it("should use t3.medium instance type", async () => {
    const instance = new aws.ec2.Instance("test", {
      instanceType: "t3.medium",
      ami: "ami-xxx",
    });
    const type = await new Promise<string>(resolve =>
      instance.instanceType.apply(resolve)
    );
    expect(type).toBe("t3.medium");
  });
});

Unit-тесты Pulumi работают через mocking — быстрее и дешевле, чем terratest с реальной инфраструктурой.

Экосистема

┌────────────────┬──────────────────┬──────────────────┐
│                │ Terraform        │ Pulumi           │
├────────────────┼──────────────────┼──────────────────┤
│ Providers      │ 4000+ (registry) │ 150+ native +    │
│                │                  │ все TF providers  │
│ Язык           │ HCL              │ TS, Python, Go,  │
│                │                  │ C#, Java, YAML   │
│ GitHub Stars   │ ~43k             │ ~22k             │
│ Вакансии       │ Значительно больше│ Растёт           │
└────────────────┴──────────────────┴──────────────────┘

Pulumi может использовать любой Terraform provider через bridge — экосистема провайдеров фактически общая. Но native Pulumi providers дают лучший DX с автодополнением и типизацией.

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

Terraform:

  • Команда уже знает HCL и имеет наработанные модули.
  • Инфраструктура стандартная, без сложной логики.
  • Важен найм — специалистов по Terraform на рынке больше.
  • Нужна максимальная зрелость и предсказуемость.

Pulumi:

  • Команда разработчиков, не желающих учить DSL.
  • Сложная инфраструктура: динамическая генерация, абстракции.
  • Нужны unit-тесты без реальных ресурсов.
  • Стек на TypeScript/Python — единый язык для приложения и инфраструктуры.

Вывод

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

Комментарии 0

  • Будьте первым, кто оставит комментарий.

Войдите, чтобы оставить комментарий.