ИИ в DevOps или как мы слепо доверяем сгенерированным манифестам. DevOps.. DevOps. kubeconform.. DevOps. kubeconform. Kubernetes.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты. llm.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты. llm. opa.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты. llm. opa. yaml.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты. llm. opa. yaml. безопасность контейнеров.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты. llm. opa. yaml. безопасность контейнеров. Блог компании OTUS.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты. llm. opa. yaml. безопасность контейнеров. Блог компании OTUS. валидация конфигураций.. DevOps. kubeconform. Kubernetes. Kubernetes-манифесты. llm. opa. yaml. безопасность контейнеров. Блог компании OTUS. валидация конфигураций. искусственный интеллект.

Меня зовут Андрей Бирюков. Я — независимый эксперт в области ИТ и ИБ, преподаю в учебных центрах и пишу статьи и книги.

Искусственный интеллект у нас есть везде, и, конечно, в ИТ, а точнее в DevOps, он тоже имеется. Многие, особенно начинающие инженеры, часто просят ИИ сгенерировать, к примеру, манифест Kubernetes Deployment.

И нейросеть послушно выполняет поставленную задачу, при этом не спрашивая, какая версия кластера у вас запущена, не проверяя, какие CRD установлены, и не интересуясь, что отклоняет ваш admission controller.

Вместо этого, LLM просто сгенерирует YAML, который «выглядит правильно» на основе наиболее частых паттернов из обучающих данных.

ИИ создавался в том числе для того, чтобы облегчить ручной труд, поэтому вместо того, чтобы полностью отказываться от использования нейросетей в задачах DevOps, давайте попробуем разобраться в проблеме. Здесь корень всех бед кроется в смещении обучающих данных.

Основной корпус LLM составляют публичные Dockerfile, репозитории на GitHub и туториалы.

Их объединяет одно:

Они «запускаются на ноутбуке разработчика», а не «безопасно работают в production‑кластере».

Модель корректно воспроизводит эту небезопасную норму, а не совершает какую‑то «ошибку».

В общем‑то, это логично, мало кто публикует свои dockerfile, предназначенные для использования в продуктивной среде, это не очень безопасно. Поэтому нейросети и учатся на учебных примерах.

Исследование 2026 года дало количественный результат: в тестах на инфраструктурный код развертывания (контейнеры, CI/CD‑конфигурации и так далее) средний уровень уязвимостей в сгенерированном ИИ коде достигает 57,5%, что заметно хуже, чем показатели для обычного прикладного кода.

При этом Dockerfile показал худший результат среди всех типов артефактов, близкий к «повсеместному провалу».

ИИ в DevOps или как мы слепо доверяем сгенерированным манифестам - 1

Давайте рассмотрим небольшой пример, демонстрирующий глючность ИИ‑шных манифестов.

Перед нами стояла задача сгенерировать манифест Deployment для Go‑сервиса, при этом кластер работал на Kubernetes 1.27.

ИИ был передан, может, и не очень подробный, но достаточно конкретный промпт:

ИИ в DevOps или как мы слепо доверяем сгенерированным манифестам - 2

ИИ вернул YAML, семантически вроде бы полностью разумный, apiVersion указана правильная, лимиты ресурсов на месте.

После деплоя этого манифеста Pod успешно перешел в состояние Running, сервис отвечал нормально.

То есть вроде бы всё хорошо, но через неделю утечка памяти привела Pod в состояние «ложной смерти», то есть HTTP‑порт он слушал, но все запросы таймаутились. При этом Liveness probe не сработал и не перезапустил Pod.

Причина такого странного поведения скрывалась в синтаксисе манифеста, сгенерированного ИИ.

Хотя наш yaml и проходил валидацию в версии 1.27, но семантика некоторых полей изменилась, и они были молча проигнорированы кубом.

С точки зрения кластера «ничего не сломалось», потому что API server принял ресурс в работу. Но пробники, ответственные за проверку работоспособности, никогда реально не работали.

И ключевой характеристикой этого паттерна отказа является отсутствие сообщений об ошибках.

Логи чистые, события нормальные, kubectl get pod показывает состояние Running. Вы просто не знаете, почему health check не работает.

