Шпаргалка
| Команда | Что делает |
|---|---|
kubectl apply -f файл.yaml | применить манифест: создать или обновить объект |
kubectl get pods | список подов и их статусы |
kubectl get deployments | список Deployment |
kubectl get services | список Service с их адресами |
kubectl logs имя-пода | логи контейнера в поде |
kubectl describe pod имя-пода | подробности и события пода |
kubectl delete pod имя-пода | удалить под (Deployment тут же поднимет новый) |
kubectl rollout status deployment/web | следить за выкатом новой версии |
kubectl port-forward service/web 8080:80 | прокинуть сервис на свой компьютер |
Pod, Deployment, Service – три слова, которые нужно запомнить
Из шага про архитектуру вы знаете, кто внутри кластера работает. Теперь разберем то, чем пользуются каждый день: три объекта, из которых собирается почти любое приложение в Kubernetes. Все трое описываются YAML-манифестами и применяются одной командой `kubectl apply`, как в скринкасте. Идем от самого мелкого к самому верхнему, чтобы каждый следующий объект опирался на предыдущий.
Начинается все с Pod
Сам под вам уже знаком, это обертка вокруг контейнера со своим IP. Вот как выглядит его манифест целиком:
apiVersion: v1
kind: Pod
metadata:
name: web
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80Структура у всех манифестов Kubernetes одинаковая, поэтому разберем ее один раз. `apiVersion` и `kind` говорят, что за объект описывается. `metadata` это имя объекта и лейблы (про них через минуту, они важнее, чем кажутся). `spec` это желаемое состояние, здесь один контейнер из образа nginx.27, слушающий порт 80.
Применяем и смотрим:
kubectl apply -f pod.yaml
kubectl get podsNAME READY STATUS RESTARTS AGE
web 1/1 Running 0 10sПод запущен. Заглянуть в его логи можно через `kubectl logs web`, а подробности и события через `kubectl describe pod web`.
И сразу правда жизни: вот так напрямую, руками, поды почти никогда не создают. Этот под одинок: если умрет узел, на котором он живет, пересоздавать его будет некому, ведь никто в кластере не обещал, что подов с именем web должно быть сколько-то. Подовый манифест мы разобрали потому, что он целиком ляжет внутрь следующего объекта.
Лейблы, на которых все держится
Строчка `labels: app: web` из манифеста это лейбл: произвольная пара ключ-значение, стикер на объекте. Сам по себе стикер не делает ничего. Но именно по стикерам объекты в Kubernetes находят друг друга: Deployment узнает свои поды, Service понимает, кому слать трафик. Механизм называется селектором и читается как «мне нужны все поды со стикером app: web». Запомните эту пару строк, она клей всего, о чем дальше пойдет речь.
Deployment следит за копиями
Формулировка из заголовка, «хочу 3 копии этого пода, и если один упадет, подними новый», это дословное описание Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80Три составные части. `replicas` это сколько копий держать. `selector` это каких подов считать своими, всех со стикером app: web. `template` это шаблон, по которому штамповать поды, и присмотритесь: внутри template лежит ровно тот подовый манифест из начала, с теми же контейнерами и лейблом. Deployment это количество, селектор и шаблон пода, и ничего больше.
Одна деталь устройства, которую полезно знать: напрямую подами Deployment не управляет. Он создает промежуточный объект ReplicaSet, и уже тот следит, чтобы число подов совпадало с `replicas`. В повседневной работе вы имеете дело с Deployment, а ReplicaSet делает свое дело тихо, но при выкате новой версии вы увидите его в выводе команд, и теперь понятно, откуда он берется.

Применяем:
kubectl apply -f deployment.yaml
kubectl get pods
NAME READY STATUS RESTARTS AGE
web-7c9f8d6b4-2xkq9 1/1 Running 0 15s
web-7c9f8d6b4-8jzwm 1/1 Running 0 15s
web-7c9f8d6b4-tg5rp 1/1 Running 0 15s
Имена со случайными хвостами выдают происхождение: поды отштампованы из шаблона, и их персональные имена никого не интересуют.
Теперь лучший пятиминутный аттракцион в Kubernetes, убить под и посмотреть, что будет:
kubectl delete pod web-7c9f8d6b4-2xkq9
kubectl get pods
NAME READY STATUS RESTARTS AGE
web-7c9f8d6b4-8jzwm 1/1 Running 0 2m
web-7c9f8d6b4-tg5rp 1/1 Running 0 2m
web-7c9f8d6b4-x4nd2 1/1 Running 0 4s
Подов снова три, у одного возраст четыре секунды. ReplicaSet под управлением Deployment заметил «заявлено три, вижу два» и пересоздал недостающий, тот самый self-healing из шага про архитектуру, теперь вызванный вашими руками.
Здесь же живет и rolling update из шага «Зачем Kubernetes»: поменяйте в манифесте образ на nginx.28, выполните apply, и Deployment по очереди заменит старые поды новыми. Следить за процессом можно командой `kubectl rollout status deployment/web`.
Service дает постоянный адрес
Свежеубитый под только что доказал тезис, который мы вводили ранее: поды смертны, и у нового пода новый IP. Обращаться к подам по адресам бессмысленно, нужен Service:
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 80Снова селектор, снова те же стикеры: Service направляет трафик всем живым подам с лейблом app: web, какими бы они ни были сегодня. `port` это на каком порту слушает сам Service, `targetPort` это на какой порт пода передавать.
kubectl apply -f service.yaml
kubectl get services
NAME TYPE CLUSTER-IP PORT(S)
web ClusterIP 10.96.45.12 80/TCP
У Service появился постоянный адрес, ClusterIP, который не изменится, сколько бы поды под ним ни пересоздавались. Больше того, внутри кластера к нему можно обращаться просто по имени: у Kubernetes есть свой DNS, и другое приложение в кластере пойдет на http://web, не зная вообще никаких IP.
Тип ClusterIP означает «адрес доступен внутри кластера». Чтобы заглянуть на сервис со своего компьютера во время экспериментов, есть удобный прием из скринкаста:
kubectl port-forward service/web 8080:80
После этого http://localhost:8080 на вашей машине ведет в кластер, на один из подов, и там встречает страница nginx. Полноценный вход трафика снаружи это Ingress, оставленный за рамками еще на прошлом шаге.
Как трое работают вместе
Deployment "web"
(replicas: 3, шаблон пода)
│ через ReplicaSet штампует и пересоздает
┌─────────────┼─────────────┐
[под] [под] [под] лейбл app: web
▲ ▲ ▲
└─────────────┼─────────────┘
│ селектор app: web
Service "web"
(постоянный адрес, балансировка)
▲
трафик к приложению
Роли распределены так: Pod это где работает контейнер, Deployment это сколько их должно быть и какими, Service это как до них добраться.

Связаны они не ссылками друг на друга, а лейблами: Deployment штампует поды со стикером, Service по тому же стикеру их находит. Эта тройка минимальный комплект практически любого приложения в Kubernetes, ведь объектов в кубере десятки, но эти три встречаются в каждом проекте без исключений, отсюда и заголовок.