// desktop only

Презентации лучше смотреть с десктопа

Слайды рассчитаны на широкий экран, клавиатуру и формат 16:9. Откройте эту страницу на ноутбуке или компьютере.

Вернуться на сайт
// proto · mcp · kubernetes · deckhouse

Как стартап на 500к
научил агента управлять Kubernetes

Эдгар Сипки//Founder EasyP && SIPKI Tech

// speaker.bio

Кто я и где мы

01

Эдгар Сипки

Senior golang developer, open-source. Founder EasyP.

02

Наш контекст

Маленький стартап. Мало денег, нет инфраструктурной команды.

// agenda

О чём поговорим?

  1. 01Агент и MCP за пять минут
  2. 02Стартап против инфраструктуры
  3. 03Deckhouse и первый MCP-сервер
  4. 04spec-first и protoc-gen-mcp
  5. 05deckhouse-harness изнутри
  6. 06Сценарии и живое демо
// chapter 01 / starting

О чём поговорим?

  • 01Агент и MCP за пять минут
  • 02Стартап против инфраструктуры
  • 03Deckhouse и первый MCP-сервер
  • 04spec-first и protoc-gen-mcp
  • 05deckhouse-harness изнутри
  • 06Сценарии и живое демо
// chapter 01

АГЕНТ
И MCP

// agent.intro

LLM умна, но безрука

  • Модель отлично рассуждает
  • Но сама по себе ничего не делает в реальном мире
  • → чтобы действовать, ей нужны руки
// agent.anatomy

Анатомия агента

LLM

рассуждает и принимает решения

Цикл

план → действие → наблюдение

Инструменты

руки во внешний мир

Контекст

что модель видит сейчас

// mcp.what

MCP = USB-C для интеграций

  • Один протокол вместо зоопарка кастомных коннекторов
  • Агент видит и вызывает внешние действия через один стандарт
  • MCP-сервер = руки агента
// mcp.primitives

Три примитива

Tools 🔧

действия

Resources 📄

чтение

Prompts 💬

шаблоны

// mcp.flow

Как агент выбирает tool

Agent (LLM)MCP Servertools/listсхема всех tools (JSON Schema)Выбор tool по description и JSON Schematools/callresult / isError
// mcp.transport

Два транспорта

stdio

  • агент запускает процесс локально
  • один клиент = один процесс
  • доступ - kubeconfig разработчика

SSE / HTTP

  • сервер живёт в кластере
  • много агентов одновременно
  • доступ - RBAC от ServiceAccount

один бинарь - оба транспорта: TRANSPORT=sse LISTEN_ADDR=:8080

// mcp.annotations

Аннотации: контракт безопасности

read_only_hint

только чтение - можно без подтверждения

destructive_hint

опасно - требует человека

idempotent_hint

повтор вызова безопасен

Клиент читает аннотации и понимает, где нужен человек.

// chapter 02 / problem

О чём поговорим?

  • 01Агент и MCP за пять минут
  • 02Стартап против инфраструктуры
  • 03Deckhouse и первый MCP-сервер
  • 04spec-first и protoc-gen-mcp
  • 05deckhouse-harness изнутри
  • 06Сценарии и живое демо
// chapter 02

СТАРТАП ПРОТИВ
ИНФРАСТРУКТУРЫ

// task

Задача

  • Продукту нужна настоящая инфраструктура: Kubernetes, деплои, TLS
  • В команде - только бэкенд-разработчики
  • DevOps-инженера нет и не будет
// requirements

Что нам реально нужно

  1. Поднять и держать кластер
  2. Добавлять ноды, когда не хватает ресурсов
  3. Выпускать сервисы наружу: Ingress + TLS
  4. Понимать, что сломалось, быстро
  5. Обновлять платформу без страха

И всё это - без выделенной команды.

// economics

Экономика вопроса

$93M

столько подняли стартапы вокруг AI-инфры

500к ₽

наш бюджет на всё

// the.bet

Ставка

Не нанимаем DevOps.
Отдаём управление инфраструктурой агенту.

'// attempt.01'

Попытка №1: готовый Kubernetes MCP

Agent<br>  │<br>  ▼<br>MCP (Kubernetes)   ← готовый сервер с kubectl-тулами<br>  │<br>  ▼<br>kube-apiserver
// why.fail

