Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud

Рейтинг: 62.3% · 11 голосов
Подробный курс по Terraform и OpenTofu на примерах Yandex Cloud: ресурсы и провайдеры, состояние и бэкенды, модули, циклы и условия HCL, секреты и Lockbox, тестирование, CI/CD и командная работа. С актуализацией на 2026 (Terraform 1.3-1.10, OpenTofu).
Ответить
Аватара пользователя
Vlad_DevOps
Сообщения: 47
Зарегистрирован: 11 май 2026, 05:31

Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud

Сообщение Vlad_DevOps »

Оглавление курса (47)
  1. Что такое инфраструктура как код и зачем она нужна
  2. Категории инструментов IaC: чем отличаются Ansible, Packer, Kubernetes и Terraform
  3. Чем Terraform отличается от Ansible, Pulumi и CloudFormation
  4. Как работает Terraform под капотом и кто такой OpenTofu
  5. Установка Terraform и OpenTofu, подготовка Yandex Cloud
  6. Первый ресурс: разворачиваем виртуальную машину в Yandex Cloud
  7. Веб-сервер на ВМ: метаданные, user-data и группы безопасности
  8. Переменные ввода и выходные значения в Terraform
  9. Кластер ВМ: группа экземпляров Yandex Compute Instance Group
  10. Балансировщик нагрузки: Application Load Balancer в Yandex Cloud
  11. Состояние Terraform: что такое tfstate и чем опасен локальный файл
  12. Удалённое хранилище состояния: бэкенд на Yandex Object Storage
  13. Изоляция состояния: рабочие области против раскладки по папкам
  14. Источники данных и terraform_remote_state: связываем компоненты
  15. Модули Terraform: переиспользуем инфраструктуру
  16. Входные, локальные и выходные переменные модуля
  17. Версионирование модулей и подводные камни
  18. Циклы в Terraform: параметр count
  19. Циклы в Terraform: for_each по множествам и картам
  20. Выражения for и строковые директивы
  21. Условная логика: count-трюк, for_each и директива if
  22. Встроенные функции, типы и выражения HCL
  23. Развёртывание без простоя: create_before_destroy
  24. Подводные камни Terraform и рефакторинг с блоком moved
  25. Управление секретами: основы и типы
  26. Инструменты управления секретами: Yandex Lockbox, Vault, SOPS
  27. Аутентификация провайдера и секреты: сервисные аккаунты и OIDC
  28. Секреты в ресурсах и состоянии, ephemeral-значения
  29. Провайдеры Terraform: установка, версии, required_providers
  30. Несколько копий одного провайдера: alias и мультизона
  31. Несколько провайдеров и аккаунтов: configuration_aliases
  32. Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud (вы здесь)
  33. Код Terraform промышленного уровня: почему это долго
  34. Мелкие компонуемые модули вместо монолита
  35. Тестируемые модули и проверки: validation, precondition, postcondition
  36. Версионирование, публикация модулей и Terragrunt
  37. Ручное тестирование Terraform и очистка ресурсов
  38. Автоматические тесты на Terratest: модульные тесты
  39. Интеграционные и сквозные тесты, пирамида тестирования
  40. Нативный terraform test и статический анализ
  41. Внедрение Terraform в команде: процессы и культура
  42. Конвейер развёртывания прикладного кода
  43. Конвейер инфраструктурного кода и золотое правило Terraform
  44. Стиль, ревью и CI/CD-инструменты: Atlantis, TACOS, policy as code
  45. Что нового в Terraform 1.3-1.10: моды, импорт, провайдер-функции, Stacks
  46. OpenTofu в 2026: чем живёт форк и как мигрировать
  47. Сертификация HashiCorp Terraform Associate и карьера
У тебя есть приложение в Docker-контейнере. Локально оно бодро поднимается через docker run, но как только речь заходит про прод - начинается боль. Кто будет перезапускать упавший контейнер? Как раскатить новую версию без даунтайма? Что делать, если нагрузка скакнула и нужно три копии вместо одной? Руками это не вывозится. Тут на сцену выходит Kubernetes, а поднимать его руками через консоль - удовольствие сомнительное. Поэтому в этом уроке мы соберём весь пайплайн на инфраструктуре как код: собрали образ, запушили в реестр, Terraform поднял Managed Kubernetes в Yandex Cloud, и тот же Terraform через провайдеры kubernetes и helm раскатил приложение. Один terraform apply - и у тебя живой кластер с работающим деплоем.