Теперь давайте подробнее поговорим о наиболее типичных ошибках, которые создают нейросети на уровне кода.

Устаревшие apiVersion

Первая строка любого манифеста ApiVersion, казалось бы, просто синтаксическая конструкция. Но на самом деле неверная версия API это хотя и самая заметная, но в тоже время и самая частая ошибка.

Дело в том, что ИИ очень любит генерировать для Deployment строки вида: apiVersion: extensions/v1beta1. Однако, этот API был удален достаточно давно, в Kubernetes 1.16, то есть в 2019 году. Но модель генерирует его потому, что в ее обучающих данных этот синтаксис когда‑то был повсюду, и она выдает его «уверенно», без предупреждений и оговорок.

Похожая история и с Ingress: networking.k8s.io/v1beta1 удален, но ИИ продолжает его использовать в сгенерированных манифестах. Но здесь гораздо опаснее ошибки на уровне полей, например spec.rules[].http.paths[].backend.serviceName в новом API заменен структурой backend.service.name, но сгенерированный ИИ манифест в старом синтаксисе все еще «формально корректен». И вообще, сейчас Ingress официально уже не поддерживается и его использование в сгенерированных манифестах уже является дурным тоном.

Кстати, этим грешат и поисковики, когда выдают в топах выдачи статьи с устаревшими примерами конфигов и кода.

Отсутствующий securityContext

У сгенерированного ИИ Deployment есть, а вернее нет securityContext. В учебных примерах это понятно, но в манифестах для продуктива такой подход неприемлем. Это же настоящий рай для атакующего:

  • контейнер по умолчанию работает от root,

  • allowPrivilegeEscalation по дефолту тоже true,

  • readOnlyRootFilesystem наоборот false,

  • да и capabilities не сброшены.

И это совсем не мелочь, так как контейнер, работающий от root, означает, что любая уязвимость исполнения кода на уровне приложения напрямую превращается в root-in-container. При неправильно настроенном runtime это может стать первым шагом к побегу на хостовую машину с правами root.

ИИ в DevOps или как мы слепо доверяем сгенерированным манифестам - 3

Почему «выглядит правильно» — самый опасный сигнал

Низкокачественный цифровой контент принято называть нейрослопом, но сгенерированные ИИ манифесты как правило, не особо похожи на кривой конфиг. У созданных нейросетями манифестов есть обманчивая черта:

  • идеальный синтаксис,

  • разумная структура,

  • аккуратное форматирование,

  • подробные комментарии.

А еще отступы правильные, имена полей без опечаток, уровни вложенности четкие, в общем прямо как в учебниках по разработке. Это создает у инженера иллюзию, что «модель знает, что делает».

А еще поведение сервера Kubernetes API только усугубляет проблему. Когда манифест не содержит какое‑то устаревшее поле, API server реагирует двумя способами.

Либо отклоняет с ошибкой (и это как раз нормально) или молча отбрасывает.

Во втором случае вы получаете частично примененный ресурс, то есть часть намерений из манифеста реализована, а часть просто проигнорирована.

В качестве примера можно привести PodSecurityPolicy. Этот ресурс был официально удален в Kubernetes 1.25, но ИИ по‑прежнему генерирует синтаксически валидные PSP‑манифесты, kubeconform в некоторых мягких конфигурациях тоже не выдаст ошибку, но API server примет объект ресурса (!) и никогда не будет его исполнять.

Вы «думаете», что у вас есть ограничения прав контейнеров, а на самом деле ничего нет.

ИИ в DevOps или как мы слепо доверяем сгенерированным манифестам - 4

Валидация как мышечная память

Но что же все‑таки делать, если мы не хотим полностью отказываться от использования ИИ для генерации манифестов. Прежде всего, необходимо провести валидацию схемы под версию вашего кластера.

То есть не надо верить ИИ, когда он говорит «это поле валидно». Вместо этого используйте kubeconform для офлайн‑проверки под фактическую версию кластера:

kubectl version --short

Допустим, у нас 1.27, в таком случае делаем strict‑валидацию под точную версию

kubeconform -kubernetes-version 1.27.0 -strict manifest.yaml

