Раньше сервис деплоили так: написали скрипт, зашли по ssh, остановили процесс, скопировали новый jar, запустили снова. Если нода упала — всё, сервис лежит, кто-то идёт чинить руками. Если нужно пять копий — пять раз делаешь одно и то же.
Kubernetes решает эту проблему иначе: вы описываете, что должно работать, а кластер сам решает как — и поддерживает это состояние непрерывно.
Главная идея: желаемое состояние
Kubernetes работает как постоянный наблюдатель. Вы говорите ему: «хочу три копии этого сервиса, каждой нужно 512 МБ памяти, наружу смотрит порт 8080». Kubernetes сравнивает это с тем, что есть на самом деле, и устраняет расхождения.
Упала одна копия — Kubernetes создаёт новую. Умерла целая нода — поды переезжают на живые машины. Вы ничего не делаете руками: кластер сам поддерживает нужную картину.
Из этого следует важное правило: состояние кластера меняют правкой деклараций, не ручными командами. Зайти и что-то поправить «по-быстрому» — это то же самое, что менять файл на работающем сервере в обход системы контроля версий.
Pod: один процесс (или несколько рядом)
Pod — это наименьшая единица в Kubernetes. В большинстве случаев под — это один контейнер с вашим приложением.
Два свойства пода важно понять с самого начала:
Под одноразовый. Его не лечат — его убивают и создают новый. Если приложение упало, Kubernetes не пытается его починить: он просто запускает свежий контейнер из образа. Из этого следует: никакого важного состояния внутри пода быть не должно. Файлы на диске исчезнут. IP-адрес сменится.
IP пода непостоянен. Пока под жив — у него есть адрес. Когда под пересоздаётся — адрес другой. Полагаться на него нельзя. Для постоянного адреса существует Service — об этом ниже.
Иногда в поде несколько контейнеров: например, ваше приложение плюс агент сбора логов. Они делят одну сеть и один диск. Это называется sidecar-паттерн, но новичку это редко нужно — в 90% случаев под = один контейнер.
Deployment: кто управляет подами
Поды вручную почти никогда не создают. Deployment — это декларация: «запусти N копий вот такого пода и поддерживай их в рабочем состоянии».
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
replicas: 3
selector:
matchLabels: { app: order-service }
template:
metadata:
labels: { app: order-service }
spec:
containers:
- name: app
image: registry.local/order-service:1.42.0
ports:
- containerPort: 8080
resources:
requests: { cpu: "500m", memory: "768Mi" }
limits: { memory: "768Mi" }
Deployment даёт три вещи:
- Самовосстановление — упала реплика, Kubernetes создаёт новую.
- Масштабирование — поменяли
replicas: 3наreplicas: 5, через несколько секунд их пять. - Обновление без остановки — при смене образа Deployment заменяет поды порциями, не роняя сервис целиком.
Как Deployment находит свои поды? Не по именам — по меткам (labels). В примере выше все поды имеют метку app: order-service, а Deployment ищет именно их через selector.matchLabels. Этот же механизм используется в Service.
Service: постоянный адрес над сменяющимися подами
Поды приходят и уходят, их адреса меняются. Service — это стабильное имя и виртуальный IP, который всегда указывает на живые поды:
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector: { app: order-service }
ports:
- port: 80
targetPort: 8080
Теперь любой другой сервис в кластере обращается по имени http://order-service — и Kubernetes направит запрос на один из живых подов с меткой app: order-service.
Важная деталь: под попадает в список доступных адресов только тогда, когда его readiness probe возвращает успех. Если приложение ещё не прогрелось или временно недоступно — трафик на него не идёт. Как настроить probe — в следующей статье.
Как запрос из интернета добирается до пода
Полная цепочка выглядит так:
Интернет → LoadBalancer → Ingress-контроллер → Service → Pod
Ingress — это декларация маршрутизации: «запросы на api.example.com/orders отправляй в Service order-service». Плюс там же настраивается TLS. Выполняет эту декларацию Ingress-контроллер (например, nginx или traefik) — он уже реально слушает входящие запросы.
Когда что-то не работает, эту цепочку проверяют звено за звеном: LoadBalancer поднят? Ingress сконфигурирован правильно? Service видит поды? Поды отвечают на probe?
Namespace: разделяем окружения
Namespace — это папка для объектов кластера. Обычно делают отдельные namespace для каждого окружения: payments-prod, payments-staging.
Изоляция в namespace административная: права доступа, квоты на ресурсы. Сетевой изоляции namespace не даёт — сервисы из разных namespace могут общаться, если явно не запрещено через NetworkPolicy.
Минимальный набор команд
Большинство задач разработчика покрывают четыре команды:
kubectl -n payments-prod get pods
kubectl -n payments-prod describe pod order-service-7d4b9c-x2x4v
kubectl -n payments-prod logs deploy/order-service --tail=200
kubectl -n payments-prod port-forward svc/order-service 8080:80
Первая — посмотреть, что запущено. Вторая — разобраться, почему под не стартует или лежит. Третья — прочитать логи. Четвёртая — временно пробросить порт к себе, чтобы проверить работу сервиса локально.
Что Kubernetes не делает за вас
Kubernetes заменяет упавшие поды — но не чинит код внутри. Если приложение падает из-за бага, Kubernetes будет бесконечно перезапускать под (это называется CrashLoopBackOff) — но причину надо искать в логах и фиксить самостоятельно.
Kubernetes не делает сервис отказоустойчивым сам по себе. Повторные попытки, таймауты, автоматическое отключение неработающего соседа — это по-прежнему задача разработчика. Kubernetes лишь следит, чтобы нужное количество подов было живо.
База данных в Kubernetes — отдельная, сложная тема (StatefulSet, операторы). Большинству команд проще держать управляемую БД вне кластера.
Шпаргалка по объектам
| Объект | Что делает |
|---|---|
| Pod | Запускает один или несколько контейнеров вместе |
| Deployment | Следит, чтобы нужное число подов всегда работало |
| Service | Постоянное имя и адрес над меняющимися подами |
| Ingress | Маршрутизация внешнего трафика к нужному Service |
| ConfigMap / Secret | Конфигурация и секреты отдельно от образа |
| Namespace | Группа объектов с правами и квотами |
Коротко
- Kubernetes поддерживает желаемое состояние: вы декларируете, он выполняет и восстанавливает при сбоях.
- Pod — одноразовая единица. Его не лечат, а пересоздают. Никакого важного состояния внутри.
- Deployment управляет N копиями пода, даёт самовосстановление, масштабирование и обновление без остановки.
- Labels — механизм связи: Deployment находит свои поды по меткам, Service — тоже.
- Service — постоянный адрес над живыми подами. Трафик идёт только на поды с зелёной readiness probe.
- Ingress маршрутизирует внешний трафик к нужному Service.
- Namespace разделяет окружения административно, не сетево.
- Kubernetes заменяет упавшие поды, но не чинит код и не делает сервис отказоустойчивым сам по себе.
Что почитать дальше
- Spring Boot в Kubernetes — probes, ресурсы и graceful shutdown: то, за что отвечает разработчик.
- Сеть и трафик — типы Service, DNS, Ingress и Gateway API подробно.
- Деплой и конфигурация — манифесты, Helm, rolling update.
- Эксплуатация и отладка — kubectl и типичные инциденты.