Это прикладной урок. Если ты ещё путаешься в terraform plan apply и не понимаешь, что такое terraform state - вернись на пару глав назад, тут уже считается, что база есть.

Docker и Kubernetes за пять минут (контекст)

Чтобы дальше не было каши в голове, договоримся о терминах. Docker упаковывает твоё приложение со всеми зависимостями в образ - неизменяемый слепок файловой системы. Из образа запускается контейнер - изолированный процесс. Образы хранятся в реестре (registry): это как Git, только для образов. Запушил образ туда - и любая машина может его скачать.

Kubernetes (он же k8s) - это оркестратор. Он берёт кучу серверов, объединяет их в кластер и сам решает, на какой ноде запустить твой контейнер, перезапускает упавшее, балансирует нагрузку и катит обновления. Минимальный кирпичик в k8s - это Pod (один или несколько контейнеров). Поды плодятся не вручную, а через Deployment - он держит заданное число реплик. Чтобы до подов можно было достучаться по сети, поверх вешается Service.

Кластер делится на две части: control plane (мастер) - мозги, которые принимают решения, и worker-ноды - рабочие лошадки, где реально крутятся твои контейнеры. В Managed Kubernetes от Yandex Cloud мастером управляет облако: ты его не админишь, не патчишь, не чинишь по ночам. Тебе остаётся описать ноды и приложение. Это и есть смысл managed-сервиса.

Изображение

Поднимаем кластер: cluster + node group

В Yandex Cloud кластер описывается двумя основными ресурсами. Первый - сам кластер с мастером (yandex_kubernetes_cluster), второй - группа рабочих нод (yandex_kubernetes_node_group). Мастер бывает двух видов: zonal (один инстанс в одной зоне - дёшево, но если зона легла, легло всё) и regional (три инстанса в трёх зонах - отказоустойчиво, но дороже). Для обучения берём zonal, для прода - regional.

Перед кластером нужна сеть, подсеть, два сервисных аккаунта (один для самого кластера, второй для нод) и роли на них. Чтобы урок не растёкся на десять экранов, сетевую обвязку я обозначу ссылками на ресурсы, а сфокусируюсь на самом k8s. Сначала провайдер и реестр образов:

Код: Выделить всё

terraform {
  required_providers {
    yandex = {
      source = "yandex-cloud/yandex"
    }
    kubernetes = {
      source = "hashicorp/kubernetes"
    }
    helm = {
      source = "hashicorp/helm"
    }
  }
}

provider "yandex" {
  zone = "ru-central1-a"
}

resource "yandex_container_registry" "app" {
  name      = "cyberlake-registry"
  folder_id = var.folder_id

  labels = {
    env = "demo"
  }
}
Теперь зональный кластер. Обрати внимание на блок master.zonal и на два разных service_account_id - это не опечатка, у кластера и у нод разные аккаунты:

Код: Выделить всё

resource "yandex_kubernetes_cluster" "demo" {
  name       = "cyberlake-k8s"
  network_id = yandex_vpc_network.k8s.id

  master {
    version   = "1.30"
    public_ip = true

    zonal {
      zone      = yandex_vpc_subnet.k8s_a.zone
      subnet_id = yandex_vpc_subnet.k8s_a.id
    }

    maintenance_policy {
      auto_upgrade = true

      maintenance_window {
        start_time = "03:00"
        duration   = "3h"
      }
    }
  }

  service_account_id      = yandex_iam_service_account.k8s.id
  node_service_account_id = yandex_iam_service_account.k8s_nodes.id
  release_channel         = "REGULAR"

  depends_on = [
    yandex_resourcemanager_folder_iam_member.k8s_editor,
    yandex_resourcemanager_folder_iam_member.k8s_nodes_puller,
  ]
}
Тот depends_on в конце - не для красоты. В доке прямо предупреждают: если роли сервисным аккаунтам выданы тоже через Terraform, то на destroy он может снести роли и кластер одновременно, и удаление зависнет. Явная зависимость гарантирует правильный порядок.

