MLOps Path

3.8.2 · блок 3

Terraform на практике: plan, apply, modules

Terraform на практике: plan, apply, modules

Зачем это нужно

Предыдущий урок — «зачем IaC». Здесь — как читать и безопасно менять Terraform в команде: variables, outputs, modules, workspaces (или отдельные каталоги env), типичный workflow MR. Даже если вы не platform engineer, вы будете review'ить MR с новым bucket для dataset или quota на namespace через Terraform provider Kubernetes.

Основные идеи

Минимальный root module.


terraform {
  required_version = ">= 1.5"
  required_providers {
    kubernetes = {
      source  = "hashicorp/kubernetes"
      version = "~> 2.23"
    }
  }
  backend "s3" {
    bucket = "mdp-terraform-state"
    key    = "dev/k8s-addons/terraform.tfstate"
    region = "eu-central-1"
  }
}

provider "kubernetes" {
  config_path = var.kubeconfig_path
}

variable "namespace" {
  type    = string
  default = "ml-dev"
}

resource "kubernetes_namespace" "ml" {
  metadata {
    name = var.namespace
  }
}

Variables и tfvars. Общие defaults в variables.tf; окружение — в dev.tfvars:


namespace = "ml-dev"

terraform plan -var-file=dev.tfvars

Outputs — контракт модуля наружу:


output "namespace_name" {
  value = kubernetes_namespace.ml.metadata[0].name
}

Module call.


module "minio_tenant" {
  source = "../modules/minio-tenant"

  bucket_name = "ml-datasets-dev"
  replicas    = 4
}

output "bucket" {
  value = module.minio_tenant.bucket_id
}

Внутри module — свои main.tf, variables.tf, outputs.tf. Версионирование module: git tag или Terraform Registry.

Lifecycle hooks.


resource "kubernetes_persistent_volume_claim" "example" {
  # ...
  lifecycle {
    prevent_destroy = true
  }
}

Защита критичных ресурсов от случайного terraform destroy.

Count / for_each. Создать N похожих namespace или S3 prefix:


variable "teams" {
  type = list(string)
  default = ["alpha", "beta"]
}

resource "kubernetes_namespace" "team" {
  for_each = toset(var.teams)
  metadata {
    name = "ml-${each.key}"
  }
}

Plan output читать обязательно.

Targeted apply (-target) — только для emergency debug, не для routine (ломает dependency graph).

Как это выглядит на практике

MR workflow в platform team:

1. Ветка feat/minio-bucket-ml-capstone.

2. Добавить module call + tfvars для dev.

3. CI: terraform fmt -check, validate, plan — comment bot постит plan diff в MR.

4. Review двумя инженерами.

5. Merge → CD job terraform apply на dev → smoke → apply prod в maintenance window.

Локально (учебный sandbox только):


cd environments/dev
terraform init
terraform plan -var-file=dev.tfvars -out=plan.bin
terraform apply plan.bin

Kubernetes provider use case для ML. Namespace, ResourceQuota (limits CPU/GPU), LimitRange, optional NetworkPolicy baseline — всё reproducible.


resource "kubernetes_resource_quota" "ml_dev" {
  metadata {
    name      = "gpu-quota"
    namespace = "ml-dev"
  }
  spec {
    hard = {
      "requests.nvidia.com/gpu" = "2"
    }
  }
}

Типичные ошибки студентов.

Что сделать после занятия

Официальные материалы

Открыть интерактивную версию