Прямой ответ
Kubernetes (K8s) — оркестратор контейнеров, и разработчику нужна не вся его глубина, а рабочая модель из пяти объектов. Pod — минимальная единица запуска (один-два контейнера с общей сетью; поды смертны и пересоздаются — «залезть в под по SSH и починить» антипаттерн: состояние живёт вне подов). Deployment — декларация «N реплик этого образа» (обновление образа — rolling-замена подов, откат одной командой — стратегии деплоя встроены). Service — стабильный сетевой адрес поверх changing-подов (DNS-имя + балансировка; виды: ClusterIP внутри кластера, LoadBalancer наружу). Ingress — маршрутизация HTTP снаружи по хостам/путям (аналог nginx-конфига — reverse proxy на уровне кластера). ConfigMap/Secret — конфигурация и секреты отдельно от образа (env-практика переносится дословно). Плюс обязательная дисциплина: пробы liveness/readiness (healthcheck-смысл тот же: readiness управляет трафиком, liveness — перезапуском зависшего), requests/limits ресурсов (без requests планировщик вслепую, без limits — сосед по ноде страдает), и kubectl как основной инструмент диагностики: get pods, describe, logs, exec. Локальная песочница для практики — k3s/minikube (ресурсы и выбор).
Deployment: как живёт и обновляется сервис
Манифест Deployment описывает шаблон пода (образ, env, пробы, ресурсы) и политику: replicas: 3, strategy: RollingUpdate (maxUnavailable/maxSurge — сколько подов можно заменить одновременно — ноль простоя при правильных readiness), revisionHistoryLimit для откатов. Жизненный цикл обновления: новый образ в шаблоне → Deployment создаёт новый ReplicaSet → поды поднимаются, проходят readiness, получают трафик, старые гасятся (SIGTERM → graceful shutdown приложения — обработка сигналов обязательна, иначе rolling рвёт запросы); kubectl rollout undo — мгновенный откат на предыдущий ReplicaSet. Что разработчик обязан обеспечить в образе/приложении: обработку SIGTERM, старт без локального состояния (сессии/файлы — наружу: Redis/хранилище — S3), логирование в stdout (journald/агрегаторы заменяются кластерными сборщиками), конфигурацию из env (12-factor — образ неизменяем, окружения различаются конфигом). Миграции БД — отдельной Job'ой до деплоя (не в старте приложения каждой реплики — гонка трёх реплик, мигрирующих одновременно).
Сеть: Service, Ingress, DNS
Внутри кластера: под обращается к сервису по DNS (— ClusterIP-сервис балансировает на поды; headless-сервис для stateful-порядка — ниша). Наружу: **Ingress** (HTTP-роутингapi.example.com/v1 → api-svc, TLS-терминация с cert-manager — [Let's Encrypt-автоматика](./letsencrypt-sertifikaty-avtoprodlenie.md) в кластерном формате) или LoadBalancer-сервис (TCP/не-HTTP); NetworkPolicy — файрвол внутри кластера (по умолчанию всё со всем связано — изоляция namespace'ов явная — [файрвол-мышление](./firewall-nftables-ufw-nastroyka-servera.md) переносится). Диагностика сети: kubectl execв под + curl/wget до сервиса (DNS резолвится? порт отвечает?),kubectl get endpoints` (сервис видит поды? пусто — селектор не совпадает с метками или readiness не проходит — половина «сервис не отвечает» в K8s именно про это).
Конфигурация, секреты, ресурсы
ConfigMap — нечувствительная конфигурация (env-переменные или файл-монтирование); Secret — чувствительная (base64 — не шифрование! etcd-шифрование и внешние хранилища — отдельная забота; для серьёзного — Vault-интеграция — секрет-менеджмент); изменение ConfigMap не рестартует поды автоматически (env зашит при старте — перезапуск rollout restart или reloader-контроллер — типовой грабель «поправил конфиг, не применилось»). Requests/limits: requests (CPU/память) — гарантия планировщику (по ним под размещается на ноде), limits — потолок (превышение памяти — OOMKill пода (137-й код — контейнерная диагностика применима); CPU-превышение — троттлинг, не убийство); старт — requests=limits для памяти (предсказуемость), CPU limits спорны (троттлинг на всплесках) — начать без CPU limit с мониторингом. Пробы: liveness /healthz (провал — рестарт пода; не должен зависеть от внешних сервисов, иначе каскад рестартов), readiness /ready (зависимости прогреты — трафик; провал — вывод из балансировки без рестарта), startupProbe для медленных стартов (JVM/миграции — liveness не прибьёт прогревающийся под).
Практический сценарий: сервис переезжает в кластер
Исходник: FastAPI на VPS под systemd/gunicorn (прод-запуск); цель — namespace в общем кластере. Шаги: (1) образ — multistage (сборка), non-root USER, тег по git-sha (не latest — rolling и откат rely на уникальности тега); (2) манифесты: Deployment (2 реплики, requests 250Mi/250m, probes на /healthz + /ready, SIGTERM-graceful в приложении уже был — проверка), Service ClusterIP, Ingress с TLS от cert-manager, ConfigMap с настройками, Secret из SOPS-пайплайна; (3) миграции — Job с alembic перед rollout (helm-hook или отдельный шаг CI — миграции); (4) проверка на стейдж-namespace: rollout status, logs обоих подов, exec + curl соседнего сервиса (DNS/сеть), намеренный краш пода (kubectl delete pod) — пересоздался за секунды, трафик не моргнул (readiness отработал); (5) прод-выкат: rolling с maxUnavailable=0, метрики (дашборд) без деградации — готово; откат отрепетирован на стейдже (rollout undo — 20 секунд). Итог: деплой из «ssh + git pull + restart» (5 минут с простоем) в CI-пайплайн kubectl apply (полторы минуты без простоя); локальная разработка не пострадала — docker-compose остаётся (dev-стек), кластер — только для среды, близкой к проду.
FAQ
Нужен ли Kubernetes маленькой команде с 2–3 сервисами? Часто нет: systemd+nginx на VPS или PaaS закрывают потребности без эксплуатации кластера (K8s — заметная статья эксплуатации: обновления, etcd, сеть, мониторинг самого кластера); K8s оправдан от десятка сервисов/команд, требований autoscaling и единой платформы — локальные эксперименты помогают оценить до миграции.
Pod постоянно перезапускается (CrashLoopBackOff) — чек-лист?
kubectl logs --previous (чем умер прошлый экземпляр — половина диагнозов здесь), kubectl describe pod (события: OOMKilled — лимит памяти мал/утечка; Liveness probe failed — проба строже приложения; ImagePullBackOff — образ/секреты реестра); порядок — причина в логах/событиях, не в «пересоздать namespace».
Как попасть в приложение для отладки?
kubectl exec -it pod -- sh (если shell есть в образе — distroless требует ephemeral container), kubectl port-forward svc/app 8080 — локальный доступ к сервису кластера для тестов, kubectl debug — ephemeral-контейнер с инструментами рядом с целевым; правки руками в поде — временная диагностика, не фикс (под пересоздастся — изменения исчезнут; фикс — в манифестах/образе).
StatefulSet — когда нужен? Для сервисов со стабильной идентичностью и хранилищем (БД, Kafka-брокеры — стабильные имена подов и persistent volumes по индексу); веб-приложения — всегда Deployment; «БД в кластере» — отдельное решение (операторы/managed-сервисы проще ручной эксплуатации — Postgres в K8s без оператора — боль).
Источники: документация Kubernetes (pods, services, debug) — ссылки в шапке.