# terraform workspace: несколько state в одной директории _Основы Terraform · TerraformLab Knowledge Base_ **TL;DR:** Workspace, это именованный slot для отдельного state-файла в одной директории с HCL. Полезно для очень похожих окружений с минимальной разницей. В этом курсе не используется; обычно лучше отдельные папки. ## Что такое workspace Workspace, это именованный slot, в котором живёт отдельный state-файл. Один и тот же HCL-конфиг с двумя workspace'ами создаёт две независимые инфраструктуры, по одной на workspace. В каждый момент времени активен ровно один workspace. Команды `plan`, `apply`, `destroy` работают только в нём. По умолчанию у проекта всегда есть workspace с именем `default`. Его нельзя удалить. Команды: ```bash terraform workspace list # перечислить terraform workspace new staging # создать terraform workspace select staging # переключиться terraform workspace show # показать текущий terraform workspace delete staging # удалить (после переключения на другой) ``` ## Где лежат state-файлы С локальным backend (см. [tf-init-backends](/terraform/kb/tf-init-backends.md)) state каждого workspace хранится в подкаталоге `terraform.tfstate.d/`: ``` myproject/ ├── main.tf ├── terraform.tfstate # default workspace └── terraform.tfstate.d/ ├── staging/ │ └── terraform.tfstate └── prod/ └── terraform.tfstate ``` С remote backend (S3, GCS, Terraform Cloud) workspace становится префиксом ключа: `env:/staging/myproject` и т.п. ## Как использовать имя workspace в HCL Доступно через `terraform.workspace`: ```hcl resource "aws_s3_bucket" "logs" { bucket = "logs-${terraform.workspace}-acme" # → "logs-default-acme", "logs-staging-acme", ... } ``` Это удобно для нейминга, но и опасно: одна и та же конфигурация может в разных workspace создать разное число ресурсов через `count = terraform.workspace == "prod" ? 3 : 1`. Без чёткой дисциплины через два месяца никто не помнит, чем prod-workspace отличается от staging-workspace. ## Когда workspace оправдан - **Очень похожие копии одного и того же.** Пер-PR review-окружения, тестовые ephemeral-стенды. - **Когда инфра реально идентична** и единственное различие, имена ресурсов. - **Когда команда понимает, что workspace: just one state per config**, а не «изолированный аккаунт». ## Когда workspace, анти-паттерн - **Prod / staging / dev.** Эти окружения обычно отличаются параметрами (размеры инстансов, нагрузка), кредами, политиками доступа. В одном HCL легко выстрелить себе в ногу: ошибся в переменной `terraform.workspace == "prod"`, и в prod уехало то, что предназначалось dev. Лучшее решение, отдельная директория под каждое окружение со своим backend и своим state. - **Когда нужны разные права доступа к state.** Workspace в одном backend == один и тот же набор кредов на доступ к state. Изолировать кто может читать prod-state, а кто, staging, нельзя. - **Изоляция blast radius.** Один кривой apply в workspace `prod` при включённом backend без блокировки может покалечить и сам state, и соседние workspace. Это причина, по которой курс использует обычные директории, а не workspace. Workspace, рабочий инструмент в нишевых сценариях. ## Workspace и backend remote/local - **Local backend:** workspace меняет подпапку в `terraform.tfstate.d/`. Всё локально. - **S3 backend:** workspace становится префиксом ключа. - **Terraform Cloud:** workspace, это first-class сущность с своим UI, RBAC, run history. Тут он действительно даёт изоляцию. То есть «workspace» в TF Cloud и «workspace» в локальном CLI, два разных понятия с общим именем. Это путает многих. ## Подводные камни - **Default удалить нельзя.** Если хочется чистоты, заведи новый workspace и работай в нём, default останется пустым. - **`workspace delete` не удаляет ресурсы.** Только state. Если в workspace что-то развёрнуто, сначала `destroy`, потом `delete`, иначе останутся сиротские ресурсы в облаке. - **`terraform.workspace` доступен внутри HCL только после select.** При обращении через UI терраформ-облака может быть nuance, workspace задаётся не CLI, а контекстом запуска. - **Имена окружений не зашиваются в код.** В HCL почти никогда нельзя писать `if terraform.workspace == "prod"`. Лучше через переменную `environment = "prod"` и обычные условные выражения. ## Команды ```bash terraform workspace list ``` Все workspace в текущей директории. Звёздочка отмечает активный. ```bash terraform workspace new staging ``` Создать новый workspace и переключиться на него. ```bash terraform workspace select default ``` Вернуться в default. Если такого нет: terraform создаст его сам. ```bash terraform workspace show ``` Просто имя активного workspace. Полезно в скриптах: `if [[ $(terraform workspace show) == prod ]]; then ...` ```bash terraform workspace delete staging ``` Удалить workspace. Только пустой (без ресурсов в state) и не активный сейчас. ## См. также - [terraform init: первая команда в любом проекте](/terraform/kb/tf-init.md) - [Backend в Terraform: где живёт state](/terraform/kb/tf-init-backends.md) - [terraform destroy: снести всё, что было создано](/terraform/kb/tf-destroy.md) - [terraform apply: применить план в реальном облаке](/terraform/kb/tf-apply.md)