linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
Intro
Lessons
Footer
linuxlab-УчебникиЦеныО платформеКонфиденциальность и куки
Copyright © 2026 LinuxLab. Все права защищены.
linuxlab.io
Учебники▾
  • Линукс и сети
    Файловая система, процессы, TCP/IP, BGP и OSPF
    →
  • Terraform и IaC
    HCL, state, plan/apply на sandbox LocalStack
    →
  • Git и GitHub
    Объектная модель, plumbing, ветвление, GitHub Actions
    →
Все учебники →
ЦеныО платформеВойтиСоздать аккаунт
/
  • Введение
  • Уроки
  • How it works
  • База знаний
  • Шпаргалка
  • Capstone
  • Собеседование
home/terraform/lessons/tf-advanced-02-cdktf-typescript

lesson ── terraform-advanced ── ~18 мин ── 7 шагов

CDKTF, Terraform из TypeScript

CDKTF, пишешь инфру на TypeScript, на выходе HCL и terraform.tfstate. В образе уже стоит cdktf-cli рядом с node и npm. На уроке нагенеришь stack, синтезируешь, посмотришь что получилось в HCL, deploy'нешь.

▶ интерактивный sandbox

Поднимется пара контейнеров: terraform 1.9 и localstack 3.8 в одной сети. В браузере откроется терминал, можно сразу terraform init. Каждый шаг проверяется автоматически. TTL 45 минут, без регистрации.

запустить sandbox →

stack ── terraform · localstack · 1 GB RAM · самоуничтожается через 45 мин простоя

