Production и облако · Production and cloud · урок 1 · 13 мин

Docker и Kubernetes

Docker and Kubernetes

ТемыDocker и Kubernetes

Зачем

После урока ты объяснишь, чем image отличается от container, почему container не песочница для кода от модели, и проведёшь один запрос клиента через объекты Kubernetes с названием каждой настройки. Это базовый инфраструктурный раунд любого AI-интервью: «how would you run this agent in production?» — и словарь для всех следующих уроков модуля.

Docker: image и container

Проблема, которую решает Docker, звучит как «у меня работает»: программа зависит от версии ОС, библиотек и настроек, и при переезде ломается. Docker упаковывает приложение вместе со всем нужным в image (образ) — запечатанный снимок с версией. Запущенный image — это container: изолированный процесс со своей файловой системой и своим видом сети. Одна аналогия: image — рецепт и замороженное блюдо, container — порция, которую разогрели и едят.

Слова, которые спросят: - Dockerfile — рецепт сборки image. - Layers (слои) — image собирается слоями, неизменённые слои переиспользуются, поэтому пересборка быстрая. - Registry (хранилище образов) — откуда image скачивают на машину. - Volume — диск, который переживает замену container: база, индекс, cache весов. - Docker Compose — запуск нескольких containers из одного файла: агент, vector store, база.

Инженерное решение уже здесь: веса модели не кладут в image. Образ на 70 ГБ медленно скачивается и пересобирается при каждой правке кода, а веса меняются по своему графику. Их держат отдельно и подключают как volume или скачивают при старте (подробнее в a7-2).

Container — не песочница

Containers на одной машине делят одно ядро ОС (kernel). Ошибка в ядре или неудачная настройка — и процесс выходит за пределы container. Поэтому container — это гигиена и порядок, а не надёжная граница безопасности. Когда агент выполняет недоверенный код — например, код, который написала модель, — нужна изоляция сильнее: gVisor (ядро-посредник в пространстве пользователя), Firecracker microVM (маленькие виртуальные машины со своим ядром) или хотя бы container без сети и с файловой системой только для чтения. Ответ на интервью: «container for packaging, microVM for untrusted code».

Kubernetes: ты описываешь состояние, кластер его держит

Docker запускает containers на одной машине. Машина умерла — умерло всё, что на ней было. Kubernetes запускает containers на многих машинах (nodes, узлах) и держит их живыми.

Главная идея — declared state (объявленное состояние). Ты не говоришь «запусти container». Ты пишешь: «хочу три копии этого, по 2 ГБ памяти, доступные по такому имени». Контроллеры Kubernetes всё время сравнивают реальность с записью и исправляют разницу: перезапускают упавшее, переносят с мёртвого узла, постепенно меняют старую версию на новую. Это называется reconciliation loop (цикл сверки). Скрипт по таймеру, который раз в 5 минут поднимает пропавшие процессы, — ручная версия того же цикла; у Kubernetes таких контроллеров десятки, и они работают непрерывно.

Объект Что делает В агенте
Pod наименьшая единица запуска: один или несколько containers одна копия агента
Deployment держит N одинаковых pods и обновляет их постепенно agent-api, retriever
Service постоянное имя и адрес для меняющегося набора pods agent-api внутри кластера
Gateway API (раньше Ingress) вход снаружи: TLS, маршруты по host и path публичный адрес приложения
ConfigMap / Secret настройки и секреты для pods адреса tools, ключи
Namespace раздел кластера для команды или среды assistant-prod
NetworkPolicy кто с кем может говорить по сети агент видит только три адреса

Детали, которые отличают подготовленного кандидата (по документации kubernetes.io, открытой 08.10.2026). Deployment по умолчанию обновляет копии так, что недоступно не больше 25 % и лишних не больше 25 %, и хранит 10 старых ревизий для отката. Service типа ClusterIP виден только внутри кластера, LoadBalancer создаёт внешний балансировщик облака. Ingress API «заморожен»: не удалён, но не развивается, проект рекомендует Gateway API. Secret по умолчанию лежит в etcd (базе кластера) незашифрованным, а base64 — кодировка, не шифрование.

Requests и limits. Requests — сколько CPU и памяти scheduler (планировщик) резервирует при выборе узла. Limits — потолок: лишний CPU тормозится (throttling), лишняя память ведёт к OOM kill (убийство процесса за нехватку памяти).

Три probe — три разных вопроса

Probe (проверка) — запрос, которым kubelet (агент Kubernetes на узле) спрашивает container о состоянии. - Liveness: «процесс жив?» Нет — container перезапускают. - Readiness: «готов принимать трафик?» Нет — pod убирают из Service, но не перезапускают. - Startup: «запуск закончен?» Пока не прошла, две другие не работают. Бюджет = failureThreshold × periodSeconds; пример из документации — 30 × 10 с = 300 с.