Флаг -strict отклоняет любое неизвестное ему поле и тем самым ловит большую часть проблем с устаревшими именами полей. Если пропустить этот шаг и сразу выполнить kubectl apply, стоимость исправления будет намного выше.

Кстати, работу с Kubernetes на практике мы разбираем и на открытом уроке — поговорим о развертывании кластера с помощью Terraform и Ansible.

OPA‑политики для того, что schema не поймает

Представленная выше Schema‑валидация скажет только «существует ли это поле», но она не скажет «безопасна ли эта конфигурация». Для этого нам нужен набор Rego‑политик, который проверит то, что ИИ чаще всего игнорирует:

# policy/kubernetes.rego
package main

# Отклонять контейнеры без runAsNonRoot

deny[msg] {
    input.kind == "Deployment"
    container := input.spec.template.spec.containers[_]
    not container.securityContext.runAsNonRoot
    msg := sprintf("Container '%s' must set runAsNonRoot: true", [container.name])
}

# Отклонять образы с тегом :latest

deny[msg] {
    input.kind == "Deployment"
    container := input.spec.template.spec.containers[_]
    endswith(container.image, ":latest")
    msg := sprintf("Container '%s' uses :latest tag, pin to a specific version", [container.name])
}

# Требовать наличия лимитов ресурсов

deny[msg] {
    input.kind == "Deployment"
    container := input.spec.template.spec.containers[_]
    not container.resources.limits.memory
    msg := sprintf("Container '%s' missing memory limit", [container.name])
}

Затем запускаем через conftest:

conftest test manifest.yaml --policy policy/

Эти вроде бы несложные правила блокируют самые опасные значения по умолчанию в сгенерированных ИИ манифестах.

Server‑side dry‑run как последняя линия обороны

Если у вас есть доступ к кластеру, то kubectl --dry-run=server является самым точным способом валидации. Он не сверяется со schema, а заставляет API server реально обработать запрос, то есть запустить все admission webhook, проверить все поля, выполнить инъекцию всех значений по умолчанию, но без персистенции.

kubectl apply --dry-run=server -f ai-generated-manifest.yaml

Если выполнение команды проходит молча, без ошибок, вы как минимум знаете, что API server в текущей версии принимает этот ресурс. Это все еще не гарантирует разумность securityContext (это задача уровня политик), но гарантирует, что манифест, который вы видите, представляет собой YAML, который кластер реально сохранит, без молча отброшенных полей.

Практические итоги

В заключении давайте еще раз проговорим, что нужно сделать при запуске манифеста в непесочном окружении.

Прежде всего необходимо прогнать kubeconform -strict под версию вашего кластера.

Затем выполняем conftest с политиками, как минимум должно быть покрыто:

  • runAsNonRoot,

  • тег :latest,

  • лимиты ресурсов.

Также проверяем наличие securityContext, так как если в сгенерированном ИИ манифесте этого поля нет, то по умолчанию это root.

И в завершении делаем kubectl --dry-run=server.

Ну и в целом, относимся к сгенерированной конфигурации с подозрением. Семантика полей меняется между версиями часто, и schema‑валидация не обязательно поймает семантические проблемы.

Основной принцип прост: вывод ИИ — это черновик, а не готовый продукт.

Модель генерирует манифест, который «выглядит правильным» в обучающих данных, а не манифест, спроектированный под ваш кластер, вашу версию, ваши политики безопасности.

Существование слоя валидации это не недоверие к ИИ, а инженерное управление тем разрывом, который лежит между «генерацией» и «развертыванием».

ИИ в DevOps или как мы слепо доверяем сгенерированным манифестам - 5

Если вы уже используете ИИ в DevOps, следующий вопрос возникает довольно быстро: как дать модели данные о реальном состоянии инфраструктуры, а не заставлять её строить догадки по контексту из промпта?

Разобраться с этим на практике можно на бесплатном демо-уроке OTUS: посмотрим, как связать ИИ с данными мониторинга, чтобы быстрее находить проблемы в инфраструктуре и принимать решения на основе реальных метрик.

  • 14 октября в 20:00. «ИИ для мониторинга: что Prometheus и Grafana могут рассказать агенту». Записаться

Полный список открытых уроков октября собрали в дайджесте.

Автор: Andrey_Biryukov

Источник