Консоль безопасности Kubernetes: OSS-стек с MCP и ИИ

Архитектура

Единственная находка в области безопасности Kubernetes почти никогда не раскрывает полной картины.

Это справедливо вне зависимости от того, откуда пришёл сигнал — из системы обнаружения угроз в реальном времени, сканера уязвимостей, инструмента оценки конфигурации или контроля допуска.

  • «В контейнере запущен шелл» — это может быть чрезвычайной ситуацией. А может — шумным отладочным контейнером, CI-задачей или просто рабочей нагрузкой, появившейся по недосмотру в YAML.

  • Критическая CVE может требовать немедленного внимания. А может быть зарыта в пути к пакету, до которого приложение никогда не добирается.

  • Провальная проверка конфигурации может означать реальную уязвимость. А может — малозначимый контроль, висящий нетронутым уже полгода.

Полезный вопрос звучит не так:

«Что нашёл этот инструмент?»

А вот так:

«Что означает эта находка в контексте?»

Какая рабочая нагрузка затронута? Какой образ запущен? Есть ли в нём критические или устранимые уязвимости? Были ли уже у пода проблемы с конфигурацией? Пропустил ли контроль допуска что-то рискованное? Проявляла ли рабочая нагрузка подозрительное поведение во время выполнения?

Большинство инструментов с открытым исходным кодом для безопасности Kubernetes отвечают лишь на один срез этих вопросов.

  • Falco видит поведение во время выполнения.

  • Trivy видит уязвимые образы.

  • Kubescape видит отклонения в конфигурации и соответствии требованиям.

  • Kyverno видит нарушения политик и решения о применении.

Проблема не в слабости этих инструментов. Проблема в том, что сами по себе они не превращаются в единую поверхность расследования.

Именно об этом данная серия: построить консоль безопасности Kubernetes с открытым исходным кодом, которая собирает сигналы о конфигурации, уязвимостях, политиках и поведении во время выполнения, предоставляет их через нативные для Kubernetes объекты там, где это возможно, и подключает эти данные к MCP-серверу, чтобы ИИ-агент мог помочь с сортировкой (triage) по всему стеку. Никакой магии. Никакого автономного устранения проблем. Никакого «ИИ чинит ваш кластер, пока вы потягиваете овсяный латте». Просто структурированные данные о безопасности, вменяемый слой запросов и воспроизводимые рабочие процессы.

Архитектурная ставка этой серии проста: использовать CRD Kubernetes как общую поверхность данных безопасности везде, где это возможно, а сверху разместить MCP в качестве слоя запросов. Это фундамент, на котором строится всё остальное. Но всё это будет постоянно меняться — не стоит ожидать, что финальный продукт охватит всё задуманное: в итоге его станет значительно больше.

Следите за изменениями здесь, обновления будут выходить быстро: https://github.com/sf-matt/k8s-sec-stack

Обзор архитектуры

flowchart TD
subgraph cluster["Kubernetes Cluster"]
falco["Falco<br/>Runtime Threat Detection"]
sidekick["Falcosidekick"]
sink["Runtime Event Sink<br/>Falco Alert Store"]
trivy["Trivy Operator<br/>Vulnerability Scanning"]
kubescape["Kubescape Operator<br/>Posture + Compliance"]
kyverno["Kyverno<br/>Policy Enforcement"]
crds["Kubernetes CRDs<br/>Shared Security Data Surface"]
end
falco --> sidekick
sidekick --> sink
trivy --> vuln["VulnerabilityReport CRDs"]
kubescape --> posture["Posture / Compliance CRDs"]
kyverno --> policy["PolicyReport CRDs"]
vuln --> crds
posture --> crds
policy --> crds
crds --> mcp["MCP Server<br/>Typed Security Tools"]
sink --> mcp
mcp --> skills["Agent Skills<br/>/triage-threat<br/>/posture-check<br/>/fix-image"]
skills --> agent["Claude<br/>Query + Triage Layer"]

Диаграмма намеренно скучна в одном важном смысле: большая часть стека — это просто ресурсы Kubernetes.

