lenec ru

← все посты

Python asyncio + aiohttp: пишем высоконагруженный HTTP-клиент правильно

18K

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

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

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

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

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

resource "aws_security_group" "api" {
  name = "api-sg"

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

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"),
  },
});

const sg = new aws.ec2.SecurityGroup("api-sg", {
  ingress: [{
    fromPort: 443,
    toPort: 443,
    protocol: "tcp",
    cidrBlocks: ["0.0.0.0/0"],
  }],
});

На простых примерах разница минимальна. Она проявляется при сложной логике: циклы, условия, динамическая генерация ресурсов. В 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):

# Managed backend (по умолчанию)
pulumi login

# Self-hosted S3
pulumi login s3://myorg-pulumi-state

# Локально (для экспериментов)
pulumi login --local

Pulumi Cloud автоматически шифрует секреты, управляет блокировками и показывает историю изменений в UI. Но это зависимость от 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"]
  public_subnets  = ["10.0.101.0/24", "10.0.102.0/24"]

  enable_nat_gateway = true
}

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,
      })
    );
  }
}

// Использование
const network = new VpcStack("prod", {
  cidr: "10.0.0.0/16",
  azs: ["eu-west-1a", "eu-west-1b"],
  privateSubnets: ["10.0.1.0/24", "10.0.2.0/24"],
});

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

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

Terraform — тестирование через внешние инструменты:

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

Pulumi — тесты на родном языке:

import * as pulumi from "@pulumi/pulumi";
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 instanceType = await new Promise<string>((resolve) =>
      instance.instanceType.apply(resolve)
    );

    expect(instanceType).toBe("t3.medium");
  });

  it("should tag all resources with environment", async () => {
    // Policy test: все ресурсы должны иметь тег Environment
  });
});

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

Экосистема: providers, registry, community

┌────────────────┬──────────────────┬──────────────────┐
│                │ Terraform        │ Pulumi           │
├────────────────┼──────────────────┼──────────────────┤
│ Providers      │ 4000+ (registry) │ 150+ native +    │
│                │                  │ все TF providers  │
│ Registry       │ registry.terraform.io │ pulumi.com/registry │
│ Язык           │ HCL              │ TS, Python, Go,  │
│                │                  │ C#, Java, YAML   │
│ GitHub Stars   │ ~43k             │ ~22k             │
│ Вакансии       │ Значительно больше│ Растёт           │
│ Документация   │ Обширная         │ Хорошая          │
└────────────────┴──────────────────┴──────────────────┘

Ключевой момент: Pulumi может использовать любой Terraform provider через bridge. Это значит, что экосистема провайдеров фактически общая. Но native Pulumi providers (AWS, Azure, GCP, Kubernetes) дают лучший developer experience с автодополнением и типизацией.

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

Выбирайте Terraform, если:

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

Выбирайте Pulumi, если:

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

Вывод

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

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

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

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