Промты для DevOps: как я поднял CI/CD, Terraform и Kubernetes-кластер, почти не открывая документацию

Промты для DevOps: как я поднял CI/CD, Terraform и Kubernetes-кластер, почти не открывая документацию

Полтора года назад я потратил почти три дня на одну задачу: настроить multi-stage сборку Docker-образа так, чтобы кэш работал, секреты не попадали в слои, а финальный образ весил меньше 100 МБ. Три дня. Не на архитектуру, не на отладку продакшена — на рутину, которую любой опытный инженер делает за час. Проблема была не в сложности, а в переключении контекста: документация Docker, гайды по BuildKit, Stack Overflow, снова документация.

Сейчас я работаю иначе. Я всё ещё читаю официальные доки (например, docs.docker.com/build или kubernetes.io/docs), но делаю это точечно — когда нужно понять концепцию. А всю рутинную генерацию артефактов я делегирую LLM. Промт — это не «магия, которая всё сделает за тебя». Это способ зафиксировать контекст: версию, среду, ограничения — и получить черновик, который остаётся только проверить и запустить.

Ниже — подборка промтов, отсортированных по сложности: от базовых (Dockerfile, Compose) до продвинутых (Terraform-модули, Helm-чарты, GitLab CI) и экспертных (RBAC, admission-политики, GitOps). Каждый промт я привожу в том виде, в котором реально его использую, с примером результата. Важная оговорка: любой сгенерированный манифест нужно валидировать — через terraform validate, kubectl apply --dry-run=server, hadolint или kubeconform.

Базовый уровень: Docker и локальная среда

1. Multi-stage Dockerfile с кэш-маунтами

Задача: получить воспроизводимый образ для Python/Node-приложения с разделением build- и runtime-стадий.

Промт:

Ты senior DevOps. Напиши multi-stage Dockerfile для FastAPI-приложения (Python 3.12).
Требования: базовый образ python:3.12-slim, зависимости в отдельном слое для кэша,
запуск от non-root пользователя, HEALTHCHECK через /health, финальный образ минимальный.
Используй BuildKit cache mount для pip. Приведи команду сборки с --cache-to/--cache-from.

Пример результата:

# syntax=docker/dockerfile:1.7
FROM python:3.12-slim AS builder
WORKDIR /app
RUN --mount=type=cache,target=/root/.cache/pip \
    pip install --prefix=/install -r requirements.txt

FROM python:3.12-slim
RUN useradd -m appuser
COPY --from=builder /install /usr/local
COPY . /app
WORKDIR /app
USER appuser
HEALTHCHECK CMD curl -f http://localhost:8000/health || exit 1
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Проверяйте через hadolint Dockerfile — линтер поймает проблемы вроде отсутствия --no-install-recommends или непиннованных версий.

2. Docker Compose для локальной разработки

Задача: поднять приложение + Postgres + Redis одной командой.

Промт:

Сгенерируй docker-compose.yml для локальной разработки: app (build из ./),
postgres:16, redis:7. Используй healthcheck, depends_on с condition: service_healthy,
именованные volume для данных Postgres, .env-файл для переменных.

Пример результата:

services:
  db:
    image: postgres:16
    env_file: .env
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER"]
      interval: 5s
      retries: 5
    volumes:
      - pgdata:/var/lib/postgresql/data
  app:
    build: .
    depends_on:
      db:
        condition: service_healthy
    ports: ["8000:8000"]
volumes:
  pgdata:

3. Разбор ошибки сборки

Задача: LLM как «резиновый утёнок» для отладки.

Промт:

Сборка падает с ошибкой: <вставить лог целиком>.
Вот мой Dockerfile: <вставить>.
Объясни причину, предложи минимальный фикс и покажи diff.
Не переписывай файл целиком.

Ключевой приём — требовать diff, а не полный файл. Так вы видите, что именно меняется, и не теряете свои правки.

Продвинутый уровень: CI/CD и IaC

4. GitHub Actions workflow с матрицей

Задача: тесты + сборка образа + пуш в registry.

Промт:

Напиши GitHub Actions workflow. Триггеры: push в main, pull_request.
Джобы: lint (ruff), test (pytest с матрицей Python 3.11/3.12), build-and-push
(только на main, через docker/build-push-action с кэшем gha).
Пиновать actions по SHA. Добавить concurrency для отмены устаревших запусков.

Пример результата (фрагмент):

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
jobs:
  test:
    strategy:
      matrix: { python: ["3.11", "3.12"] }
    steps:
      - uses: actions/checkout@<sha>
      - uses: actions/setup-python@<sha>
        with: { python-version: ${{ matrix.python }} }

5. Terraform-модуль для VPC

Задача: сеть с публичными и приватными подсетями.

Промт:

Сгенерируй Terraform-модуль vpc для AWS (провайдер ~> 5.0).
Входные переменные: cidr_block, az_count, name. Выходные: vpc_id, public_subnet_ids,
private_subnet_ids. Подсети распредели через cidrsubnet(). Добавь variables.tf,
outputs.tf, main.tf и пример вызова в README.

Пример результата:

