Когда в твоём хозяйстве сначала три сервера, а потом внезапно пятнадцать, и каждый нужно настроить одинаково — ручной SSH превращается в адову рутину. Ты логинишься, правишь конфиги, ставишь пакеты, и молишься, чтобы на четвёртой ноде не забыть тот самый systemd-юнит, который добавлял вручную в прошлый раз. Собственно, ровно так я и пришёл к Terraform: не потому что модно, а потому что надоело гадать, какая именно правка потерялась между вторым и пятым сервером.
Создание повторяемой инфраструктуры для небольшого кластера — это чистый Infrastructure as Code. Описываешь виртуалки, сети, балансировщики в декларативном виде, и Terraform сам приводит реальность к тому состоянию, которое ты задумал. Неважно, облако это или локальное железо, — результат будет одним и тем же при каждом запуске. Для админа, перешагнувшего рубеж в сотню серверов, это уже не оптимизация, а единственный способ не превратиться в «перекопипастера конфигов». Ниже разберу по шагам, как поднять кластер (например, Kubernetes или ту же распределённую базу) в Yandex Cloud или Cloud.ru, с акцентом на реальные практики и грабли, которые особенно актуальны для российской инфраструктуры.
Почему Terraform — это выбор современного админа, а не разработчика
Классика жанра: открываешь консоль облака, тыкаешь мышкой, создаёшь виртуалку, идёшь по SSH, доставляешь руками пакеты, запускаешь сервис. Два сервера — ещё терпимо. Три — начинаешь забывать, на каком именно ты вчера правил лимиты. А когда после обновления ядра всё ложится, понять, какие именно изменения были внесены за последнюю неделю, практически невозможно. В такие моменты вспоминаешь, что bash-скрипты хороши для прототипов, а не для продакшена.
Terraform заходит с другой стороны и держится на трёх принципах, которые сразу меняют картину:
- Декларативность. Вместо инструкций «сделай то, потом это» ты описываешь конечное желаемое состояние: три ВМ, такой-то тип диска, вот эта подсеть. Terraform сам вычисляет, какие API-вызовы нужны, чтобы это состояние получить.
- Повторяемость. Один и тот же
main.tfв любой момент развернёт идентичную инфраструктуру. Критично, когда у тебя есть dev, stage и prod, которые должны быть максимально похожими. И для аварийного восстановления — бесценно: не нужно судорожно вспоминать, как именно был настроен кластер полгода назад. - Версионирование. Конфигурация живёт в Git. Видно, кто и зачем изменил размер диска или тип сети. Если что-то отвалилось после коммита —
git blameиgit revertв помощь, а не лихорадочный поиск по истории SSH-сессий.
Для кластера из 3–5 узлов Terraform позволяет описать всю сетевую топологию — подсети, роутеры, группы безопасности — в одном проекте. Это исключает человеческий фактор при настройке VLAN и правил доступа: ты больше не забудешь привязать security group к подсети или ошибиться в CIDR.
Подготовка окружения: выбор провайдера и настройка доступа
Первый и самый важный шаг — выбрать облачного провайдера и грамотно настроить авторизацию. В российском контексте, если речь о бизнесе и требованиях 152-ФЗ, приоритетны Yandex Cloud и Cloud.ru. Они закрывают вопросы локализации данных и имеют вполне зрелые Terraform-провайдеры под свои API.
Выбор облачного провайдера
Дальше — простая таблица для ориентира, когда выбираешь между провайдерами под конкретную задачу:
| Провайдер | Terraform Provider | Ключевые особенности для кластера |
|---|---|---|
| Yandex Cloud | yandex |
Мощный Managed Kubernetes, гибкая настройка сетей, VPC. Самый предсказуемый вариант для старта. |
| Cloud.ru | cloudru |
Свой Managed K8s (MK8S), заточенный под FinOps, плотная интеграция с экосистемой Сбера. Удобен для гибридных сред. |
| Selectel | selectel |
Отличный выбор для on-premise и частных облаков. Можно очень гибко управлять роутерами и подсетями. |
| VK Cloud | vkcloud |
Доступные квоты, Cloud Containers, простой интерфейс для создания K8s. Хорош для быстрой проверки гипотез. |
В этой статье я пойду по пути Yandex Cloud — его документация и провайдер детальнее всего проработаны под создание кластеров. Но логика действий идентична и для Cloud.ru, и для VK Cloud.
Настройка авторизации в облаке
Terraform без ключей доступа работать не умеет. И в отличие от скриптов, где у новичков токены часто лежат прямо в коде, здесь сразу приучаем себя к безопасному хранению.
Шаги подготовки в Yandex Cloud:
- Регистрируетесь в консоли и подключаете платёжный аккаунт.
- Убеждаетесь, что на аккаунте есть средства (калькулятор провайдера даст примерную оценку для 3–9 ВМ).
- Создаёте сервисный аккаунт с ролью
adminилиeditor. Для Managed Kubernetes часто нужна рольkubernetes.admin. - Генерируете авторизованный ключ в формате JSON. Это ваш «пароль» для Terraform, и его нельзя светить.
Файл auth.json сохраняете в надёжное место. В проекте путь до него будет указан в конфигурации провайдера. Главное правило: не хранить ключ в Git. Использовать переменные окружения или .tfvars с защитой.
Установка Terraform и CLI провайдера
На рабочей машине (Linux/Windows) ставим сам Terraform. Для Yandex Cloud дополнительно рекомендую поставить их CLI yc — он упрощает инициализацию окружения и отладку, хотя сам Terraform чаще работает напрямую через сервисный ключ.
На практике это выглядит так: ставим yc, выполняем yc init, чтобы профиль сохранился локально, а Terraform при этом конфигурируем на созданный ранее авторизованный ключ. Так мы получаем удобную связку для отладки и мониторинга через CLI без компромиссов в безопасности Terraform-окружения.
Структура проекта: как организовать файлы для надежности
Когда пишешь код, которым будут управляться реальные ресурсы, хочется избежать ситуации, когда изменение IP-адреса в одном месте ломает всё остальное. Опытные админы не пишут всё в main.tf — для небольшого кластера, который со временем будет расти, правильная структура становится вопросом масштабируемости.
Рекомендуемая структура директорий
cluster/
├── provider.tf # провайдер и бэкенд
├── network.tf # VPC, подсети, роутеры
├── security.tf # группы безопасности
├── main.tf # вычислительные ресурсы (кластер/ВМ)
├── variables.tf # все переменные
├── outputs.tf # IP-адреса, эндпоинты
└── terraform.tfvars # значения переменных (не в Git)
Такой расклад держит в уме:
network.tfизолирует сетевую логику. Меняя подсети, ты не рискуешь случайно перезаписать конфигурацию ВМ.variables.tfделает код гибким: изменил размер диска или тип ВМ через переменную — и не надо лезть в тело ресурса, рискуя что-то сломать.outputs.tfавтоматически возвращает IP-адреса созданных узлов, избавляя от ручного поиска в консоли облака.
Базовая конфигурация провайдера (provider.tf)
В provider.tf описываем, как Terraform соединяется с облаком. Никаких токенов в открытом виде: используем переменную var.yandex_token. Так секреты остаются в .tfvars или пробрасываются через YC_TOKEN, не попадая в репозиторий.
На практике это первое, что проверяешь при смене машины: убедился, что переменная окружения экспортирована, иначе apply упадёт на этапе аутентификации.
Описание сетевой инфраструктуры: фундамент кластера
Кластер без сети — просто кучка виртуалок. В облаке это не «воткнуть кабель», а создание виртуальной сети (VPC), подсетей и таблиц маршрутизации. Для небольшого кластера (3 воркера + 1 мастер) важно сразу правильно выбрать диапазоны, чтобы они не пересекались с другими ресурсами, и решить, нужен ли выход в интернет для обновлений или подсеть должна быть изолированной.
Создание VPC и подсетей (network.tf)
В файле network.tf описываем сеть. Типовая ошибка, которую я ловил не раз: создал подсеть, а привязать её к роутеру забыл. Без этого воркер-ноды не могут скачивать пакеты и контейнеры. yandex_vpc_route_table как раз связывает подсеть с интернет-шлюзом.
Ещё один нюанс: статические маршруты. Если вы планируете гибридную среду, где часть сервисов остаётся на локальном железе, продумывайте маршруты сразу, иначе потом придётся перекраивать сеть на живую.
Группы безопасности (Security Groups)
Для кластера Kubernetes или, скажем, YDB нужны строгие правила. Создаём security group, которая разрешает:
- Доступ к API кластера (порт 6443) только из доверенных источников.
- Внутренний обмен между узлами — все порты внутри своей подсети.
- SSH (порт 22) исключительно для администраторов, и только с конкретных IP.
Здесь часто прокалываются: открывают 0.0.0.0/0 на все порты «чтобы работало», а через месяц удивляются, что кто-то майнит крипту на их воркерах. Лучше потратить лишние 10 минут на настройку групп сейчас, чем тушить инцидент в 3 часа ночи.
Создание вычислительных ресурсов: ВМ и кластер
После того как сеть описали, переходим к самим ресурсам. Для небольшого кластера есть два пути, и выбор сильно зависит от того, насколько вы готовы брать на себя обслуживание control plane:
- Отдельные ВМ с последующей установкой Kubernetes через Ansible или kubeadm.
- Managed Kubernetes — сервис облака, где Terraform управляет конфигурацией кластера, а не его операционной системой.
Для продакшена я почти всегда рекомендую Managed: облако берёт на себя отказоустойчивость мастер-узлов и обновление ядер, а ваша головная боль сводится к воркерам и приложениям.
Вариант 1: Managed Kubernetes в Yandex Cloud (рекомендуемый)
В main.tf описываем кластер. Ключевое:
- Версия K8s: всегда указывайте актуальную, но стабильную. Не гонитесь за самой свежей — облако может ещё не поддерживать её в целевом регионе. 1.28 или 1.29 — нормальный выбор на сегодня.
- Публичный IP для API: если вы ставите
master.public_ip = true, то сможете подключиться черезkubectlоткуда угодно. В продакшене я чаще использую приватный IP и доступ через Bastion-хост или VPN — так просто спокойнее. - Размер ВМ: 2 ядра и 4 ГБ памяти — минимально комфортный уровень. Ставить 1 ядро и 1 ГБ — тренировка на устойчивость к падениям, потому что при мало-мальской нагрузке воркеры начнут отваливаться.
Вариант 2: Создание ВМ вручную (для обучения или специфических задач)
Если вы управляете ВМ самостоятельно (например, для YDB или специфического ПО), то создаёте их как обычные вычислительные ресурсы, а затем накатываете Ansible. Такой подход даёт полный контроль, но кратно увеличивает ручную работу. Для задачи «повторяемая инфраструктура» это менее эффективно: ты снова вынужден следить за консистентностью конфигурации на каждой ноде.
В гибридных средах, где локальное железо соседствует с облаком, такой подход иногда безальтернативен. Но тогда важно позаботиться о том, чтобы Ansible-плейбуки тоже версионировались и запускались автоматически после apply.
Инициализация, планирование и применение: рабочий цикл
Когда все .tf-файлы написаны, начинаем жить по циклу Terraform. Он состоит из трёх этапов, и каждый из них стоит понимать, а не просто гонять по памяти.
1. Инициализация (terraform init)
Команда скачивает провайдера Yandex Cloud, устанавливает зависимости и создаёт кэш в .terraform. Если меняли версию провайдера или подключали новые модули — повторный init обязателен. Игнорировать этот шаг — верный способ получить ошибку посреди plan.
2. Планирование (terraform plan)
plan показывает, что Terraform сделает, но ничего не трогает. Это детектор ошибок. Я приучил себя просматривать план всегда, даже когда уверен в изменениях. На что смотреть:
- Количество ресурсов: соответствует ли ожиданиям (3 воркера, 1 сеть, 1 security group)?
- Типы ресурсов: не изменился ли случайно диск с SSD на HDD?
- IP-адреса и CIDR: не пересекаются ли с существующими сетями?
Если план показывает удаление ресурсов (-), которые вы не собирались удалять, — стоп, apply не запускаем. Это почти всегда признак ошибки: случайно переименовали ресурс или изменили идентификатор, и Terraform теперь думает, что старый ресурс надо убрать.
3. Применение (terraform apply)
Только после проверки плана запускаем создание. Terraform запросит подтверждение yes. Процесс может занять от 5 до 15 минут — сеть, подсеть, роутер и кластер поднимаются последовательно. На этом этапе уже поздно пить кофе: если всё пошло по плану, можно готовить kubectl.
4. Проверка результатов (terraform output)
После apply используйте terraform output, чтобы получить IP API-эндпоинта и сертификат. Берёте эти значения, настраиваете kubectl. Если в столбце READY для мастер-узлов горят 2/2 — кластер поднялся успешно.
Удаление и управление состоянием: FinOps и безопасность
Создать инфраструктуру — полдела. Уметь корректно её выключить, когда она не нужна, и не потерять при этом состояние — вот что отличает инженера по надёжности от энтузиаста.
Удаление ресурсов (terraform destroy)
Если кластер оттестировали и он больше не нужен — terraform destroy. Terraform запросит yes и аккуратно уберёт ВМ, кластер, подсети и сеть. Перед запуском я всегда делаю terraform plan -destroy: он показывает, что будет удалено, и помогает избежать сюрпризов вроде зависимых дисков, которые по ошибке остались висеть в облаке и продолжают тратить бюджет.
Управление состоянием (terraform state)
Файл terraform.tfstate — это «мозг» Terraform. Если удалить его вручную, инструмент «забудет» о созданных ресурсах и попытается создать их заново, что приведёт к конфликтам. Не храните tfstate в Git, если там есть секреты (а они там часто есть).
Для продакшена настоятельно рекомендую использовать Remote State: S3-совместимый бакет, GCS, Azure Blob. Тогда состояние доступно всей команде и не зависит от локальной машины. На своей практике видел, как админ ушёл в отпуск, а его ноутбук с единственным tfstate умер — восстановление заняло пару дней через поддержку облака, а могло занять пять минут через remote state.
Типовые ошибки и важные нюансы при создании кластера
На Terraform я наступал на все возможные грабли, поэтому собрал самые частые проблемы и способы их решения.
1. Пересечение диапазонов подсетей
Ошибка: создали подсеть 10.0.1.0/24, а в облаке уже есть другая с тем же диапазоном. apply падает.
Решение: всегда проверять доступные диапазоны в консоли перед запуском. Для второго кластера используйте уникальный CIDR (например, 10.0.2.0/24).
2. Отсутствие квот в регионе
Ошибка: в выбранной зоне нет квоты на нужный тип ВМ, например standard-v3.
Решение: проверяйте квоты в консоли до plan. Если квоты нет, пишите в поддержку или переезжайте в другую зону доступности.
3. Неправильная версия K8s
Ошибка: указали версию 1.30, а облако её пока не поддерживает.
Решение: смотрите документацию провайдера, используйте стабильную версию. Для Yandex Cloud это обычно 1.28 или 1.29.
4. Секреты в коде
Ошибка: токен авторизации вставили прямо в provider.tf — теперь он в Git, и любой, у кого есть доступ к репозиторию, может удалить вашу инфраструктуру.
Решение: использовать переменные окружения (YC_TOKEN) или .tfvars, который добавлен в .gitignore.
5. Задержка создания ресурсов
Ошибка: запускаете kubectl get nodes сразу после apply, а узлов ещё нет.
Решение: Terraform ждёт завершения создания ресурса на уровне облака, но не гарантирует, что K8s внутри узла уже готов. Лучше добавить проверку статуса с повторными попытками или использовать depends_on в комбинации с внешними скриптами.
Чек-лист: готовность инфраструктуры к продакшену
Перед тем как считать кластер готовым к бою, прохожусь по такому списку:
- Сеть: подсеть привязана к роутеру, нет пересечений с другими сетями.
- Безопасность: security group ограничивает SSH и API кластера до конкретных источников.
- Ресурсы: количество воркеров (3) и размер ВМ (2 ядра, 4 ГБ) соответствуют ожидаемой нагрузке.
- Версионирование:
main.tf,variables.tf,network.tf— всё закоммичено в Git. - Секреты: токены и ключи не лежат в репозитории, используются переменные окружения.
- Тестирование:
terraform planне показывает неожиданных изменений. - Мониторинг:
kubectlподключен, кластер виден и отвечает. - FinOps: стоимость ресурсов посчитана в калькуляторе, не выходит за рамки бюджета.
FAQ: часто задаваемые вопросы
Вопрос: Можно ли использовать Terraform для управления локальным железом (on-premise)?
Ответ: Да, Terraform поддерживает провайдеры для локальных гипервизоров: Proxmox, OpenStack, VMware. Можно описать ВМ на локальном сервере, настроить сеть и роутеры так же, как в облаке. Особенно ценно для гибридных сред, где часть сервисов живёт на своём железе, а часть — в облаке.
Вопрос: Что делать, если Terraform «забыл» ресурс после ручного удаления в консоли?
Ответ: Terraform держит состояние в terraform.tfstate. Если кто-то удалил ресурс вручную через веб-интерфейс, при следующем apply Terraform попытается создать его заново (и, скорее всего, упадёт с ошибкой, что имя занято). Чтобы разрулить, делают terraform state rm <resource_name> — удаляют запись из состояния, не трогая реальный ресурс. После этого состояние синхронизируется с реальностью.
Вопрос: Как обновить версию кластера без удаления?
Ответ: В Managed Kubernetes достаточно изменить параметр version в main.tf и запустить terraform apply. Облако возьмёт на себя миграцию, не удаляя воркеры. Это один из главных аргументов в пользу управляемого кластера.
Вопрос: Можно ли использовать Terraform вместе с Ansible?
Ответ: Это классическая связка. Terraform создаёт инфраструктуру (ВМ, сети), а Ansible её настраивает (пакеты, конфиги, сервисы). Можно запустить Ansible через provisioner или просто выполнить ansible-playbook сразу после apply. Для Managed Kubernetes, правда, Ansible часто уже не нужен — облако настраивает кластер самостоятельно.
Вопрос: Как защитить terraform.tfstate от потери?
Ответ: Remote State — S3, GCS, Azure Blob. Тогда файл состояния лежит в облаке и доступен каждому члену команды. Если локальная машина сломается, вы просто подтягиваете состояние из бакета и продолжаете работу.
Заключение: от тушения пожаров к инженерии надежности
Создание повторяемой инфраструктуры с Terraform для небольшого кластера — это не просто ещё один инструмент в арсенале. Это конкретный переход от практики «поправил в 18:30 и где-то записал» к миру, где инфраструктура описана кодом, проверяется в плане и разворачивается одинаково хоть в трёх разных зонах доступности.
Для кластера из 3–5 узлов IaC даёт главное преимущество: вы можете быстро поднять тестовое окружение, провести эксперимент, удалить его и тут же создать новое, точь-в-точь как продакшен. Это ощутимо снижает риски ночных инцидентов и высвобождает время на инженерию, а не на марафоны по консолям.
Когда ваша инфраструктура живёт в Git и поднимается одной командой, вы перестаёте быть «тем самым админом, который всё знает, но ушёл в отпуск», и становитесь инженером по надёжности, который автоматизировал даже собственные задачи. Начните с одного кластера: создайте его, проверьте, удалите и создайте снова. Убедитесь, что повторяемость реально работает — и дальше масштабируйте подход на всё, что только можно описать кодом.
Ключевой вывод: Не бойтесь начинать с малого. Даже один кластер, описанный в Terraform, спасает от ручных ошибок и даёт уверенность, что при сбое вы восстановите систему за минуты, а не будете мучительно вспоминать, на какой из нод лежал тот самый конфиг.
