Senior Go Interview Prep - Core Go: https://go.vbloher.org/docs/01-core-go/ - Механика defer в Go: https://go.vbloher.org/docs/01-core-go/defer/ - Встраивание структур и интерфейсов (Embedding): https://go.vbloher.org/docs/01-core-go/embedding/ - Ошибки в Go: error, wrapping, errors.Is/As/Join: https://go.vbloher.org/docs/01-core-go/errors/ - Дженерики в Go (1.18+): https://go.vbloher.org/docs/01-core-go/generics/ - Интерфейсы в Go: https://go.vbloher.org/docs/01-core-go/interfaces/ - Устройство map в Go: https://go.vbloher.org/docs/01-core-go/maps/ - panic / recover: механика, раскрутка стека и runtime-паники: https://go.vbloher.org/docs/01-core-go/panic-recover/ - Указатели в Go: https://go.vbloher.org/docs/01-core-go/pointers/ - Рефлексия в Go (reflect): https://go.vbloher.org/docs/01-core-go/reflection/ - Внутреннее устройство слайсов в Go: https://go.vbloher.org/docs/01-core-go/slices/ - Строки, руны и байты в Go: https://go.vbloher.org/docs/01-core-go/strings-runes-bytes/ - Система типов Go: defined types, alignment, memory layout: https://go.vbloher.org/docs/01-core-go/type-system/ - Concurrency: https://go.vbloher.org/docs/02-concurrency/ - sync/atomic: https://go.vbloher.org/docs/02-concurrency/atomic/ - Буферизованные vs небуферизованные каналы: https://go.vbloher.org/docs/02-concurrency/buffered-unbuffered/ - Канал vs Mutex: когда что выбрать: https://go.vbloher.org/docs/02-concurrency/channel-vs-mutex/ - Каналы: устройство hchan: https://go.vbloher.org/docs/02-concurrency/channels/ - Утечки горутин, дедлоки, livelock, starvation: https://go.vbloher.org/docs/02-concurrency/common-leaks-deadlocks/ - sync.Cond: https://go.vbloher.org/docs/02-concurrency/cond/ - context: https://go.vbloher.org/docs/02-concurrency/context/ - Горутины: жизненный цикл, стоимость, стек: https://go.vbloher.org/docs/02-concurrency/goroutines-lifecycle/ - sync.Mutex и sync.RWMutex: https://go.vbloher.org/docs/02-concurrency/mutex-rwmutex/ - sync.Once: https://go.vbloher.org/docs/02-concurrency/once/ - Паттерны конкурентности: https://go.vbloher.org/docs/02-concurrency/patterns/ - Race Detector (гонки данных и -race): https://go.vbloher.org/docs/02-concurrency/race-detector/ - Планировщик GMP: https://go.vbloher.org/docs/02-concurrency/scheduler-gmp/ - select: https://go.vbloher.org/docs/02-concurrency/select/ - sync.WaitGroup: https://go.vbloher.org/docs/02-concurrency/waitgroup/ - Runtime и память: https://go.vbloher.org/docs/03-runtime-memory/ - Паттерны аллокаций и снижение давления на GC: https://go.vbloher.org/docs/03-runtime-memory/allocation-patterns/ - Escape Analysis: когда переменная убегает в кучу: https://go.vbloher.org/docs/03-runtime-memory/escape-analysis/ - Сборщик мусора Go: concurrent tri-color mark-sweep: https://go.vbloher.org/docs/03-runtime-memory/gc/ - Тюнинг GC: GOGC и GOMEMLIMIT: https://go.vbloher.org/docs/03-runtime-memory/gogc-gomemlimit/ - GOMAXPROCS: параллелизм планировщика и проблема контейнеров: https://go.vbloher.org/docs/03-runtime-memory/gomaxprocs/ - Утечки горутин (goroutine leaks): https://go.vbloher.org/docs/03-runtime-memory/goroutine-leaks/ - Утечки памяти в Go (несмотря на GC): https://go.vbloher.org/docs/03-runtime-memory/memory-leaks/ - Модель памяти Go (Go Memory Model): happens-before и синхронизация: https://go.vbloher.org/docs/03-runtime-memory/memory-model/ - pprof: профилирование CPU, памяти и блокировок в Go: https://go.vbloher.org/docs/03-runtime-memory/pprof/ - Execution Tracer и runtime/trace: тайминги вместо агрегатов: https://go.vbloher.org/docs/03-runtime-memory/runtime-tracing/ - Стек vs Куча: где живут данные в Go: https://go.vbloher.org/docs/03-runtime-memory/stack-vs-heap/ - Тестирование: https://go.vbloher.org/docs/04-testing/ - testify, assert/require и golden files: https://go.vbloher.org/docs/04-testing/assertions-testify/ - Бенчмарки в Go: https://go.vbloher.org/docs/04-testing/benchmarks/ - Покрытие, -race и флаки-тесты: https://go.vbloher.org/docs/04-testing/coverage-race/ - Нативный fuzzing в Go (1.18+): https://go.vbloher.org/docs/04-testing/fuzzing/ - Интеграционные тесты, testcontainers-go, TestMain: https://go.vbloher.org/docs/04-testing/integration-testcontainers/ - Моки, стабы и тестируемость: https://go.vbloher.org/docs/04-testing/mocks/ - Table-driven тесты, subtests и параллельность: https://go.vbloher.org/docs/04-testing/table-driven/ - Backend: https://go.vbloher.org/docs/05-backend/ - Аутентификация и авторизация: AuthN/AuthZ, сессии vs токены, RBAC/ABAC, API keys, mTLS, секреты: https://go.vbloher.org/docs/05-backend/auth-authz/ - Graceful Shutdown HTTP/gRPC сервера в Go: https://go.vbloher.org/docs/05-backend/graceful-shutdown/ - gRPC: типы RPC, интерсепторы, контекст, метаданные, error model: https://go.vbloher.org/docs/05-backend/grpc/ - JWT (JSON Web Token): https://go.vbloher.org/docs/05-backend/jwt/ - Middleware-паттерн в Go: https://go.vbloher.org/docs/05-backend/middleware/ - net/http: Server, Handler, ServeMux, таймауты, Client и контекст: https://go.vbloher.org/docs/05-backend/net-http/ - OAuth2: роли, grant types, OIDC, токены и типовые ошибки: https://go.vbloher.org/docs/05-backend/oauth2/ - OpenAPI/Swagger, code generation, contract-first vs code-first, валидация: https://go.vbloher.org/docs/05-backend/openapi/ - Protocol Buffers: схемы, wire format, эволюция и совместимость: https://go.vbloher.org/docs/05-backend/protobuf/ - REST: принципы, версионирование, идемпотентность, статусы, пагинация, ошибки: https://go.vbloher.org/docs/05-backend/rest/ - Сети и протоколы: https://go.vbloher.org/docs/06-networking/ - Пулы соединений: http.Transport, БД, утечки: https://go.vbloher.org/docs/06-networking/connection-pooling/ - DNS: записи, резолвинг, кэширование, DNS в Go: https://go.vbloher.org/docs/06-networking/dns/ - Версии HTTP: 1.1, 2, 3: https://go.vbloher.org/docs/06-networking/http-versions/ - TCP/IP: модель, транспорт и что важно бэкендеру: https://go.vbloher.org/docs/06-networking/tcp-ip/ - TLS: handshake, сертификаты, mTLS, производительность: https://go.vbloher.org/docs/06-networking/tls/ - UDP и надёжность поверх UDP: https://go.vbloher.org/docs/06-networking/udp/ - WebSocket: upgrade, фреймы, масштабирование: https://go.vbloher.org/docs/06-networking/websocket/ - Базы данных: https://go.vbloher.org/docs/07-databases/ - Пул соединений к PostgreSQL в Go: database/sql, pgx, pgxpool, PgBouncer: https://go.vbloher.org/docs/07-databases/connection-pooling-pgx/ - Взаимоблокировки (Deadlocks) в PostgreSQL: https://go.vbloher.org/docs/07-databases/deadlocks/ - Индексы в PostgreSQL: https://go.vbloher.org/docs/07-databases/indexes/ - Уровни изоляции транзакций в PostgreSQL: https://go.vbloher.org/docs/07-databases/isolation-levels/ - MVCC в PostgreSQL: версии строк, видимость, VACUUM и bloat: https://go.vbloher.org/docs/07-databases/mvcc/ - Обзор NoSQL и Redis: https://go.vbloher.org/docs/07-databases/nosql-redis/ - Партиционирование таблиц в PostgreSQL: https://go.vbloher.org/docs/07-databases/partitioning/ - Архитектура PostgreSQL: https://go.vbloher.org/docs/07-databases/postgresql-architecture/ - Планирование и оптимизация запросов в PostgreSQL: https://go.vbloher.org/docs/07-databases/query-planning/ - Репликация в PostgreSQL: https://go.vbloher.org/docs/07-databases/replication/ - Шардирование (горизонтальное масштабирование): https://go.vbloher.org/docs/07-databases/sharding/ - Транзакции в PostgreSQL и Go (database/sql, pgx): https://go.vbloher.org/docs/07-databases/transactions/ - Распределённые системы: https://go.vbloher.org/docs/08-distributed-systems/ - CAP теорема: https://go.vbloher.org/docs/08-distributed-systems/cap-theorem/ - Circuit Breaker: https://go.vbloher.org/docs/08-distributed-systems/circuit-breaker/ - Консенсус и Raft: репликация состояния в присутствии отказов: https://go.vbloher.org/docs/08-distributed-systems/consensus-raft/ - Модели согласованности: https://go.vbloher.org/docs/08-distributed-systems/consistency/ - Гарантии доставки сообщений: at-most-once / at-least-once / exactly-once: https://go.vbloher.org/docs/08-distributed-systems/delivery-guarantees/ - Eventual Consistency: https://go.vbloher.org/docs/08-distributed-systems/eventual-consistency/ - Идемпотентность в распределённых системах: https://go.vbloher.org/docs/08-distributed-systems/idempotency/ - Apache Kafka: https://go.vbloher.org/docs/08-distributed-systems/kafka/ - Transactional Outbox: https://go.vbloher.org/docs/08-distributed-systems/outbox/ - RabbitMQ: AMQP 0-9-1, маршрутизация, надёжность доставки и сравнение с Kafka: https://go.vbloher.org/docs/08-distributed-systems/rabbitmq/ - Ретраи: backoff, jitter, budgets и идемпотентность: https://go.vbloher.org/docs/08-distributed-systems/retries/ - Saga Pattern: https://go.vbloher.org/docs/08-distributed-systems/saga/ - Observability: https://go.vbloher.org/docs/09-observability/ - Grafana: https://go.vbloher.org/docs/09-observability/grafana/ - Метрики: RED, USE, Golden Signals: https://go.vbloher.org/docs/09-observability/metrics/ - OpenTelemetry: https://go.vbloher.org/docs/09-observability/opentelemetry/ - Prometheus: https://go.vbloher.org/docs/09-observability/prometheus/ - SLI / SLO / SLA: https://go.vbloher.org/docs/09-observability/slo-sli/ - Структурированное логирование (slog): https://go.vbloher.org/docs/09-observability/structured-logging/ - Distributed Tracing: https://go.vbloher.org/docs/09-observability/tracing/ - System Design: https://go.vbloher.org/docs/10-system-design/ - Analytics Pipeline: https://go.vbloher.org/docs/10-system-design/analytics-pipeline/ - Chat System: https://go.vbloher.org/docs/10-system-design/chat/ - Фреймворк System Design интервью: https://go.vbloher.org/docs/10-system-design/framework/ - Notification Service: https://go.vbloher.org/docs/10-system-design/notification-service/ - Order Service: https://go.vbloher.org/docs/10-system-design/order-service/ - Payment Service: https://go.vbloher.org/docs/10-system-design/payment-service/ - Rate Limiter: https://go.vbloher.org/docs/10-system-design/rate-limiter/ - URL Shortener: https://go.vbloher.org/docs/10-system-design/url-shortener/ - DevOps: https://go.vbloher.org/docs/11-devops/ - CI/CD: пайплайны, стадии, стратегии деплоя: https://go.vbloher.org/docs/11-devops/cicd/ - Облака (AWS / GCP) для бэкендера: https://go.vbloher.org/docs/11-devops/cloud-aws-gcp/ - Docker для Go-разработчика: https://go.vbloher.org/docs/11-devops/docker/ - GitHub Actions и GitLab CI: https://go.vbloher.org/docs/11-devops/github-gitlab-ci/ - Kubernetes для Go-разработчика: https://go.vbloher.org/docs/11-devops/kubernetes/ - Terraform / Infrastructure as Code: https://go.vbloher.org/docs/11-devops/terraform/ - Алгоритмы: https://go.vbloher.org/docs/12-algorithms/ - Типовые алгоритмические задачи и паттерны: https://go.vbloher.org/docs/12-algorithms/common-problems/ - Асимптотическая сложность (Big-O): https://go.vbloher.org/docs/12-algorithms/complexity/ - Структуры данных в Go: https://go.vbloher.org/docs/12-algorithms/data-structures/ - Специфика live-coding на Go: https://go.vbloher.org/docs/12-algorithms/go-specifics/ - Behavioral: https://go.vbloher.org/docs/13-behavioral/ - Конфликты, разногласия и работа со стейкхолдерами: https://go.vbloher.org/docs/13-behavioral/conflicts/ - Как проходит senior-интервью: этапы, оценка, оффер: https://go.vbloher.org/docs/13-behavioral/interview-flow/ - Лидерство и менторство: https://go.vbloher.org/docs/13-behavioral/leadership-mentoring/ - Типовые поведенческие вопросы для Senior: https://go.vbloher.org/docs/13-behavioral/senior-questions/ > Модуль: DevOps · Уровень: Middle+/Senior ## TL;DR - **IaC** — инфраструктура описана кодом, версионируется в git, применяется детерминированно. Уходим от ручного «кликанья в консоли» (snowflake-серверов) к воспроизводимым, ревьюимым изменениям. - Terraform **декларативен**: вы описываете *желаемое состояние*, движок сам считает дельту между ним, текущим состоянием (state) и реальностью (refresh) и применяет минимальный набор изменений. - **State** — JSON-файл, сопоставляющий ресурсы в коде с реальными объектами в облаке (по ID). Без него Terraform не знает, что уже создано. Хранить **удалённо** (S3+DynamoDB, GCS, Terraform Cloud) с **блокировкой** (lock), иначе два одновременных apply испортят инфраструктуру. - **Цикл**: `init` (плагины+бэкенд) → `plan` (dry-run, показывает дельту) → `apply` (применяет). `plan` обязателен в review. - **Providers** — плагины к API (aws, google, kubernetes). **Modules** — переиспользуемые наборы ресурсов с input/output. **Drift** — расхождение реальности и state (кто-то поменял руками). - Best practices: remote state с локом, маленькие изолированные state'ы, модули, отсутствие секретов в state/коде в открытом виде, `plan` в CI, иммутабельность. ## Теория ### Декларативность и граф зависимостей Вы пишете, *что должно быть*, а не *как это сделать* (в отличие от императивных скриптов). Terraform строит **граф зависимостей** ресурсов (по ссылкам `resource.attr`) и применяет их в правильном порядке, параллеля независимые. ```hcl resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" } resource "aws_subnet" "app" { vpc_id = aws_vpc.main.id # ссылка => subnet зависит от vpc, создастся после cidr_block = "10.0.1.0/24" } ``` ### State: что это и зачем State — это маппинг «ресурс в конфиге ↔ реальный объект в провайдере (по ID) + закэшированные атрибуты». Терраформ использует его, чтобы: - знать, что уже существует (иначе создавал бы дубликаты); - считать дельту для plan; - хранить зависимости и метаданные. **State содержит чувствительные данные** (пароли БД, ключи, приватные поля ресурсов) в открытом виде — относитесь к нему как к секрету. #### Remote state + locking Локальный `terraform.tfstate` непригоден для команды: не шарится, нет блокировки, легко потерять. Решение — **remote backend**: ```hcl terraform { backend "s3" { bucket = "my-tf-state" key = "prod/network/terraform.tfstate" region = "eu-central-1" dynamodb_table = "tf-locks" # блокировка через DynamoDB encrypt = true } } ``` **Блокировка (lock)** критична: при `apply` Terraform берёт lock (запись в DynamoDB / условный объект в GCS / Terraform Cloud). Если кто-то уже применяет — второй apply падает с «state is locked». Без лока два параллельных apply дадут гонку и порчу state. (В новых версиях S3-бэкенд умеет нативную блокировку через lockfile, но DynamoDB-вариант всё ещё распространён.) ```bash # если процесс убит и lock завис — снять вручную (осторожно!) terraform force-unlock ``` ### Рабочий цикл ```bash terraform init # скачивает providers, настраивает backend terraform fmt # форматирование terraform validate # синтаксис/типы terraform plan -out=plan.tfplan # dry-run: что создастся/изменится/удалится terraform apply plan.tfplan # применяет ровно этот plan (без сюрпризов) terraform destroy # сносит всё из state ``` Чтение plan: - `+` create, `~` update in-place, `-` destroy, `-/+` **replace** (destroy+create — опасно для stateful-ресурсов!), `<=` read. Применяйте сохранённый `-out` plan, чтобы apply сделал ровно то, что показал plan (между plan и apply реальность могла измениться). ### Providers Плагин, реализующий CRUD к API конкретной системы. Пиньте версии — обновление провайдера может поменять поведение/схему. ```hcl terraform { required_version = ">= 1.6" required_providers { aws = { source = "hashicorp/aws", version = "~> 5.0" } google = { source = "hashicorp/google", version = "~> 5.0" } } } provider "aws" { region = "eu-central-1" } # несколько инстансов одного провайдера через alias provider "aws" { alias = "us" region = "us-east-1" } ``` ### Модули Модуль — переиспользуемый набор ресурсов с входами (`variable`) и выходами (`output`). Корневой каталог — тоже модуль (root module). ```hcl # modules/service/variables.tf variable "name" { type = string } variable "image" { type = string } variable "min_count" { type = number, default = 1 } # modules/service/main.tf -> ресурсы сервиса ... # modules/service/outputs.tf output "service_url" { value = aws_lb.this.dns_name } ``` ```hcl # использование module "api" { source = "./modules/service" # или git/registry источник, пиньте версию: "...?ref=v1.2.0" name = "api" image = "ghcr.io/org/api:sha-abc" min_count = 3 } # обращение к выходу output "api_url" { value = module.api.service_url } ``` Модули дают DRY и стандартизацию (один модуль «сервис» на десятки команд). Не плодите глубокую вложенность — это усложняет понимание. ### Переменные, count, for_each ```hcl # for_each предпочтительнее count для коллекций: # при удалении элемента из середины count "сдвигает" индексы и пересоздаёт лишнее resource "aws_s3_bucket" "b" { for_each = toset(["logs", "uploads", "backups"]) bucket = "myorg-${each.key}" } ``` ### Drift **Drift** — расхождение между state/конфигом и реальной инфраструктурой: кто-то поменял ресурс вручную в консоли, или внешний процесс. Terraform обнаруживает дрейф при `refresh` (по умолчанию в начале `plan`): сравнивает state с реальностью. ```bash terraform plan # покажет drift как изменения, которые "вернут" к конфигу terraform plan -refresh-only # только показать дрейф, не предлагая менять конфиг terraform apply -refresh-only # обновить state под реальность, не трогая ресурсы ``` Реакция на дрейф: либо вернуть как в коде (`apply`), либо узаконить изменение в коде. Лечение причины — запретить ручные правки (IAM), всё через Terraform. ### import / state операции Если ресурс создан вне Terraform — его можно завести в state без пересоздания: ```bash terraform import aws_s3_bucket.b my-existing-bucket # CLI-способ ``` ```hcl # или декларативно (Terraform 1.5+), import как код: import { to = aws_s3_bucket.b id = "my-existing-bucket" } ``` ```bash terraform state list # что в state terraform state mv A B # переименовать в state без пересоздания terraform state rm aws_x.y # убрать из state (НЕ удаляет реальный ресурс) ``` `state rm` + `import` — стандартный приём при рефакторинге (переименование ресурса/перенос в модуль) без destroy/create. ## Подводные камни / gotchas - **Локальный state в команде** = катастрофа: рассинхрон, потеря, нет блокировки. Всегда remote + lock. - **State — это секрет**: пароли/ключи лежат в нём открыто. Шифрование backend, ограничение доступа к бакету, не коммитить `*.tfstate` в git. - **Apply без сохранённого plan**: между `plan` и `apply` реальность/конфиг могли измениться — применяйте `-out` план. - **`-/+` replace stateful-ресурсов** (БД, диск): незаметно в plan можно снести prod-БД. Внимательно читайте plan; `prevent_destroy = true` в lifecycle для критичных. - **Изменение чувствительного аргумента форсит replace**: например, смена `availability_zone` инстанса. Знайте, какие поля ForceNew. - **`count` vs `for_each`**: удаление элемента из середины списка с `count` сдвигает индексы и пересоздаёт «не те» ресурсы. Для коллекций — `for_each` со стабильными ключами. - **Гигантский монолитный state**: медленный plan, большой blast radius, конфликт локов в команде. Дробите по доменам/окружениям. - **Дрейф из-за ручных правок**: state расходится, следующий apply «откатывает» чужие изменения или ломается. Дисциплина: всё через Terraform, ручные права урезаны. - **Секреты в коде/переменных в открытом виде**: используйте secret manager / `sensitive = true` (но это лишь скрывает в выводе, в state всё равно открыто). - **Незапиненные провайдеры/модули**: молчаливое обновление меняет поведение. Пиньте `version` и `ref`. - **Зависимость, не выраженная ссылкой**: Terraform не угадает порядок — используйте `depends_on` явно. ## Вопросы на собеседовании **В:** Что такое Terraform state и почему его нельзя потерять? **О:** Это маппинг ресурсов из конфига на реальные объекты в провайдере (по ID) плюс кэш их атрибутов. Без state Terraform не знает, что уже создано, и при apply создаст дубликаты или не сможет посчитать дельту. Поэтому state хранят удалённо, шифруют, бэкапят и защищают как секрет (в нём лежат пароли/ключи открытым текстом). **В:** Зачем нужна блокировка state и что будет без неё? **О:** Лок не даёт двум `apply` идти одновременно. Без него параллельные применения читают один и тот же state, делают конфликтующие изменения и перезаписывают результаты друг друга — получаем повреждённый state и рассинхрон с реальностью. Реализуется через DynamoDB (S3-backend), нативный lockfile, GCS-условную запись или Terraform Cloud. **В:** В чём разница между `plan` и `apply` и почему стоит сохранять plan? **О:** `plan` — dry-run: делает refresh, считает дельту между желаемым (конфиг) и текущим (state/реальность) состоянием и показывает, что создаст/изменит/удалит. `apply` — применяет. Если применять `plan -out=file`, то `apply file` сделает ровно показанное; иначе между plan и apply реальность может измениться, и apply сделает не то, что вы ревьюили. **В:** Что такое drift и как с ним работать? **О:** Drift — расхождение между state/кодом и реальной инфраструктурой (обычно из-за ручных изменений в консоли). Terraform ловит его при refresh в начале plan. Реакция: либо `apply` вернёт инфраструктуру к коду, либо узакониваем изменение в коде; `apply -refresh-only` синхронизирует state под реальность не трогая ресурсы. Стратегически — запретить ручные правки, всё через Terraform. **В:** Чем декларативный подход (Terraform) лучше императивных скриптов? **О:** Вы описываете желаемое состояние, а движок сам считает минимальную дельту и порядок (по графу зависимостей), идемпотентно. Императивный скрипт надо писать с учётом текущего состояния («если есть — пропусти»), он не идемпотентен и не знает, как откатить/изменить. Декларативность даёт воспроизводимость, plan-предпросмотр и управление дрейфом. **В:** Как разбивать state и почему один большой state — плохо? **О:** Большой монолитный state: медленный plan/apply (refresh всех ресурсов), огромный blast radius (ошибка/лок затрагивает всё), конфликты локов в команде. Дробят по окружениям (dev/stage/prod) и доменам (network, data, compute), связывая через remote state data source или явные input'ы. Маленький state = быстрый, изолированный, безопаснее. **В:** Чем `for_each` лучше `count` и когда что использовать? **О:** `count` адресует ресурсы по индексу — удаление элемента из середины списка сдвигает индексы и пересоздаёт «не те» ресурсы. `for_each` адресует по стабильному ключу (map/set), поэтому добавление/удаление элемента трогает только его. `count` уместен для «N одинаковых» или условного создания (`count = var.enabled ? 1 : 0`), `for_each` — для коллекций именованных ресурсов. **В:** Как завести существующий (созданный вручную) ресурс под управление Terraform? **О:** Через `terraform import` (CLI) или декларативный `import {}` блок (1.5+): он добавляет ресурс в state, сопоставляя с реальным по ID, не пересоздавая. Затем нужно написать соответствующий `resource`-блок так, чтобы plan показал «нет изменений». Это же используется при рефакторинге: `state mv`/`state rm`+`import` переносят ресурсы без destroy/create. ## На что копают на senior+ - Организация на масштабе: структура репозиториев (моно vs много), окружения (workspaces vs отдельные state vs Terragrunt), promotion изменений по env. - Управление секретами: что попадает в state, шифрование backend, интеграция с Vault/secret manager, ротация, недопущение plaintext. - CI/CD для Terraform: автоматический `plan` на PR с комментарием дельты, `apply` через approval, политики (OPA/Sentinel) на запрет опасных изменений, drift-детект по расписанию. - Безопасность изменений: `prevent_destroy`, понимание ForceNew-полей, защита stateful-ресурсов, separate state для критичных слоёв. - Версионирование и совместимость: пиннинг провайдеров/модулей, upgrade-стратегия, чтение CHANGELOG провайдеров. - Альтернативы и границы: Pulumi/CDK (императивный IaC на языке), Crossplane (k8s-native), где Terraform не лучший инструмент (конфигурация приложений vs инфраструктура).