Дальше группа нод. Мастер сам по себе контейнеры не запускает - ему нужны worker-ноды. Описываем шаблон инстанса и политику масштабирования:

Код: Выделить всё

resource "yandex_kubernetes_node_group" "workers" {
  cluster_id = yandex_kubernetes_cluster.demo.id
  name       = "cyberlake-workers"
  version    = "1.30"

  instance_template {
    platform_id = "standard-v3"

    network_interface {
      nat        = true
      subnet_ids = [yandex_vpc_subnet.k8s_a.id]
    }

    resources {
      cores  = 2
      memory = 4
    }

    boot_disk {
      type = "network-ssd"
      size = 64
    }

    container_runtime {
      type = "containerd"
    }
  }

  scale_policy {
    fixed_scale {
      size = 2
    }
  }

  allocation_policy {
    location {
      zone = "ru-central1-a"
    }
  }

  maintenance_policy {
    auto_upgrade = true
    auto_repair  = true
  }
}
Минимальный размер boot_disk - 64 GB, меньше облако не даст. container_runtime ставим containerd: docker как рантайм в k8s давно депрекейтнут, не выдумывай. Если хочешь автоскейлинг вместо фиксированных двух нод - вместо fixed_scale используй блок auto_scale с обязательными полями initial, min и max.

Связываем всё: образ, реестр и деплой через провайдеры

Кластер есть, но он пустой. Логика пайплайна такая: собираем Docker-образ, пушим его в yandex_container_registry, а потом через k8s-провайдер раскатываем Deployment, который тянет этот образ. Сборка и пуш - это шаг вне Terraform (Terraform не собирает образы, не надо его об этом просить):

Код: Выделить всё

# логинимся в реестр Yandex Cloud
yc container registry configure-docker

# собираем и тегаем образ ID реестра из terraform output
docker build -t cr.yandex/$REGISTRY_ID/web:1.0 .
docker push cr.yandex/$REGISTRY_ID/web:1.0
Теперь самое интересное - несколько провайдеров в одной конфигурации. Провайдеру kubernetes надо как-то подключиться к свежесозданному кластеру. Координаты мастера (эндпоинт и CA-сертификат) Terraform уже знает - они лежат в атрибутах ресурса кластера: master.0.external_v4_endpoint и master.0.cluster_ca_certificate. Токен берём через data-источник клиентской конфигурации:

Код: Выделить всё

data "yandex_client_config" "client" {}

provider "kubernetes" {
  host                   = yandex_kubernetes_cluster.demo.master[0].external_v4_endpoint
  cluster_ca_certificate = yandex_kubernetes_cluster.demo.master[0].cluster_ca_certificate
  token                  = data.yandex_client_config.client.iam_token
}

resource "kubernetes_deployment_v1" "web" {
  metadata {
    name = "web"
  }

  spec {
    replicas = 2

    selector {
      match_labels = { app = "web" }
    }

    template {
      metadata {
        labels = { app = "web" }
      }

      spec {
        container {
          name  = "web"
          image = "cr.yandex/${yandex_container_registry.app.id}/web:1.0"

          port {
            container_port = 8080
          }
        }
      }
    }
  }
}
Заметь: image собирается из ID реестра, который Terraform знает. Получается сквозная связка - реестр, образ и деплой соединены через ссылки на ресурсы, и Terraform сам построит правильный граф зависимостей.

Helm-провайдер настраивается так же, через тот же host/token, только внутри блока kubernetes. Через него удобно ставить готовые чарты - ingress-контроллер, мониторинг, cert-manager - не описывая сотни строк манифестов руками.