Шаги

  1. 01

    Проверь cdktf-cli

    bash
    cd /home/student/cdktf-demo
    which cdktf
    cdktf --version
    node --version

    cdktf-cli забейкан в образ глобально (/usr/local/bin/cdktf), рядом с node 20 LTS и npm 10. Без npm install -g, экономит минуту установки и убирает зависимость от npm registry в рантайме.

    ✓ cdktf-cli на месте, версия отображается.

  2. 02

    Инициализируй TypeScript-проект

    bash
    cdktf init --template=typescript --local --project-name=cdktf-demo --project-description="demo" 2>&1 | tail -10
    ls
    cat cdktf.json

    --local, state локально (не в HCP Terraform). В проекте появились main.ts, cdktf.json, package.json, node_modules/.

    cdktf.json, главный config: какой язык, какие провайдеры подтягивать.

    ✓ TypeScript-проект готов.

  3. 03

    Добавь AWS-provider

    bash
    # отредактируй cdktf.json, добавь aws-provider
    python3 - <<'EOF'
    import json
    with open('cdktf.json') as f:
        c = json.load(f)
    c['terraformProviders'] = ['aws@~> 5.60']
    with open('cdktf.json', 'w') as f:
        json.dump(c, f, indent=2)
    EOF
    cat cdktf.json
    cdktf get 2>&1 | tail -5
    ls .gen/providers/aws/

    cdktf get сгенерировал TypeScript-типы для AWS-provider. Они лежат в .gen/. Без них TS не знает про S3Bucket, IamRole и т.д.

    ✓ AWS-провайдер type-bindings готовы.

  4. 04

    Напиши stack на TypeScript

    bash
    cat > main.ts <<'EOF'
    import { App, TerraformStack, TerraformOutput } from "cdktf";
    import { Construct } from "constructs";
    import { AwsProvider } from "./.gen/providers/aws/provider";
    import { S3Bucket } from "./.gen/providers/aws/s3-bucket";
    class CdktfDemoStack extends TerraformStack {
      constructor(scope: Construct, id: string) {
        super(scope, id);
        new AwsProvider(this, "aws", {
          region: "us-east-1",
          accessKey: "test",
          secretKey: "test",
          s3UsePathStyle: true,
          skipCredentialsValidation: true,
          skipMetadataApiCheck: "true",
          skipRequestingAccountId: true,
          endpoints: [{
            s3:  "http://localstack:4566",
            iam: "http://localstack:4566",
            sts: "http://localstack:4566",
          }],
        });
        const envs = ["dev", "stage", "prod"];
        const buckets = envs.map((env) =>
          new S3Bucket(this, `bucket-${env}`, {
            bucket: `linuxlab-cdktf-${env}`,
            tags: { Environment: env, ManagedBy: "cdktf" },
          })
        );
        new TerraformOutput(this, "bucket-ids", {
          value: buckets.map((b) => b.id),
        });
      }
    }
    const app = new App();
    new CdktfDemoStack(app, "demo");
    app.synth();
    EOF

    Три бакета через Array.map, это и есть преимущество CDKTF над нативным HCL. На HCL, for_each = toset(...), на TS, обычный цикл с типами.

    ✓ Stack на TypeScript готов. Теперь синтезируем.

  5. 05

    cdktf synth, посмотри сгенерированный HCL

    bash
    cdktf synth 2>&1 | tail -5
    cat cdktf.out/stacks/demo/cdk.tf.json | jq '.resource.aws_s3_bucket | keys'

    Видишь три ключа, bucket-dev, bucket-stage, bucket-prod. Это обычный JSON-формат HCL, Terraform его понимает.

    ✓ HCL сгенерирован. 3 бакета из одного array.map.

  6. 06

    cdktf deploy

    bash
    cdktf deploy demo --auto-approve 2>&1 | tail -10
    aws --endpoint-url=http://localstack:4566 s3 ls

    Видишь три бакета созданы. Под капотом cdktf deploy = synth + terraform init + terraform apply в cdktf.out/stacks/demo/.

    State, обычный terraform.tfstate в той же папке. Это значит: можно бросить CDKTF, удалить main.ts, написать HCL на ходу state совместим, ничего не теряешь.

    ✓ Три бакета развёрнуты через TypeScript.

    То же самое на OpenTofu

    OpenTofu держит CLI и state совместимыми с Terraform по командам этого шага: миграция обычно проходит через mv .terraform .terraform.bak; tofu init -upgrade. Но при первом переходе сделай backup state и прогон на feature-branch - расхождения концентрируются в новых фичах (variables в backend, state-encryption, OCI registry-backed модули). См. tf-opentofu-parity для полной матрицы.

    • → OpenTofu parity
  7. 07

    Когда CDKTF, оправдан

    Когда нативный HCL коротче, он выбор:

    hcl
    # HCL, 5 строк
    resource "aws_s3_bucket" "envs" {
      for_each = toset(["dev", "stage", "prod"])
      bucket   = "linuxlab-${each.key}"
    }

    Когда генерация сложнее, CDKTF выигрывает:

    typescript
    // 100 tenants из JSON, разная conf per tenant
    const tenants = require("./tenants.json");
    tenants.forEach((t: any) => {
      if (t.tier === "premium") {
        new PremiumTenantStack(app, `tenant-${t.id}`, t);
      } else {
        new BasicTenantStack(app, `tenant-${t.id}`, t);
      }
    });

    В HCL такое бы потребовало 3-4 модуля и hairy count = condition ? 1 : 0 логики. На TS, линейно.

    Запомни smell:

    • Меньше 50 ресурсов, простая инфра → нативный HCL.
    • Программируемая генерация (forEach, if, классы) → CDKTF.
    • Команда не знает TypeScript → точно нативный HCL.

    Cleanup:

    bash
    cdktf destroy demo --auto-approve 2>&1 | tail -3

    ✓ CDKTF использован осознанно. Дальше, свой provider на Go.

    Custom Construct, переиспользование без модулей

    Аналог Terraform-модуля в CDKTF, Construct:

    typescript
    import { Construct } from "constructs";
    import { S3Bucket } from "./.gen/providers/aws/s3-bucket";
    import { S3BucketVersioningA } from "./.gen/providers/aws/s3-bucket-versioning";
    interface AuditedBucketProps {
      name: string;
      tags?: { [key: string]: string };
    }
    export class AuditedBucket extends Construct {
      public readonly bucket: S3Bucket;
      constructor(scope: Construct, id: string, props: AuditedBucketProps) {
        super(scope, id);
        this.bucket = new S3Bucket(this, "bucket", {
          bucket: props.name,
          tags: props.tags,
        });
        new S3BucketVersioningA(this, "versioning", {
          bucket: this.bucket.id,
          versioningConfiguration: { status: "Enabled" },
        });
      }
    }
    // использование
    new AuditedBucket(this, "logs", { name: "linuxlab-logs" });

    Преимущества над Terraform-модулем: type-safe props, наследование (extends), композиция через TypeScript.

    • → CDKTF целиком

Что ты узнал

cdktf уже в образе. cdktf init --template=typescript, скелет. main.ts, App + Stack + Constructs. cdktf get, type bindings для провайдеров. cdktf synth, генерирует cdktf.out/stacks/<name>/cdk.tf.json. cdktf deploy, apply.

команды

  • cdktf --versioncdktf-cli предустановлен в sandbox-образе.
  • cdktf init --template=typescript --localскелет проекта.
  • cdktf getподтянуть type-bindings для провайдеров.
  • cdktf synthсгенерировать HCL.
  • cdktf deploy <stack>synth + apply одной командой.

концепции

  • · Class extends TerraformStack, один stack = одна root-Terraform-конфигурация
  • · Construct, переиспользуемый блок, аналог Terraform-модуля
  • · cdktf.out/, generated, gitignore

← предыдущий

Линтеры, fmt, validate, tflint

следующий →

Переменные: убираем хардкод

Footer
linuxlab-
Copyright © 2026 LinuxLab. Все права защищены.
Учебники
Цены
О платформе
Конфиденциальность и куки