Backend-разработчику не нужно администрировать Kubernetes — но нужно понимать среду, в которой живёт его сервис. Probes, ресурсы, graceful shutdown, «почему под перезапустился ночью» — всё это вопросы к разработчику, а не к платформенной команде. Эта статья — минимальная модель Kubernetes, достаточная, чтобы остальные статьи раздела (и инциденты на проде) читались осознанно.
Идея: желаемое состояние
Kubernetes — это цикл сверки (reconciliation loop): вы декларируете желаемое состояние («три реплики этого образа, столько-то памяти, наружу порт 8080»), кластер непрерывно сравнивает его с фактическим и устраняет расхождение. Под упал — будет создан новый. Нода умерла — поды переедут на живые. Вы описываете «что», Kubernetes решает «как» — в этом отличие от императивных скриптов деплоя «зайди по ssh и перезапусти».
Из этой идеи следует главное культурное правило: состояние кластера меняют правкой деклараций, не руками. kubectl edit на проде — то же самое, что hotfix правкой класса в работающем Tomcat.
Pod: единица исполнения
Pod — не «контейнер», а группа контейнеров с общей сетью и диском, неделимая единица планирования. В 90% случаев в поде один контейнер — ваше приложение; остальные 10% — sidecar-ы (прокси service mesh, агент логов).
Два свойства пода определяют всё остальное:
- Pod смертен и одноразов. Его не «лечат» — его убивают и создают новый. Никакого состояния внутри пода: файлы исчезнут, IP сменится. Всё долгоживущее — в БД, S3, внешних кешах.
- У пода есть IP, но полагаться на него нельзя — он живёт ровно столько, сколько под. Отсюда необходимость Service (ниже).
Deployment: реплики и обновления
Напрямую поды почти никогда не создают. Deployment декларирует «N реплик такого-то шаблона пода» и управляет их жизнью через ReplicaSet:
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 даёт три вещи: самовосстановление (упавшая реплика пересоздаётся), масштабирование (replicas: 5 — и через секунды их пять) и rolling update — смена образа порциями без остановки сервиса (механика — в статье про деплой).
Связующий механизм всего Kubernetes — labels и selectors: Deployment находит «свои» поды не по именам, а по меткам (app: order-service). Тот же принцип использует Service.
Service: стабильный адрес над смертными подами
Поды приходят и уходят, их IP меняются. Service — постоянное имя и виртуальный IP, за которым живёт актуальный список подходящих под selector подов (endpoints):
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector: { app: order-service }
ports:
- port: 80
targetPort: 8080
Теперь любой сервис кластера зовёт http://order-service (внутри namespace) — и попадает на одну из живых реплик. Балансировка примитивная (по соединениям), но для межсервисного HTTP её хватает. Важная деталь, которая свяжется с probes: под попадает в endpoints только когда его readiness probe зелёная — так Kubernetes не шлёт трафик на ещё не прогретое приложение.
Путь запроса снаружи
Полная цепочка, по которой пользовательский запрос доходит до вашего кода:
Internet → LoadBalancer → Ingress controller → Service → endpoints → Pod:8080
Ingress — декларация маршрутизации «host/path → такой-то Service» плюс TLS; исполняет её Ingress-контроллер (nginx, traefik). Подробно сеть разобрана отдельной статьёй — для начала достаточно держать в голове эту цепочку: при «сервис не отвечает» проверяется каждое её звено.
Namespace и kubectl
Namespace — папка для объектов: payments-prod, payments-staging. Изоляция административная (права, квоты), не сетевая (сетевую дают 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
Этого хватает для 80% задач; полный разбор отладки — в эксплуатации.
Чего Kubernetes не делает
- Не чинит приложение. Перезапуск CrashLoop-пода бесконечен, но причина — в вашем коде или конфиге.
- Не делает сервис отказоустойчивым сам по себе. Ретраи, таймауты, circuit breaker — по-прежнему ваша работа; k8s лишь заменяет упавшие реплики.
- Не управляет данными. БД в k8s — отдельная дисциплина (StatefulSet, операторы), и для большинства команд managed-БД вне кластера проще.
- Не отменяет понимание JVM. Память, GC и ресурсы контейнера взаимодействуют нетривиально — разбор.
Словарь объектов
| Объект | Что декларирует | Аналогия |
|---|---|---|
| Pod | Группа контейнеров, единица исполнения | Процесс |
| Deployment | N реплик пода + стратегия обновления | systemd-юнит с автоперезапуском, на N машин |
| Service | Стабильное имя над живыми подами | Внутренний балансировщик + DNS-запись |
| Ingress | Маршрутизация снаружи: host/path → Service | nginx-конфиг как объект кластера |
| ConfigMap / Secret | Конфигурация / секреты отдельно от образа | application.yml, вынесенный из jar |
| Namespace | Группа объектов с правами и квотами | Папка / проект |
| HPA | Авто-масштабирование по метрикам | «replicas: auto» |
Что почитать дальше
- Spring Boot в Kubernetes — probes, ресурсы и JVM, graceful shutdown: то, за что отвечает именно разработчик.
- Сеть и трафик — Service-типы, DNS, Ingress и Gateway API подробно.
- Деплой и конфигурация — манифесты, Helm, rolling update.
- Эксплуатация и отладка — kubectl-набор и типичные инциденты.