Почему не взлетело

  • Сырой kubectl-уровень: агент тонет в низкоуровневых объектах
  • Нет модели нашего домена: «добавь ноду» ≠ 20 kubectl-команд
  • Опасные операции без ограничений и без аннотаций
  • → нужен доменный MCP-сервер, а не обёртка над kubectl
// chapter 03 / deckhouse

О чём поговорим?

  • 01Агент и MCP за пять минут
  • 02Стартап против инфраструктуры
  • 03Deckhouse и первый MCP-сервер
  • 04spec-first и protoc-gen-mcp
  • 05deckhouse-harness изнутри
  • 06Сценарии и живое демо
// chapter 03

DECKHOUSE И ПЕРВЫЙ
MCP-СЕРВЕР

// deckhouse.what

Что такое Deckhouse

  • Kubernetes-платформа: кластер + модули «из коробки»
  • Мониторинг, ingress, cert-manager, автообновления - уже внутри
  • Вся платформа управляется декларативно через CRD
'// deckhouse.crd'

CRD: декларативный интерфейс платформы

apiVersion: deckhouse.io/v1<br>kind: NodeGroup<br>metadata:<br>  name: worker<br>spec:<br>  nodeType: Static<br>  staticInstances:<br>    count: 3<br>    labelSelector:<br>      matchLabels:<br>        role: worker
// deckhouse.verdict

Вердикт

🙂

Для человека: платформа закрывает 90% рутины

🤖

Для агента: интерфейса нет - только kubectl и документация

// deckhouse.idea

Идея

Пишем свой MCP-сервер над Deckhouse:
доменные тулы вместо сырого kubectl.

// build.start

Начали писать руками

  • Каждый tool: схема + валидация + хендлер + описание
  • Первые 5 тулов - нормально
  • Дальше - копипаста и расхождение схем
// build.problem

Проблема масштаба

  • Нужны десятки тулов: ноды, модули, релизы, конфиги, диагностика
  • JSON Schema руками = ошибки в каждой второй
  • Схема, код и описание живут отдельно и расходятся
// build.symptom

Симптом

Агент вызывает tool с параметрами, которых нет в схеме.
Схема говорит одно, код делает другое.

// build.diagnosis

Диагноз

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

// chapter 04 / spec-first

О чём поговорим?

  • 01Агент и MCP за пять минут
  • 02Стартап против инфраструктуры
  • 03Deckhouse и первый MCP-сервер
  • 04spec-first и protoc-gen-mcp
  • 05deckhouse-harness изнутри
  • 06Сценарии и живое демо
// chapter 04

SPEC-FIRST И
PROTOC-GEN-MCP

// spec.search

Нужен источник правды

  • Одна спецификация → схема, код и описания генерируются
  • Руками пишем только бизнес-логику хендлеров
  • → подход называется spec-first
// spec.candidates

OpenAPI vs Protobuf

// protobuf
  • Строгая типизация и компактный синтаксис
  • Экосистема плагинов protoc
  • Уже используем в продукте (EasyP!)
// openapi
  • Многословный YAML/JSON
  • Слабая связь со структурами кода
  • Генерация клиентов ≠ генерация MCP-серверов
// spec.solution

Решение

Берём proto как единственный источник правды
и пишем свой генератор: protoc-gen-mcp.

// the.meta-thesis

Агент ужасно проектирует,
но неплохо кодит

// protoc-gen-mcp.idea

Идея protoc-gen-mcp

  • proto-сервис → набор MCP-тулов
  • rpc → tool, message → JSON Schema, комментарий → description
  • Опции метода → аннотации безопасности
'// options.proto'

rpc + опции = tool с аннотациями