Trivy Operator записывает результаты сканирования уязвимостей прямо в кластер. Kubescape записывает данные о конфигурации и соответствии требованиям. Kyverno записывает результаты применения политик. Всё это становится доступным для запросов через Kubernetes API.

Falco — исключение. Он создан для потоковой передачи событий времени выполнения, а не для записи долгоживущих CRD. Поэтому Falcosidekick направляет эти события в лёгкий приёмник (sink), который MCP-сервер может опрашивать наряду с более медленно меняющимися данными из CRD.

Это разделение принципиально:

Сигнал Паттерн хранения Причина

Уязвимости

CRD

Привязаны к образам и рабочим нагрузкам

Конфигурация

CRD

Привязаны к контролям, ресурсам и пространствам имён

Политики

CRD

Привязаны к результатам политик допуска и фонового режима

Оповещения времени выполнения

Event sink

Быстро меняющийся поток поведения

Это даёт агенту две основные поверхности для запросов:

  • Kubernetes CRD — для долговременного состояния безопасности

  • Event sink времени выполнения — для недавних поведенческих оповещений

Всё остальное строится на этом.

Корреляция против покрытия на практике

Сделаем это конкретным. Предположим, рабочая нагрузка в пространстве имён demo вызывает оповещение времени выполнения:

Unexpected shell spawned in container
namespace=demo
pod=checkout-api-7c9dfb8f6d-k2p9s
container=checkout-api
command=/bin/sh

Это полезно, но недостаточно. Шелл в контейнере может означать активный взлом. Может быть сеансом отладки. Может быть сборочным заданием, которое просто выглядит подозрительно. Может быть ничем. Может быть очень даже не ничем.

Следующий шаг — контекст.

Сначала определяем рабочую нагрузку, которой принадлежит под:

kubectl get pod checkout-api-7c9dfb8f6d-k2p9s -n demo \
-o jsonpath='{.metadata.ownerReferences[0].name}{"\n"}'

Затем проверяем образ:

kubectl get pod checkout-api-7c9dfb8f6d-k2p9s -n demo \
-o jsonpath='{.spec.containers[?(@.name=="checkout-api")].image}{"\n"}'

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

kubectl get vulnerabilityreports -n demo

Возможно, в образе есть несколько критических CVE с доступными исправлениями. Это может изменить картину.

Проверяем результаты политик:

kubectl get policyreports -n demo

Возможно, Kyverno предупреждал, что эта рабочая нагрузка допускает повышение привилегий или не имеет требуемого контекста безопасности. Это тоже может изменить картину.

Затем проверяем данные о конфигурации:

kubectl get clustercompliancereports

Возможно, Kubescape отмечал опасные возможности (capabilities), привилегированные рабочие нагрузки или слабую конфигурацию сервисных аккаунтов.

Теперь оповещение — уже не просто:

Shell spawned in container.

Оно превращается в:

Shell spawned in a workload running an image with fixable critical CVEs,
existing policy audit failures, and known posture issues.

Это значительно более полезная формулировка. И это именно та формулировка, которую я не хочу собирать вручную каждый раз, когда происходит что-то интересное. Делать это руками — как подниматься по лестнице на верхушку башни Salesforce. Технически возможно, но лифт-то есть.

Этот разрыв призвана закрыть консоль. Она должна отвечать на более качественные вопросы, чем способен дать любой отдельный инструмент:

Show me recent runtime alerts from workloads with critical vulnerabilities.
Summarize risk for the workload that triggered this alert.
Which audit-mode Kyverno findings should become enforced policies first?

Суть не в том, что MCP магическим образом понимает безопасность Kubernetes. Суть в том, что MCP может предоставлять конкретные инструменты для работы с реальными данными кластера:

list_runtime_events(namespace, hours)
list_vuln_reports(namespace, severity)
list_policy_violations(namespace, result)
list_compliance_reports(framework)

Вот так мы переходим от покрытия к корреляции.

Не: «У меня есть оповещение времени выполнения, отчёт об уязвимостях, отчёт о конфигурации и отчёт о политиках».

А: «Эта конкретная рабочая нагрузка рискованна, потому что эти сигналы пересекаются».

