Production и облако · Production and cloud · урок 1 · 13 мин
Docker и Kubernetes
Docker and 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?
2Почему container — не песочница для кода, написанного моделью, и что взять вместо?
3Liveness probe и readiness 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?
2Walk me through what happens, in Kubernetes terms, when a customer sends one message to our assistant.
3Our model server takes four minutes to load and keeps restarting. Which probe is wrong and how do you size it?
Ключевые фразы · Say it aloud
- An image is the package; a container is a running instanceобраз — пакет, container — запущенный экземпляр
- A container is hygiene, not a security boundarycontainer — гигиена, а не граница безопасности
- Kubernetes is a reconciliation loop: I declare the state, controllers fix the differenceописываю состояние, контроллеры исправляют разницу
- Readiness decides traffic, liveness decides restarts, startup protects slow loadingreadiness решает про трафик, liveness — про перезапуск, startup защищает долгую загрузку
- The weights stay out of the imageвеса не кладём в образ
- The guarantee lives in a NetworkPolicy, not in the promptгарантия живёт в сетевом правиле, а не в prompt
Материалы
- Kubernetes — Configure Liveness, Readiness and Startup Probes — три probe и пример 30 × 10 с (12 мин)
- Kubernetes — Deployments — ReplicaSet, rolling update, история ревизий и откат (15 мин)
- Kubernetes — Gateway API — GatewayClass, Gateway, HTTPRoute и почему это преемник Ingress (8 мин)
- Kubernetes — Network Policies — изоляция pods, default-deny, нужен сетевой плагин (10 мин)