service DiagnosticsAPI {<br>  // Статус кластера: ноды, модули, алерты.<br>  rpc GetClusterStatus(GetClusterStatusRequest)<br>      returns (GetClusterStatusResponse) {<br>    option (mcp.options.v1.method) = {<br>      read_only_hint: true<br>    };<br>  }<br>}
'// generator.pipeline'

Пайплайн: от proto до сервера

.proto (источник правды)<br>  │  easyp generate / buf generate<br>  ▼<br>protoc-gen-mcp<br>  ├─▶ JSON Schema для каждого tool<br>  ├─▶ интерфейсы хендлеров<br>  ├─▶ регистрация тулов + аннотации<br>  └─▶ валидация входа из constraints<br>  │<br>  ▼<br>ваш код: только бизнес-логика хендлеров
'// options.constraints'

Constraints: валидация из спецификации

message AddWorkerNodeRequest {<br>  string name = 1 [(mcp.options.v1.field) = {<br>    string: { min_len: 1, max_len: 63,<br>              pattern: "^[a-z0-9-]+$" }<br>  }];<br>  int32 cpu = 2 [(mcp.options.v1.field) = {<br>    int32: { gte: 1, lte: 64 }<br>  }];<br>}
// why.it.works

Почему это работает

  • Схема и код не могут разойтись - они из одного файла
  • Комментарий в proto = description для агента
  • Новый tool = новый rpc + один хендлер
  • Ревью спецификации вместо ревью бойлерплейта
// protojson.pain

Где болело: zero values

  • В protojson «поле не передано» и «передан ноль» выглядят одинаково
  • Агент пропускает поле → сервер видит 0 → логика ломается
  • Решение: UNSET-sentinel в рантайме - явно различаем «нет значения» и «ноль»
// polyglot

Один proto - пять языков

ЯзыкSDKОсобенность
Gomcp-goпервый, самый зрелый
Pythonofficial MCP SDKdataclass- или protobuf-хендлеры
Kotlinkotlin-sdk-serverJVM-мир
Javamcp java sdkэнтерпрайз
TypeScript@modelcontextprotocol/sdkProtobuf-ES + Ajv
// changelog

Эволюция за полгода

v0.1
Go MVP: rpc → tool, JSON Schema, stdio
v0.2
типизированные опции mcp/options/v1: constraints + аннотации
v0.3
rename в protoc-gen-mcp + Agent Skill для агентов
v0.4
Python: official SDK, dataclass-хендлеры, UNSET
v0.5
Kotlin, Java, TypeScript - пять языков из одного proto
// meta

Мета-уровень

Агент сам умеет пользоваться генератором:
агент пишет proto → генерирует себе руки

npx skills add easyp-tech/protoc-gen-mcp-skill
'// deckhouse-harness / handler'

Руками - только бизнес-логика

// Сгенерировано protoc-gen-mcp. Не редактировать.<br>type DiagnosticsAPIToolHandler interface {<br>	GetClusterStatus(<br>		ctx context.Context,<br>		req *deckhousev1.GetClusterStatusRequest,<br>	) (*deckhousev1.GetClusterStatusResponse, error)<br><br>	ListUnhealthyPods(<br>		ctx context.Context,<br>		req *deckhousev1.ListUnhealthyPodsRequest,<br>	) (*deckhousev1.ListUnhealthyPodsResponse, error)<br>}
'// easyp.yaml'

Генерация одной командой

generate:<br>  plugins:<br>    - name: go<br>      out: gen<br>    - name: mcp<br>      out: gen<br>      opts:<br>        lang: go
'// main.go'

Сборка сервера

srv := mcpruntime.NewServer("deckhouse-harness")<br><br>deckhousev1.RegisterDiagnosticsAPITools(<br>	srv, diagnosticsHandler,<br>)<br>deckhousev1.RegisterNodesAPITools(<br>	srv, nodesHandler,<br>)<br><br>if transport == "sse" {<br>	return srv.ServeSSE(ctx, listenAddr)<br>}<br>return srv.ServeStdio(ctx)
// chapter 05 / harness

О чём поговорим?

  • 01Агент и MCP за пять минут
  • 02Стартап против инфраструктуры
  • 03Deckhouse и первый MCP-сервер
  • 04spec-first и protoc-gen-mcp
  • 05deckhouse-harness изнутри
  • 06Сценарии и живое демо
// chapter 05

DECKHOUSE-HARNESS
ИЗНУТРИ

// harness.map

43 тула, 6 доменов

diagnostics
11

все read-only

nodes
13

самый опасный домен

modules
7

вкл/выкл модулей

sources
6

источники модулей

releases
3

обновления платформы

config
3

ModuleConfig

Каждый домен = отдельный proto-сервис в proto/deckhouse/v1/

// harness.composite

Тул ≠ один API-вызов

AddWorkerNode

  • создать SSHCredentials
  • создать StaticInstance
  • ждать bootstrap ноды

DrainNode

  • cordon ноды
  • eviction подов с уважением PDB
  • отчёт о том, что не выселилось

Один вызов агента = целый сценарий внутри хендлера

'// harness.transport'

Один бинарь - два режима

# локально: stdio + kubeconfig разработчика<br>./deckhouse-harness<br><br># в кластере: Pod в d8-system, in-cluster auth<br>TRANSPORT=sse LISTEN_ADDR=:8080 ./deckhouse-harness
// harness.safety

Границы доверия

  • Аннотации: read-only тулы агент зовёт свободно
  • destructive-тулы - только с подтверждением человека
  • RBAC: ServiceAccount ограничен тем, что реально нужно
  • даже сломавшийся агент не сделает больше, чем разрешено
// war.story

Боевая история: одна буква

deckhouserelease → deckhousereleases
  • Опечатка в GVR: resource в единственном числе
  • 133 unit-теста с моками - все зелёные 🟢
  • Поймали только интеграционные тесты на живом кластере
  • моки врут, кластер - нет
// harness.testing

Как тестировать руки агента

133+

unit-тестов: логика хендлеров

58

интеграционных: Kind + Deckhouse CE, оба транспорта

Интеграционные тесты гоняют реальные MCP-вызовы через оба транспорта.

// chapter 06 / scenarios

О чём поговорим?

  • 01Агент и MCP за пять минут
  • 02Стартап против инфраструктуры
  • 03Deckhouse и первый MCP-сервер
  • 04spec-first и protoc-gen-mcp
  • 05deckhouse-harness изнутри
  • 06Сценарии и живое демо
// chapter 06

СЦЕНАРИИ И
ЖИВОЕ ДЕМО

// scenario.a / diagnostics

Сценарий A: диагностика

Разработчик 🧑Агент 🤖Deckhouse API ☸️«почему прод тормозит?»GetClusterStatusunhealthy: 2 podsListUnhealthyPodsCrashLoopBackOff + причиныдиагноз + план действий
// scenario.b / provisioning

Сценарий B: новая нода

Агент 🤖harnessDeckhouse API ☸️Cloud VM ☁️AddWorkerNodeCreate VMSSHCredentials + StaticInstanceSSH BootstrapNode Readyнода в кластере ✅
// scenario.c / https

Сценарий C: HTTPS за один вызов

Агент 🤖harnessCertManager 🔒Let's Encrypt ✍️CreateIngressWithTLSIngress + CertificateACME challengeсертификатTLS Readyhttps://домен готов ✅
// scenario.d / incident

Сценарий D: разбор инцидента

DeveloperAgent (LLM)Deckhouse API"Why is app crashing?"GetClusterStatus2 unhealthy podsGetPodLogsOOMKilled, exit 137GetNodeEvents"memory limit 256Mi → 512Mi"

Вся цепочка - read-only тулы: агент расследует без риска, решение принимает человек.

// live.demo

ЖИВОЕ ДЕМО

// demo.discussion

Что мы только что видели

// агент справился
  • Диагностика без единой команды kubectl
  • Сложные операции одним вызовом
  • Объясняет, что и зачем делает
// по-прежнему человек
  • Подтверждает destructive-операции
  • Ставит границы через RBAC
  • Отвечает за прод головой
// summary

Шесть тезисов

  1. Агенту нужны доменные руки, а не сырой kubectl
  2. Руки руками не масштабируются - нужен источник правды
  3. proto + protoc-gen-mcp: схема, код и описания из одного файла
  4. Агент ужасно проектирует, но неплохо кодит
  5. Один proto - пять языков MCP-серверов
  6. Доверие агенту = аннотации + RBAC + интеграционные тесты
// when

Когда это вам подойдёт

// берите
  • Маленькая команда без выделенного DevOps
  • Уже есть proto или готовы его завести
  • Операции типовые и описуемые
// не спешите
  • Жёсткий комплаенс и аудит каждого действия
  • Нет интеграционных тестов - сначала они
  • Одноразовые уникальные операции
// roadmap

ЧТО ДАЛЬШЕ

// roadmap

Планы

now
protoc-gen-mcp v0.5: Go, Python, Kotlin, Java, TypeScript
next
deckhouse-harness: больше доменов, больше композитных сценариев
later
Resources и Prompts из proto, мультикластерный режим
// outcome

Итог в цифрах

43 тула · 6 proto-сервисов
133+58 тестов · 5 языков
0 нанятых DevOps

// links

Попробуйте сами

Эдгар Сипки//Спасибо!