Почему CRD — это общая поверхность

Архитектурная ставка этого проекта проста:

Если инструмент безопасности Kubernetes может записывать полезные находки обратно в Kubernetes, эти данные становятся гораздо удобнее для корреляции.

Именно поэтому CRD так важны. Без общей поверхности каждый инструмент превращается в собственный маленький островок выходных данных.

Falco генерирует события времени выполнения. Trivy может выдавать результаты сканирования. Kubescape может выдавать данные о конфигурации. Kyverno может выдавать результаты политик. У каждого есть ценность, но у каждого также свой формат, модель запросов, паттерн хранения и операционный беспорядок.

Parse this JSON.
Normalize that field.
Map this pod name to that owner.
Join this image reference to that vulnerability report.
Store this event somewhere.
Hope none of the output formats change next week.

В этом стеке я хочу избежать всего этого по максимуму. CRD дают нам лучшую отправную точку, потому что превращают находки безопасности в нативные объекты Kubernetes.

Это означает, что мы получаем:

One API surface
Kubernetes RBAC
Namespaces
Labels
Owner references
Watch behavior
kubectl compatibility

CRD — не идеальное решение. Они не являются SIEM-системой. Они не являются хранилищем данных. Хранить в них события за шесть месяцев и называть это наблюдаемостью — не лучшая идея. Но для консоли безопасности внутри кластера это очень удобная общая поверхность.

Находки безопасности как объекты Kubernetes

Полезный паттерн выглядит так:

Tool finds something
→ Tool writes a Kubernetes object
→ MCP server queries Kubernetes
→ Agent receives structured security context

Это куда чище, чем учить агента понимать сырой вывод каждого инструмента. Инструменты в этом стеке вносят разные виды нативного для Kubernetes состояния безопасности:

Инструмент Основной сигнал Нативный вывод Kubernetes

Trivy Operator

Уязвимости и аудит конфигурации

VulnerabilityReport, ConfigAuditReport

Kyverno

Результаты политик допуска и фонового режима

PolicyReport, ClusterPolicyReport

Kubescape

Данные о конфигурации и соответствии

Ресурсы, ориентированные на соответствие и конфигурацию

Falco

Оповещения об угрозах времени выполнения

Поток событий через Falcosidekick

Теперь медленно меняющиеся сигналы можно запрашивать через Kubernetes API и связывать с реальными ресурсами Kubernetes.

У рабочих нагрузок есть пространства имён. У подов есть метки. У ReplicaSet есть владельцы. Образы привязаны к контейнерам. Отчёты о политиках ссылаются на ресурсы. Отчёты об уязвимостях ссылаются на образы.

Отдача

Уже одна простая команда показывает контуры системы:

kubectl get vulnerabilityreports,policyreports -A

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

Which workloads have critical vulnerabilities?
Which policy failures affect the same namespace?
Which findings belong to the workload that triggered a runtime alert?
Which namespaces have the most overlapping risk?

Консоль начинает не с нуля. Она начинает с объектов, которые уже знают, что живут в Kubernetes.

Исключение Falco

Falco — исключение из паттерна CRD. Это не проблема, просто другой вид сигнала.

Отчёты об уязвимостях, результаты политик и данные о конфигурации относительно долговечны. Они описывают текущее или недавнее состояние рабочих нагрузок и конфигурации кластера. Оповещения времени выполнения — иное. Это быстро меняющиеся события.

Запуск шелла в контейнере — не состояние кластера в том же смысле, что провальный результат политики. Это событие, произошедшее в конкретный момент времени.

Поэтому архитектура обрабатывает Falco отдельно:

Falco
→ Falcosidekick
→ Runtime event sink
→ MCP server

Falcosidekick обеспечивает чистый путь маршрутизации, не навязывая оповещениям времени выполнения ту же модель, что и CRD. В продакшн-окружении таким приёмником мог бы быть Loki, Elasticsearch, Datadog, Splunk или другое хранилище событий. В рамках этой серии достаточно лёгкого HTTP-приёмника, чтобы паттерн работал.

Главное — MCP-сервер может опрашивать обе поверхности:

