Промты для Kubernetes и Terraform: как я перевёл деплой в GitOps и перестал тушить прод в 3 часа ночи
Три ночи подряд я просыпался от алерта CrashLoopBackOff в Slack. Причина каждый раз была одна и та же: кто-то руками поправил kubectl edit deployment, состояние кластера разошлось с репозиторием, а следующий terraform apply снёс правку. Классическая проблема «configuration drift» — расхождения между декларативным описанием инфраструктуры и реальным состоянием.
Решение оказалось не в покупке нового инструмента, а в смене процесса: перевести всё в GitOps, где единственный источник правды — Git-репозиторий, а ArgoCD синхронизирует кластер с ним. Но переписывать сотни манифестов и модулей руками — это недели работы. Здесь мне и помогли промты для LLM: не как замена инженеру, а как ускоритель рутины — генерации boilerplate, ревью YAML и разбора логов.
Ниже — 14 промтов, которые я реально использую в ежедневном workflow. Каждый закрывает конкретный кусок рутины: от написания Terraform-модуля до диагностики упавшего пода. Все примеры проверены на Kubernetes 1.30+, Terraform 1.9 и ArgoCD 2.12.
Как я формулирую промты для инфраструктуры
Правило простое: чем больше контекста о версии, провайдере и ограничениях — тем меньше галлюцинаций. LLM уверенно выдумывает несуществующие поля в CRD и устаревшие аргументы провайдеров, если не указать версию явно. Поэтому в каждом промте ниже есть версии, scope и требование не придумывать поля.
| Категория | Что закрывает | Экономия времени |
|---|---|---|
| Kubernetes manifests | Генерация и ревью YAML, probes, resources | ~2–3 ч/нед |
| Terraform | Модули, state, drift, plan-ревью | ~3–4 ч/нед |
| Debug | CrashLoopBackOff, ImagePullBackOff, OOMKilled | часы в инцидентах |
| GitOps / ArgoCD | Sync, Application CR, app-of-apps | ~2 ч/нед |
| CI/CD | Пайплайны, кэш, security-скан | ~2 ч/нед |
1. Генерация production-ready Deployment
Рутина: каждый новый сервис требует манифеста с ресурсами, probes, security context и anti-affinity. Писать с нуля — 30–40 минут.
Промт:
Сгенерируй Kubernetes Deployment (apiVersion apps/v1, k8s 1.30)
для сервиса на Go. Образ: ghcr.io/acme/orders-api:v1.4.2.
Требования:
- 3 реплики, RollingUpdate maxSurge=1 maxUnavailable=0
- readinessProbe и livenessProbe на /healthz (порт 8080)
- resources.requests/limits (cpu/memory)
- securityContext: runAsNonRoot, readOnlyRootFilesystem
- topologySpreadConstraints по зонам
Не выдумывай поля. Если сомневаешься в поле — помечай комментарием.
Что получаю: готовый YAML с корректным topologySpreadConstraints. Руками я обычно забывал readOnlyRootFilesystem — теперь он в шаблоне по умолчанию.
2. Ревью манифеста как строгий линтер
Рутина: PR с YAML никто не ревьюит внимательно — все смотрят на diff и жмут merge.
Промт:
Ты — ревьюер Kubernetes-манифестов. Проверь YAML ниже по чеклисту:
1. Задан ли resources.limits для cpu и memory?
2. Есть ли livenessProbe и readinessProbe?
3. securityContext: runAsNonRoot, allowPrivilegeEscalation=false?
4. Не используется ли тег image :latest?
5. Указан ли namespace явно?
Выведи таблицу: Проблема
| Строка | Severity | Как исправить.
Не хвали, только замечания.
Почему работает: явный чеклист убирает вежливые «в целом хорошо». Модель выдаёт список замечаний, который можно скопировать в комментарии PR.
3. Дебаг CrashLoopBackOff по логам
Рутина: контейнер в цикле перезапуска, kubectl logs --previous нужен, но забываешь про этот флаг.
Промт:
Под в CrashLoopBackOff. Вот вывод:
kubectl describe pod (события) и kubectl logs --previous.
[вставить логи]
Определи root cause. Раздели на:
- гипотеза 1 + как проверить (команда)
- гипотеза 2 + как проверить
- что точно НЕ причина
Не предлагай перезапустить под — это не решение.
Кейс: однажды модель по логам dial tcp 10.96.0.10:53: connection refused сразу указала на CoreDNS, а не на само приложение. Экономия — минут 40 поиска.
4. Terraform-модуль с переменными и outputs
Рутина: модуль для S3-бакета с версионированием, шифрованием и lifecycle-политикой — 20 минут copy-paste.
Промт:
Напиши Terraform-модуль (>= 1.9) для AWS S3 bucket.
Входные переменные: bucket_name (string), versioning (bool, default true),
lifecycle_days (number, default 90).
Обязательно: server_side_encryption (AES256), public_access_block,
lifecycle_rule для перехода в STANDARD_IA и expiration.
Выведи outputs: bucket_arn, bucket_id.
Используй only реальные аргументы провайдера hashicorp/aws ~> 5.0.
Важно: всегда проверяю terraform validate и terraform plan — LLM иногда путает блоки lifecycle в resource и в module.
5. Аудит configuration drift
Рутина: кластер вручную поправлен, Git — нет. Найти расхождения глазами нереально.
Промт:
Сравни два YAML: (A) версия из Git-репозитория,
(B) вывод kubectl get deploy -o yaml из кластера.
Игнорируй метаданные: resourceVersion, uid, generation,
status, creationTimestamp, managedFields.
Выведи только смысловые расхождения в spec.
Формат: путь в spec
| значение в Git | значение в кластере | риск.
Результат: список из 3–5 реальных расхождений вместо тысячи строк diff от kubectl diff.
6. Настройка Helm-чарта с values
Рутина: обернуть Deployment+Service+Ingress+HPA в чарт — час работы.
Промт:
Создай структуру Helm chart (apiVersion v2) для веб-сервиса.
Файлы: Chart.yaml, values.yaml, templates/deployment.yaml,
templates/service.yaml, templates/ingress.yaml, templates/hpa.yaml,
templates/_helpers.tpl.
values.yaml: image.repository, image.tag, replicaCount, resources,
ingress.enabled, ingress.hosts, autoscaling.enabled.
Используй {{ include "chart.fullname" . }} для имён.
Не используй deprecated поля.
7. ArgoCD Application CR (app-of-apps)
Рутина: подключение сервиса к GitOps — это Application-манифест с syncPolicy, а не просто «нажми Sync».
Промт:
Напиши ArgoCD Application (argoproj.io/v1alpha1, ArgoCD 2.12).
repoURL: git@github.com:acme/k8s-manifests.git, targetRevision: main,
path: apps/orders, destination: https://kubernetes.default.svc, namespace orders.
syncPolicy: automated с prune=true, selfHeal=true, allowEmpty=false.
Добавь retry с limit=5 и backoff. Пометь, какие поля критичны для безопасности.
Почему selfHeal: true важен: именно он закрывает ручные kubectl edit — ArgoCD откатывает drift сам. По официальной документации ArgoCD, selfHeal синхронизирует кластер при отклонении от Git.
8. Диагностика OOMKilled и подбор ресурсов
Рутина: под убит по памяти, непонятно — утечка или занижен limit.
Промт:
Под получил OOMKilled (exit code 137). Данные:
- requests.memory = 256Mi, limits.memory = 512Mi
- kubectl top pod показывает рост до 480Mi за 10 минут
- приложение: Node.js
Что вероятнее: утечка или заниженный limit?
Как проверить через kubectl top и metrics-server?
Предложи безопасный новый limit и объясни риск.
Правило, которое я вывел: requests = реальное потребление в steady-state, limit = ×1.5 от пика. Промт помогает посчитать, а не гадать.
9. Terraform plan — ревью перед apply
Рутина: terraform plan на 800 строк, глазами не читается, а там может быть destroy прода.
Промт:
Вот вывод terraform plan (текст). Найди:
1. Все ресурсы с действием destroy или replace (force new).
2. Изменения в security groups и IAM — потенциальные дыры.
3. Ресурсы, где меняется только tag (можно игнорировать).
Выведи три списка отдельно. Если destroy затрагивает stateful
ресурсы (RDS, EBS) — выдели как CRITICAL.
Кейс: этот промт поймал replace на RDS-инстансе из-за изменения identifier — apply бы пересоздал базу. Обошлось.
10. CI/CD пайплайн с security-сканом
Рутина: GitHub Actions с build, test, scan, push — каждый раз собираю по кускам.
Промт:
Напиши GitHub Actions workflow (.github/workflows/deploy.yml).
Триггер: push в main и pull_request.
Jobs:
1. build: docker build с кэшем (actions/cache или buildx cache-to/from).
2. scan: Trivy (aquasecurity/trivy-action) на CRITICAL, fail на уязвимостях.
3. push: только на main, в ghcr.io, тег = SHA коммита.
Используй актуальные версии actions (checkout@v4, setup-buildx).
Не используй deprecated set-output.
11. NetworkPolicy для zero-trust
Рутина: по умолчанию все поды видят друг друга — это дыра.
Промт:
Напиши NetworkPolicy (networking.k8s.io/v1) для namespace orders.
Дефолт: deny all ingress. Разрешить:
- ingress от namespace ingress-nginx на порт 8080;
- egress только к DNS (kube-system, порт 53) и к БД в namespace data (5432).
Поясни, почему egress-правило с DNS обязательно,
иначе разрешение по имени не сработает.
Нюанс: без egress к CoreDNS разрешения по DNS-именам ломаются — модель это объясняет, если попросить.
12. Миграция с kubectl apply на GitOps
Рутина: перевод легаси-кластера на GitOps без простоя.
Промт:
Составь пошаговый план миграции кластера с ручного kubectl apply
на ArgoCD без downtime. Учти:
- как выгрузить текущее состояние (kubectl get -o yaml) и убрать
служебные поля (status, managedFields, resourceVersion);
- как разбить на Application по namespace;
- как использовать syncPolicy с selfHeal постепенно (сначала manual sync);
- как проверить, что ArgoCD не удалит ресурсы (prune=false на старте).
Дай команды для каждого шага.
13. Траблшутинг ImagePullBackOff
Рутина: образ не тянется — причин пять (тег, registry, secret, network, arch).
Промт:
ImagePullBackOff для образа ghcr.io/acme/api:latest.
Вот вывод kubectl describe pod. [вставить]
Прогони по причинам по порядку:
1. существует ли тег (команда для проверки через docker manifest inspect);
2. есть ли imagePullSecrets и верный ли secret;
3. совпадает ли архитектура образа и ноды (amd64/arm64);
4. доступен ли registry из кластера.
Скажи, какая причина по событиям наиболее вероятна.
14. Terraform state — безопасные операции
Рутина: нужно удалить ресурс из state, но не из облака. Ошибка = прод удалён.
Промт:
Мне нужно убрать ресурс aws_s3_bucket.logs из Terraform state,
не удаляя сам бакет в AWS. Terraform 1.9.
Дай точную команду terraform state rm и объясни разницу
с terraform destroy. Добавь предварительные шаги:
бэкап state (terraform state pull > backup.tfstate)
и проверку, что ресурс управляется только этим state.
Почему это критично: terraform state rm не трогает облако, а destroy — удаляет. Разница в одну команду, а цена — прод-бакет.
Как встроить это в ежедневный workflow
Я не копирую ответы модели слепо. Схема такая: промт → ответ → terraform validate / kubectl apply --dry-run=server / helm template → ревью глазами → merge в Git → ArgoCD синхронизирует. Модель пишет черновик, финальное решение и ответственность — на инженере.
Полезные официальные источники, на которые я опираюсь при проверке:
- Kubernetes API reference — точные поля манифестов;
- Terraform Registry — актуальные аргументы провайдеров;
- ArgoCD docs — syncPolicy и Application CRD;
- Helm docs — структура чарта.
Главный вывод за полгода: GitOps убирает ночные инциденты не потому, что ArgoCD умный, а потому что исчезает класс проблем «кто-то поправил прод руками». Промты снимают рутину вокруг этого перехода — генерацию YAML, ревью plan и разбор логов. Начните с одного промта: возьмите манифест, который давно хотели привести в порядок, и прогоните его через ревью-промт №2. Дальше процесс затянет сам.
Comments