Типичные грабли
  • Провайдер k8s подключается раньше, чем готов кластер. Классика: Terraform пытается создать Deployment, а мастер ещё поднимается. Лекарство - depends_on на ресурсе кластера у деплоя, либо разнести инфраструктуру и приложение по разным конфигурациям (два state). Второе чище: смешивать создание кластера и деплой в него в одном apply - известный антипаттерн.
  • IAM-токен живёт около 12 часов. iam_token из yandex_client_config протухает. Для разовых apply нормально, для CI лучше workload identity или отдельный сервисный аккаунт с ключом.
  • Нодам нет доступа к реестру. Если поды не могут вытянуть образ (ImagePullBackOff) - проверь, что node_service_account_id имеет роль container-registry.images.puller. Кластер видит реестр, а ноды качают образы именно под своим аккаунтом.
  • Перепутал zonal и regional. В одном блоке master может быть только что-то одно. Засунешь оба - Terraform ругнётся на конфликт.
Мини-лаба

Повтори руками, не копируя бездумно:
  • Опиши yandex_container_registry и zonal-кластер yandex_kubernetes_cluster с node group на 2 ноды. Сеть и сервисные аккаунты добавь сам - это хорошая тренировка.
  • Собери любой простой образ (хоть nginx), запушь в реестр через docker push на cr.yandex.
  • Подключи провайдер kubernetes через master[0].external_v4_endpoint и раскатай Deployment с этим образом.
  • Сделай terraform plan apply, дождись подов, проверь kubectl get pods. Потом измени replicas и снова apply - посмотри, как меняется только нужное.
  • Финал - terraform destroy. Убедись, что благодаря depends_on всё сносится в правильном порядке.
Контрольные вопросы
  • Чем zonal-мастер отличается от regional и когда какой выбирать?
  • Зачем у кластера два разных сервисных аккаунта (service_account_id и node_service_account_id)?
  • Откуда провайдер kubernetes берёт host и cluster_ca_certificate для подключения?
  • Почему собирать и пушить Docker-образ - это шаг вне Terraform, а не его задача?
Что запомнить

Managed Kubernetes в Yandex Cloud - это два ресурса: yandex_kubernetes_cluster (мастер, zonal или regional) плюс yandex_kubernetes_node_group (worker-ноды). Образы живут в yandex_container_registry, кластер подтягивает их под аккаунтом нод. Магия - в связке провайдеров: yandex поднимает железо, а kubernetes и helm поверх него катят приложение, получая kubeconfig прямо из атрибутов кластера. Пайплайн собрали образ - запушили - подняли кластер - задеплоили описывается целиком как код, в идеале с разделением инфраструктуры и приложения по разным state. И всё это одинаково работает что в Terraform, что в OpenTofu - синтаксис HCL и провайдеры те же.
👍3 ❤️4 🔥1 😄 🤔
Аватара пользователя
uncensored2
Сообщения: 1
Зарегистрирован: 04 июн 2026, 21:54

Re: Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud

Сообщение uncensored2 »

Спасибо, наконец дошло зачем кластеру ДВА сервисных аккаунта, я думал это лишнее и удалял node_service_account_id. Теперь понятно откуда ImagePullBackOff лез.
👍 ❤️ 🔥 😄 🤔
Аватара пользователя
rabbitmain
Сообщения: 1
Зарегистрирован: 29 май 2026, 13:40

Re: Terraform, Docker и Kubernetes: Managed Kubernetes в Yandex Cloud

Сообщение rabbitmain »

А можно подробнее почему лучше держать кластер и деплой в разных state? У меня всё в одном apply и иногда плэн пытается создать Deployment когда мастер ещё не готов, ловлю ошибку connection refused.
👍1 ❤️ 🔥1 😄 🤔1
Ответить
← Предыдущая глава
Несколько провайдеров и аккаунтов: configuration_aliases
Следующая глава →
Код Terraform промышленного уровня: почему это долго

Все главы курса «Terraform: инфраструктура как код на Yandex Cloud»

Поделиться темой: ✈ Telegram VK
Похожие запросы: terraform yandex cloud с чего начать новичкукак установить terraform и opentofu на linuxчто такое terraform state и tfstate простыми словамиудаленный backend terraform на object storage yandex cloudчто такое инфраструктура как код iac простыми словамиterraform plan и apply что делают и чем отличаются

Вернуться в «Terraform: инфраструктура как код на Yandex Cloud»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость