1. Введение
Контейнеризация и оркестрация контейнеров стали стандартами в современных распределенных системах. Kubernetes, в качестве лидера в этой области, предоставляет широкий спектр возможностей для управления, развертывания и масштабирования контейнеризованных приложений.
Цель – детально исследовать один из ключевых компонентов Kubernetes – объект Deployment. Объект Deployment предназначен для декларативного обновления и масштабирования приложений, а также для поддержания здоровья приложения и обновлений.
С применением Deployment, разработчики и системные администраторы получают возможность обновлять приложения без простоя, останавливая старые Pod'ы и создавая новые в автоматизированном и контролируемом процессе. Исследование также посвящено изучению различных стратегий обновления, предлагаемых Kubernetes, и определению ситуаций, в которых каждая из них является наиболее подходящей.
Такое понимание и умение применять Deployment в Kubernetes является ключевым для успешного и эффективного управления приложениями в производственной среде.
2. Объект Deployment в Kubernetes: Обзор и основные принципы работы
Объект Deployment в Kubernetes представляет собой ресурс, который управляет процессом развертывания и обновления приложений, делая этот процесс более предсказуемым и контролируемым. Deployment координирует создание и модификацию ReplicaSets, подмножеств Pod'ов, которые обеспечивают отказоустойчивость и масштабируемость приложения.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
Containers:
- name: nginx
image: nginx:1.14.2
Рис.
Описание Deployment включает в себя спецификации, такие как селекторы меток, количество реплик и шаблоны для создания Pod'ов. Это позволяет определить, какие Pod'ы должны быть созданы и как они должны функционировать в рамках приложения. Логическая структура объектов показана на рисунке.
Также рассматривается процесс создания Deployment, включая использование параметра --record, который добавляет историю изменений Deployment, что упрощает процесс отслеживания и управления версиями приложения.
Важным аспектом работы с Deployment является понимание статуса развертывания, а также способов просмотра и анализа этого статуса. Изучаются различные команды kubectl, которые позволяют пользователям получить информацию о состоянии Deployment, включая просмотр текущих Deployment'ов и их статуса, а также просмотр истории развертывания.
3. Анализ стратегий обновления приложений в контексте объекта Deployment
Предположим, что у нас есть приложение версии 1.0. мы обновляем версию приложения до 2.0, собираем докер образ и загружаем этот образ в докер регистри. Теперь нам нужно обновить все поды нашего приложения в кластере, чтобы они использовали образ 2.0. Т.к. мы не можем изменить образ текущего пода после его создания, нам нужно удалить все старые поды приложения и запустить новые.
Тут у нас есть 3 способа:
- Сначала удалить все существующие поды, а затем запустить новые
- Запустить новые и, как только они запустятся, удалить старые.
- Или действовать поэтапно: если у нас несколько реплик одного пода, то можно добавлять по одному новому и удалять по одному старому.
В первом случае будет даунтайм, т.к. пройдет некоторое время между включением старых подов и запуском новых. В случаях 2 и 3 будут какое-то время запущены 2 версии приложения, что в некоторых случаях может иметь негативные последствия. Например, потому что вторая версия может накатывать миграции в базу данных, которые несовместимы с первой версией.
Здесь логично будет использовать ReplicaSet. В статье “Репликация и автоматическое масштабирование в Kubernetes с помощью объекта ReplicaSet” подробно рассмотрено применение этого объекта.
Рассмотрим сценарий, в котором наше приложение, изначально имеющее версию 1.0, подвергается обновлению до версии 2.0. В этом контексте процесс обновления включает в себя составление Docker образа и последующую его загрузку в Docker регистри. В конечном итоге, цель состоит в обновлении всех подов приложения в кластере, так чтобы они использовали образ версии 2.0. В силу непеременности образа пода после его создания, обновление подов требует удаления всех существующих подов и запуска новых.
В данном контексте мы можем выделить три стратегии обновления подов:
- Удалить все существующие поды, а затем запустить новые.
- Запустить новые поды и, по их активации, удалить существующие.
- Реализовать поэтапное обновление: при наличии нескольких реплик одного пода, можно последовательно добавлять новые поды и удалять старые.
Первая стратегия неизбежно приводит к временному простою (даунтайм), поскольку процесс переключения между старыми и новыми подами требует времени. Вторая и третья стратегии подразумевают параллельное функционирование двух версий приложения в течение определенного промежутка времени, что может иметь отрицательные последствия в определенных условиях. В частности, если вторая версия приложения включает в себя миграции в базу данных, несовместимые с первой версией.
В этой ситуации возможно применение объекта ReplicaSet, вопросы использования которого подробно изложены в статье "Репликация и автоматическое масштабирование в Kubernetes с помощью объекта ReplicaSet".
Пример спецификации:
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: app
spec:
replicas: 3
selector:
matchLabels:
app: app
template:
metadata:
labels:
app: app
spec:
containers:
- name: app
image: app:v1.0
В представленной выше спецификации ReplicaSet видно, что имеется шаблон пода с названием 'app' и Docker образом 'app:v1.0'. Для обновления подов до новой версии можно вручную изменить образ на 'v2.0'. Однако, уже функционирующие поды ReplicaSet модифицировать не будет, а новый шаблон применяется исключительно к новым подам. В данной ситуации остается одна возможность: идентифицировать поды со старой версией и последовательно их удалять.
В этом случае ReplicaSet (RS) будет генерировать новые поды на основе нового шаблона с новой версией. Альтернативно, если приложение не поддерживает совместную работу двух версий, можно удалить все старые поды и дождаться создания новых. Однако, этот подход приводит к временному простою. Более гибким решением является создание нового RS с новым шаблоном пода, позволяя динамически регулировать значение параметра 'replicas' в новом и старом RS. Несмотря на свою эффективность, данная стратегия требует значительных ручных вмешательств.
Решение данной проблематики предлагает объект Deployment – конструкция, предназначенная для декларативного развертывания и обновления приложений, что является альтернативой прямому взаимодействию с ReplicaSet. Deployment является объектом, координирующим создание и модификацию двух объектов ReplicaSet в процессе обновления приложения.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
Базовое описание Deployment очень похоже на описание ReplicaSet. Оно также состоит из селектора лейблов, количества реплик и шаблона будущего пода.
Создадим Deployment используя описание из примера спецификации выше.
#kubectl create -f deployment.yaml
Посмотреть существующие Deployment в кластере можно с помощью команды kubectl get deployment:
#kubectl get deployments.apps
NAME app-deployment |
READY 3/3 |
UP-TO-DATE 3 |
AVAILABLE 3 |
AGE 8h |
Цифры 3/3 означают что работают все 3 реплики, которые были указаны в спецификации деплоймента.
У kubectl также есть команда rollout, с помощью которой можно посмотреть статус деплоя:
#kubectl rollout status deployment nginx-deployment
Deployment “nginx-deployment” successfully rolled out
Если Deployment создает RS, их можно посмотреть:
#kubectl get replicaset
NAME Nginx-deployment-66b6c48dd5 |
DESIRED 3 |
CURRENT 3 |
READY 3 |
AGE 7m34s |
Возникает вопрос: почему в списке представлен только один ReplicaSet? Ответ кроется в том, что приложение пока не прошло обновление, и данный ReplicaSet необходим для запуска наших подов.
Обратите внимание, что имя нашего ReplicaSet состоит из имени Deployment и некоторого числового значения. Данное число представляет собой хэш-значение шаблона пода в описании Deployment. Такой подход осознанно применяется, поскольку использование хэша шаблона позволяет объекту Deployment использовать тот же самый ReplicaSet, если шаблон пода и соответственно его хэш остаются неизменными.
Теперь, после овладения созданием объектов Deployment, можно переходить к рассмотрению процесса обновления нашего приложения с помощью данного инструмента. В основе своей обновление приложения при помощи Deployment представляет собой простую операцию, требующую лишь некоторых изменений в шаблоне пода.
3.1 Описание стратегий обновления: RollingUpdate и Recreate
Однако возникает вопрос: каким механизмом Deployment будет обновлять наши поды? Для выполнения этой задачи мы располагаем двумя стратегиями обновления - RollingUpdate и Recreate.
Примеры стратегий:
apiVersion: apps/v1 |
apiVersion: apps/v1 |
3.1.1 Обновление с постепенной заменой (RollingUpdate)
Данная стратегия предусматривает инкрементное обновление подов. Если у нас присутствуют множественные реплики одного и того же пода, мы в состоянии добавлять новые реплики с обновленной версией по одной, аналогично удаляя старые реплики. Эта методика минимизирует риск простоя, поскольку в любой промежуток времени хотя бы один под приложения продолжает функционировать. Важным замечанием является то, что во время обновления могут одновременно функционировать поды различных версий, что может вызвать проблемы совместимости.
3.1.2 Полное пересоздание (Recreate)
Альтернативный подход, "Recreate", предполагает полное уничтожение всех подов приложения перед деплоем новых подов с обновленной версией. Данный метод является более радикальным и ведет к временному простою приложения, поскольку между остановкой старых подов и запуском новых существует временной промежуток. Однако, таким образом устраняется риск конфликта версий, поскольку поды различных версий никогда не функционируют совместно.
Выбор стратегии обновления определяется конкретным случаем и требованиями к приложению. Если первоочередной задачей является предотвращение даже незначительного простоя, то следует применять "RollingUpdate". Если критически важно гарантировать, что различные версии приложения никогда не работают совместно, рекомендуется выбрать "Recreate".
В представленном выше примере отображены спецификации Deployment для обеих стратегий. Для RollingUpdate у нас есть два дополнительных параметра - maxSurge и maxUnavailable.
maxSurge – Определяет, насколько превысить указанное в Deployment количество реплик подов можно. По умолчанию используется значение 25%. То есть, если в конечном итоге мы хотим получить 4 реплики, то во время обновления никогда не будет одновременно запущено более пяти экземпляров пода. При переводе процентного значения в абсолютное число округление производится в большую сторону. Вместо процентного значения можно указать абсолютное. Этот параметр, по сути, выражает нашу готовность инвестировать больше средств в увеличение задействованных ресурсов в обмен на повышение скорости развертывания.
maxUnavailable – Определяет, сколько экземпляров пода может быть недоступно во время процесса обновления. По умолчанию это значение также составляет 25%. Если запрашиваемое количество реплик равно четырем и процентное значение равно 25%, то только один под может быть недоступен. Как и в случае с maxSurge, вместо процентного значения можно указать абсолютное. Этот параметр, по сути, выражает нашу устойчивость к возможной недостаче подов при нагрузке.
4. Заключение
В ходе нашего обсуждения мы проследили, как Kubernetes с его объектом Deployment облегчает процесс управления приложениями и их обновлениями. Возможность декларативного описания состояния приложения, автоматическое управление подами и способность быстро и безопасно откатывать изменения делают Deployment ключевым инструментом для разработчиков.
В этом контексте мы увидели, как можно обновить приложение в Kubernetes, обсудив стратегии и подходы к обновлению версий приложений. Осознавая потенциальные проблемы с совместимостью между различными версиями приложений, важно тщательно планировать и управлять этим процессом.
В целом, эффективное использование Deployment в Kubernetes помогает обеспечить гибкость, масштабируемость и устойчивость приложений, что делает его мощным инструментом в руках разработчиков.