- Deployment и ReplicaSet
- Зачем нужны ReplicaSet
- Масштабирование приложений
- Deployment: управление обновлениями
- Rolling Update: плавное обновление
- Откат обновлений
- Стратегии обновления
- Практический пример: веб-приложение с обновлениями
- Управление метками и селекторами
- Мониторинг и отладка
- Автомасштабирование
- Лучшие практики
- Заключение
Deployment и ReplicaSet
Работа с отдельными Pod в реальных приложениях недостаточна. Для надёжности нужно несколько копий приложения, автоматическое восстановление при сбоях и плавное обновление без простоя. ReplicaSet и Deployment — инструменты, которые обеспечивают эти возможности.
Зачем нужны ReplicaSet
Представьте, что вы запустили Pod с вашим приложением, и он внезапно упал из-за ошибки в коде или проблемы с узлом. Если вы работаете с отдельным Pod, приложение просто перестанет работать, пока вы не создадите новый Pod вручную. А если нужно обработать больше запросов? Придётся вручную создавать копии Pod и следить за их работой.
ReplicaSet решает эти проблемы. Это контроллер, который следит за количеством запущенных Pod и автоматически создаёт или удаляет их, чтобы поддерживать указанное количество реплик. Если Pod упал, ReplicaSet создаст новый. Если узел вышел из строя, Pod будут перезапущены на других узлах.
Давайте создадим простой ReplicaSet с тремя репликами Nginx:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: nginx-replicaset
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
В этом манифесте три ключевые секции. replicas: 3 указывает, что Kubernetes должен поддерживать три работающих Pod. Секция selector определяет, какие Pod принадлежат этому ReplicaSet — система будет искать Pod с меткой app: nginx. Секция template описывает, как должны выглядеть Pod — это тот же манифест, который вы использовали для создания отдельного Pod в предыдущем уроке.
Создайте ReplicaSet и посмотрите на результат:
kubectl apply -f nginx-replicaset.yaml
# Посмотреть ReplicaSet
kubectl get replicaset
# Посмотреть Pod
kubectl get pods
Вы увидите три Pod с автоматически сгенерированными именами вида nginx-replicaset-xxxxx. Попробуйте удалить один из них:
kubectl delete pod nginx-replicaset-xxxxx
kubectl get pods
Вы заметите, что Kubernetes сразу же создал новый Pod взамен удалённого. ReplicaSet непрерывно следит за количеством Pod и восстанавливает их при необходимости.
Масштабирование приложений
Одна из главных задач ReplicaSet — масштабирование приложений. Когда нагрузка увеличивается, вы можете быстро добавить больше реплик, а когда нагрузка спадает — уменьшить их количество.
Существует два способа масштабирования. Первый — изменить манифест и применить его заново. Второй — использовать команду kubectl scale, которая работает быстрее:
# Увеличить количество реплик до 5
kubectl scale replicaset nginx-replicaset --replicas=5
# Посмотреть изменения
kubectl get pods -w
Kubernetes немедленно создаст два новых Pod. Если уменьшить количество реплик, лишние Pod будут удалены:
# Уменьшить количество реплик до 2
kubectl scale replicaset nginx-replicaset --replicas=2
Важно понимать, что масштабирование в Kubernetes горизонтальное — вы добавляете больше копий приложения, а не увеличиваете ресурсы одного Pod. Это обеспечивает лучшую отказоустойчивость, так как при выходе из строя одного Pod остальные продолжают работать.
Deployment: управление обновлениями
ReplicaSet отлично справляется с поддержанием количества Pod, но у него есть проблема — обновление приложений. Если вы измените образ контейнера в манифесте ReplicaSet, существующие Pod не обновятся автоматически. Вам придётся удалять их вручную, чтобы ReplicaSet создал новые с обновлённым образом.
Deployment решает эту проблему. Это объект более высокого уровня, который управляет ReplicaSet и обеспечивает декларативные обновления. Когда вы обновляете Deployment, Kubernetes автоматически создаёт новый ReplicaSet с новой версией приложения и плавно переключает трафик, постепенно заменяя старые Pod новыми.
Вот как выглядит манифест Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
Обратите внимание — структура почти идентична ReplicaSet, изменилось только значение kind. Это не случайно: Deployment создаёт ReplicaSet внутри себя и управляет им.
Создайте Deployment и посмотрите на созданные объекты:
kubectl apply -f nginx-deployment.yaml
# Посмотреть Deployment
kubectl get deployments
# Посмотреть ReplicaSet (создан автоматически)
kubectl get replicaset
# Посмотреть Pod
kubectl get pods
Вы увидите, что Kubernetes создал Deployment, который создал ReplicaSet, который создал три Pod. Это многоуровневая архитектура, где каждый объект отвечает за свою задачу.
Rolling Update: плавное обновление
Главное преимущество Deployment — это механизм Rolling Update (последовательное обновление). Когда вы обновляете Deployment, Kubernetes не перезапускает все Pod одновременно. Вместо этого система постепенно заменяет старые Pod новыми, обеспечивая доступность приложения во время обновления.
Давайте обновим версию Nginx в нашем Deployment:
# Обновить образ
kubectl set image deployment/nginx-deployment nginx=nginx:1.22
# Посмотреть статус обновления
kubectl rollout status deployment/nginx-deployment
# Посмотреть историю обновлений
kubectl rollout history deployment/nginx-deployment
Kubernetes создаст новый ReplicaSet с образом nginx:1.22 и начнёт плавное обновление. По умолчанию он использует стратегию RollingUpdate: создаёт новый Pod, ждёт его готовности, удаляет старый Pod и повторяет процесс, пока все Pod не обновятся.
Вы можете контролировать скорость обновления с помощью параметров maxSurge и maxUnavailable:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # Максимум на сколько больше Pod можно создать
maxUnavailable: 1 # Максимум сколько Pod может быть недоступно
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
Параметр maxSurge: 1 означает, что во время обновления может быть максимум на один Pod больше, чем указано в replicas. Это позволяет Kubernetes создать новый Pod до удаления старого. Параметр maxUnavailable: 1 ограничивает количество недоступных Pod во время обновления — минимум два Pod из трёх будут работать в любой момент времени.
Откат обновлений
Иногда обновление приложения приводит к проблемам — новая версия содержит баг или несовместима с зависимостями. Deployment позволяет быстро откатиться к предыдущей версии:
# Откатиться к предыдущей версии
kubectl rollout undo deployment/nginx-deployment
# Откатиться к конкретной версии
kubectl rollout undo deployment/nginx-deployment --to-revision=1
# Посмотреть историю обновлений
kubectl rollout history deployment/nginx-deployment
Kubernetes хранит историю ReplicaSet, созданных Deployment, и может восстановить любую из них. По умолчанию хранятся 10 последних ревизий, но вы можете изменить это значение с помощью параметра revisionHistoryLimit в спецификации Deployment.
Стратегии обновления
Кроме RollingUpdate, Deployment поддерживает стратегию Recreate — полная замена всех Pod. При использовании этой стратегии Kubernetes сначала удаляет все старые Pod, а затем создаёт новые:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
strategy:
type: Recreate
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.22
ports:
- containerPort: 80
Стратегия Recreate подходит для случаев, когда одновременная работа двух версий приложения невозможна — например, при изменении схемы базы данных или использовании общих ресурсов, не поддерживающих параллельный доступ. Недостаток этой стратегии — полный простой приложения во время обновления.
Практический пример: веб-приложение с обновлениями
Давайте создадим более сложный пример с веб-приложением, которое использует переменные окружения и проверки готовности:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web-app
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
version: v1.0
spec:
containers:
- name: web-container
image: httpd:2.4
ports:
- containerPort: 80
env:
- name: VERSION
value: "1.0"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
В этом манифесте добавлена проверка готовности (readinessProbe), которая гарантирует, что новый Pod начнёт получать трафик только после успешного запуска. Это особенно важно при Rolling Update — Kubernetes не удалит старый Pod, пока новый не пройдёт проверку готовности.
Создайте Deployment и попробуйте обновить его:
# Создать Deployment
kubectl apply -f web-app-deployment.yaml
# Посмотреть статус
kubectl get deployments
kubectl get pods
# Обновить переменную окружения
kubectl set env deployment/web-app VERSION=2.0
# Следить за обновлением
kubectl rollout status deployment/web-app
Во время обновления вы увидите, как Kubernetes постепенно заменяет Pod, поддерживая доступность приложения. Благодаря maxUnavailable: 0 минимум три Pod всегда будут работать.
Управление метками и селекторами
Метки играют ключевую роль в работе Deployment и ReplicaSet. Selector определяет, какие Pod принадлежат Deployment, а метки в template присваиваются создаваемым Pod. Важно, чтобы метки в template совпадали с селектором, иначе Deployment не сможет управлять Pod.
Вы можете использовать сложные селекторы для фильтрации Pod:
selector:
matchLabels:
app: web-app
matchExpressions:
- key: version
operator: In
values:
- v1.0
- v1.1
Этот селектор выберет Pod с меткой app: web-app и меткой version, равной v1.0 или v1.1. Такие селекторы полезны при сложных схемах версионирования или canary-деплойментах.
Мониторинг и отладка
При работе с Deployment используйте команды мониторинга для отслеживания состояния:
# Посмотреть статус Deployment
kubectl get deployments
# Подробная информация
kubectl describe deployment nginx-deployment
# Посмотреть ReplicaSet
kubectl get replicaset
# Посмотреть события
kubectl get events --sort-by=.metadata.creationTimestamp
# Логи всех Pod в Deployment
kubectl logs -l app=nginx --tail=50
Команда kubectl describe deployment покажет подробную информацию о Deployment, включая стратегию обновления, количество реплик и события. Флаг -l в команде kubectl logs позволяет получить логи всех Pod с указанной меткой, что удобно при работе с несколькими репликами.
Автомасштабирование
Kubernetes поддерживает автоматическое масштабирование Pod на основе метрик, таких как загрузка CPU или памяти. Для этого используется объект HorizontalPodAutoscaler (HPA):
# Создать автомасштабирование
kubectl autoscale deployment nginx-deployment --min=3 --max=10 --cpu-percent=80
# Посмотреть статус автомасштабирования
kubectl get hpa
HPA будет автоматически изменять количество реплик в диапазоне от 3 до 10, поддерживая среднюю загрузку CPU на уровне 80%. Когда нагрузка увеличивается, HPA добавляет реплики, когда уменьшается — удаляет лишние.
Для работы HPA требуется metrics-server — компонент, который собирает метрики с узлов и Pod. В большинстве облачных кластеров он уже установлен, но в локальных кластерах может потребоваться установка:
# Проверить наличие metrics-server
kubectl get deployment metrics-server -n kube-system
Лучшие практики
При работе с Deployment и ReplicaSet следуйте рекомендациям, которые помогут избежать проблем в production. Всегда используйте Deployment вместо ReplicaSet напрямую — Deployment предоставляет больше возможностей для управления обновлениями и откатами.
Добавляйте проверки готовности и живучести в манифесты. readinessProbe гарантирует, что Pod начнёт получать трафик только после успешного запуска, а livenessProbe перезапустит контейнер, если приложение зависло.
Указывайте лимиты ресурсов для контейнеров. Это позволит Kubernetes правильно планировать размещение Pod и предотвратит ситуации, когда один Pod потребляет все ресурсы узла:
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
Используйте метки для организации приложений. Добавляйте метки с информацией о приложении, версии, окружении и команде разработчиков — это упростит мониторинг и отладку.
Храните манифесты в системе контроля версий. Это обеспечит историю изменений и возможность быстрого восстановления конфигурации. Используйте GitOps-подходы для автоматизации деплоймента из репозитория.
Заключение
ReplicaSet и Deployment — ключевые объекты для управления приложениями в Kubernetes. ReplicaSet обеспечивает поддержание нужного количества Pod и автоматическое восстановление при сбоях, а Deployment добавляет декларативные обновления и откат к предыдущим версиям.
Rolling Update позволяет обновлять приложения без простоя, постепенно заменяя старые Pod новыми. Автомасштабирование через HPA адаптирует количество реплик к текущей нагрузке. Вместе эти инструменты создают надёжную и масштабируемую платформу для запуска приложений.
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.