Посчитаем для сервера модели. Веса 70 ГБ (35 млрд параметров × 2 байта в BF16), чтение с локального NVMe около 1 ГБ/с — 70 с только на веса, плюс прогрев GPU. Берём худший случай с запасом: periodSeconds: 10, failureThreshold: 60 → 600 с. Без startup probe liveness убьёт pod посреди загрузки, и он уйдёт в бесконечный цикл перезапусков (CrashLoopBackOff). Типовая ошибка на интервью — сказать «liveness проверяет, что модель загрузилась».

Один запрос через кластер

Клиент пишет в приложение. DNS ведёт на облачный балансировщик. Gateway снимает TLS, проверяет token доступа клиента и ограничивает частоту запросов. HTTPRoute (правило маршрута) отправляет запрос в Service agent-api, а Service — только в pods, у которых прошла readiness probe. Pod агента идёт в retriever, во внутренний API с tools и к модели.

Две гарантии живут в объектах, а не в prompt. NetworkPolicy: по умолчанию pod открыт во все стороны; правило default-deny на namespace плюс узкие разрешения оставляют агенту три адреса. Даже если prompt injection убедит модель «позвать» чужой URL, пакет туда не дойдёт. Оговорка из документации: без сетевого плагина, который исполняет политики, NetworkPolicy не действует. ServiceAccount и RBAC (role-based access control, права по ролям): у pod своя личность и только нужные права, он не читает чужие Secrets.

И последнее: каждый шаг пишет trace (след запроса) с request ID и версией выпуска. Когда ответ неверный, по нему находят шаг, который сломался (урок a7-7).

Схема

Термины · Key terms

image
запечатанный снимок приложения со всем нужным для запуска
container
запущенный image: изолированный процесс на общем ядре ОС
declared state
записанное желаемое состояние, которое кластер поддерживает сам
reconciliation loop
цикл сверки: контроллер приводит реальность к записи
pod
наименьшая единица запуска в Kubernetes
Deployment
объект, который держит N копий pod и обновляет их постепенно
Service
постоянное имя и адрес для набора pods
Gateway API
стандарт входа в кластер снаружи, преемник Ingress
liveness / readiness / startup probe
проверки «жив», «готов к трафику», «запуск закончен»
requests / limits
резерв ресурсов для планирования / жёсткий потолок
NetworkPolicy
правило, кто с кем может говорить по сети внутри кластера

Сделай сам

На бумаге нарисуй: Gateway → Service → три pod агента; у каждого pod подпиши readiness и startup probe с числами для модели, которая грузится до 4 минут. Затем запиши голосовое на 2 предложения: объясни «declared state» человеку без технического фона.

Обсуди с тьютором: покажи рисунок и свой бюджет startup probe; спроси, что случится, если поставить только liveness с initialDelaySeconds: 60.

Проверь себя · ответ под вопросом

1Чем image отличается от container?
Image — запечатанный снимок приложения с библиотеками и настройками, хранится в registry и имеет версию. Container — запущенный экземпляр image, изолированный процесс со своей файловой системой. Из одного image можно запустить много containers.
2Почему container — не песочница для кода, написанного моделью, и что взять вместо?
Containers делят ядро ОС с машиной, поэтому уязвимость ядра или ошибка настройки выпускает процесс наружу. Для недоверенного кода берут более сильную изоляцию: gVisor или Firecracker microVM. Минимум — container без сети и с файловой системой только для чтения.
3Liveness probe и readiness probe: в чём разница?
Liveness отвечает на вопрос «жив ли процесс» и при провале перезапускает container. Readiness отвечает «готов ли принимать трафик» и при провале только убирает pod из Service, без перезапуска. Для долгой загрузки модели нужна ещё startup probe, которая отключает обе до конца запуска.

Interview questions · US / UK

1What's the difference between an image and a container, and would you run model-generated code in a container?
Strong answer: image is the immutable, versioned package; container is a running instance; containers share the host kernel so they are hygiene, not a strong boundary; untrusted code goes to gVisor or Firecracker microVMs, or at minimum no network and a read-only filesystem.
2Walk me through what happens, in Kubernetes terms, when a customer sends one message to our assistant.
Strong answer: load balancer and Gateway terminate TLS and check auth; HTTPRoute to a Service; Service routes only to ready pods of a Deployment; pod has its own ServiceAccount and a default-deny NetworkPolicy that allows retriever, tool API and model; every hop writes a trace with request ID and release version.
3Our model server takes four minutes to load and keeps restarting. Which probe is wrong and how do you size it?
Strong answer: liveness is killing it mid-load; add a startup probe so liveness and readiness wait; budget failureThreshold × periodSeconds above the worst-case load, e.g. 60 × 10 s = 600 s; keep liveness short after startup so real hangs are caught; readiness controls traffic.

Ключевые фразы · Say it aloud

Материалы