resource "aws_subnet" "public" {
  count             = var.az_count
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(var.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
  map_public_ip_on_launch = true
}

cidrsubnet("10.0.0.0/16", 8, 0) вернёт 10.0.0.0/24 — функция из Terraform docs.

6. Рефакторинг Terraform state

Задача: перенести ресурс в модуль без пересоздания.

Промт:

У меня ресурс aws_s3_bucket.logs в корне. Переношу его в модуль s3 (module.s3.aws_s3_bucket.logs).
Дай точные команды terraform state mv и объясни, как проверить план до применения.

Пример результата:

terraform state mv aws_s3_bucket.logs module.s3.aws_s3_bucket.logs
terraform plan  # должно быть "No changes"

7. Helm-чарт с values-схемой

Промт:

Создай структуру Helm-чарта для stateless-сервиса: Chart.yaml (apiVersion v2),
values.yaml, templates/deployment.yaml, service.yaml, ingress.yaml, _helpers.tpl.
Добавь values.schema.json для валидации обязательных полей (image.tag, replicas).

Пример результата:

# values.schema.json (фрагмент)
{"properties": {"replicas": {"type": "integer", "minimum": 1}},
 "required": ["image", "replicas"]}

8. GitLab CI с кэшем и артефактами

Промт:

Напиши .gitlab-ci.yml: стадии build/test/deploy. Кэш по ключу на основе lock-файла,
artifacts с expire_in: 1 week, rules вместо only/except, окружения staging/prod
с manual-джобой для prod.

Пример результата:

build:
  stage: build
  script: ["make build"]
  cache:
    key:
      files: ["package-lock.json"]
    paths: [".npm/"]
  artifacts:
    paths: ["dist/"]
    expire_in: 1 week

9. Kubernetes Deployment с probes

Задача: корректные liveness/readiness/startup probes.

Промт:

Напиши Deployment для приложения, которое стартует 40 секунд.
Добавь startupProbe (failureThreshold 30, periodSeconds 2), readinessProbe,
livenessProbe, resource requests/limits, securityContext (runAsNonRoot, readOnlyRootFilesystem).

Пример результата:

startupProbe:
  httpGet: { path: /health, port: 8000 }
  failureThreshold: 30
  periodSeconds: 2
resources:
  requests: { cpu: 100m, memory: 128Mi }
  limits: { cpu: 500m, memory: 512Mi }
securityContext:
  runAsNonRoot: true
  readOnlyRootFilesystem: true

Экспертный уровень: безопасность и эксплуатация

10. RBAC-роль с минимальными правами

Промт:

Сгенерируй Role и RoleBinding для CI-раннера в namespace ci:
только get/list/watch pods, create/delete jobs. Объясни, почему cluster-admin тут не нужен.

11. NetworkPolicy по принципу deny-all

Промт:

Напиши NetworkPolicy: default deny ingress+egress в namespace app,
затем разреши ingress от namespace ingress-nginx на порт 8000
и egress к DNS (kube-system, порт 53).

Пример результата:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: { name: default-deny, namespace: app }
spec:
  podSelector: {}
  policyTypes: ["Ingress", "Egress"]

12. Валидация манифестов через kubeconform

Задача: проверять YAML на соответствие схеме перед деплоем.

Промт:

Покажи, как встроить kubeconform в CI: команду с -strict -summary,
как указать версию Kubernetes (-kubernetes-version 1.30.0) и
где взять кастомные схемы для CRD.

Пример результата:

kubeconform -strict -summary -kubernetes-version 1.30.0 ./manifests/

13. GitOps через Argo CD

Промт:

Опиши Application-манифест для Argo CD: source — Helm-чарт из Git-репозитория,
syncPolicy с automated, prune, selfHeal. Добавь ignoreDifferences для поля,
которое меняет оператор.

14. Admission-политика на Kyverno

Промт:

Напиши ClusterPolicy Kyverno: запретить контейнеры без requests/limits
и с тегом latest. Для каждого правила — сообщение об ошибке
и режим audit для начала.

15. Terraform + проверка через tflint и checkov

Промт:

Как настроить pre-commit хуки для Terraform: terraform fmt, tflint, checkov.
Дай .pre-commit-config.yaml и объясни, какие проверки checkov ловит
(например, публичный S3 bucket).

16. Диагностика CrashLoopBackOff

Промт:

Под CrashLoopBackOff. Вот вывод: kubectl describe pod <name>,
kubectl logs <name> --previous. Помоги составить пошаговое дерево диагностики:
проверка exit code, ресурсов, probe, монтирования ConfigMap.

17. Оптимизация стоимости кластера

Промт:

Проанализируй: у меня 12 нод, средняя загрузка CPU 15%.
Предложи шаги по снижению стоимости: rightsizing requests,
HPA, cluster-autoscaler, spot-инстансы. Для каждого шага — риски.

18. Промт-шаблон с фиксацией контекста

Задача: сделать любой из промтов воспроизводимым.

Контекст: <облако/версия K8s/провайдер Terraform>
Ограничения: <security, cost, compliance>
Формат ответа: <YAML/HCL/bash + объяснение>
Критерии приёмки: <что проверю>

Последний пункт важнее всех остальных: LLM без контекста даёт «средний по интернету» ответ. С контекстом — черновик, который экономит часы.

Что это даёт на практике

Я не считаю, что LLM заменяет инженера. Он заменяет переключение контекста. Вместо «открыть доки → найти пример → адаптировать» вы делаете «сформулировать ограничения → получить черновик → валидировать». По моему опыту, это экономит значительную часть времени на рутинных задачах, но не отменяет ревью: terraform plan, --dry-run=server, hadolint, kubeconform — обязательная часть процесса. Если хотите системно прокачать этот навык — попробуйте формулировать промты как техзадание с критериями приёмки, а не как вопрос. Начните с одного промта из списка и доведите его до рабочего состояния в своём репозитории.

← All posts

Comments