Kubernetes CRDs for durable security state
Runtime event sink for recent behavior

Почему это важно для MCP

Именно CRD-ориентированный паттерн делает агентский слой полезным. Агенту не нужен огромный ком YAML, JSON, логов и вывода сканеров. Ему нужны инструменты, которые могут задавать конкретные вопросы к реальным данным.

Вместо этого:

Here is a pile of kubectl output. Please figure out what matters.

Можно предоставить инструменты вроде:

list_vuln_reports(namespace, severity)
list_policy_violations(namespace, result)
list_compliance_reports(framework)
list_runtime_events(namespace, hours)

CRD дают нам общую поверхность безопасности. MCP-сервер превращает эту поверхность в типизированные инструменты. Агент использует эти инструменты для воспроизводимых расследований.

Вот в чём разница между тем, чтобы прикрутить чат-бот к кластеру, и тем, чтобы построить нечто действительно полезное.

MCP и навыки: слой запросов

CRD дают нам поверхность данных. MCP даёт агенту структурированный способ её запрашивать. Но что насчёт навыков (skills)?

Вместо того чтобы вставлять огромный блок вывода Kubernetes в промпт, агент может вызывать типизированные инструменты:

list_runtime_events(namespace, hours)
list_vuln_reports(namespace, severity)
list_policy_violations(namespace, result)
list_compliance_reports(framework)

Пример рабочего процесса:

User asks: Triage the latest high-priority alert.
Agent calls:
1. list_runtime_events()
2. list_vuln_reports()
3. list_policy_violations()
4. list_compliance_reports()
(skill synthesizes findings into a scored recommendation)

Вот в чём разница между тем, чтобы просить LLM угадывать из кучи YAML, и тем, чтобы дать ему структурированный путь расследования.

Навык /triage-threat может определять рабочий процесс:

Start with recent runtime alerts.
Identify the affected pod, workload, namespace, and image.
Pull vulnerability findings for the image.
Pull policy and posture findings for the workload.
Summarize the combined risk.
Recommend next investigation steps.

Это не автономное устранение проблем, но это воспроизводимая сортировка. Автономность появится позже.

Что это решает и что нет

Этот проект пока не пытается решить все проблемы безопасности Kubernetes в одной серии. Такой путь ведёт к безумию, расползанию области и, вероятно, к Helm-чарту с избыточным количеством значений.

Тем не менее он даёт нам полезную отправную точку.

Что мы получаем

A Kubernetes-native investigation surface
A way to correlate OSS security signals
A repeatable triage workflow
A path from findings to policy
A transparent alternative to black-box security consoles

Ключевое слово — прозрачность. Инструменты открыты. Находки доступны для запросов. MCP-слой явный. Навыки — это рабочие процессы, которые можно изучить и улучшить.

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

Чего у нас пока нет

A SIEM replacement
Autonomous remediation
Long-term event storage
Multi-cluster coverage
Full network visibility
Proof that every CVE is exploitable

Последний пункт важен.

CVE — это не то же самое, что эксплуатируемый риск. Находка в области конфигурации — это не то же самое, что активный взлом. Оповещение времени выполнения — это не то же самое, что подтверждённая вредоносная активность.

Ценность — в пересечении.

Первая версия этой консоли должна помогать выявлять такие пересечения, а не притворяться, что каждый сигнал совершенно самодостаточен.

Заключение: куда серия движется дальше

Этот материал — архитектурный обзор. Процесс живой, но следующие шаги уже вырисовываются.

Следующим шагом будет развёртывание первой версии стека, проверка того, что CRD заполняются, маршрутизация событий Falco в приёмник и начало разработки MCP-инструментов для запросов к этим данным.

Затем — переход к навыкам: сортировка оповещений времени выполнения, приоритизация рискованных рабочих нагрузок, превращение данных о конфигурации в политики Kyverno и тестирование границ применимости этого подхода.

Цель — не прикрутить ИИ к безопасности Kubernetes. Цель — сделать сигналы безопасности с открытым исходным кодом запрашиваемыми, коррелированными и достаточно полезными для реальной сортировки угроз.

© 2026 meganuke