Стратегии деплоя в Kubernetes: Часть 1

Стратегии деплоя в Kubernetes: Часть 1


Kubernetes — это уже новая реальность…! Он стал стандартом де-факто для оркестрации контейнеров. Сегодня разберём, какие механизмы предоставляет сам Kubernetes для разных стратегий деплоя. Всегда полезно понимать доступные варианты и как можно безболезненно выкатывать новые версии приложений. Правда, в реальном продакшене мы редко ограничиваемся только Kubernetes — обычно подключаем дополнительные инструменты из экосистемы.

Например, вы можете использовать Helm Charts для упаковки приложений или работать с OpenShift / Rancher, которые расширяют возможности «голого» Kubernetes. Но сегодня давайте без лишних усложнений — посмотрим, какие есть стратегии деплоя средствами самого Kubernetes.

Recreate

При стратегии Recreate старые pod’ы сначала останавливаются, а потом Kubernetes разворачивает новые экземпляры.

Например, если вы активно разрабатываете приложение и нужно быстро протестировать свежую версию, Recreate — самый простой способ быстро выкатить новый образ.

Плюсы:

  • Просто. Завершаем старые инстансы и «пересоздаём» новые.

Минусы:

  • Есть простой. Все pod’ы останавливаются, и приложение на время недоступно.

Rolling Updates

Rolling updates обновляют pod’ы постепенно, без простоя. Эта стратегия позволяет параллельно гасить старую версию и запускать новую.

Blue/Green Deployment

При Blue/Green деплое новая версия приложения (синяя — Blue) запускается параллельно с текущей стабильной (зелёной — Green).

Пользователи продолжают работать со стабильной версией, а новая используется для тестов и проверки.

Когда тестирование проходит успешно и все проверки здоровья пройдены, трафик перенаправляется на новую версию, и она становится «зелёной» — стабильной.

Плюсы:

  • Быстрый откат.
  • Нет простоя.
  • Можно тестировать прямо в продакшене.

Минусы:

  • Дополнительные ресурсы — приходится держать две версии одновременно.
  • Kubernetes не ведёт версионность такого деплоя, так как новая версия — это полностью отдельный deployment.

Canary Deployment

Стратегия Canary позволяет «прокатить» новую версию приложения прямо в продакшене на ограниченном трафике.

Сначала поднимается небольшой набор pod’ов новой версии, и к ним направляется часть реального трафика для тестирования и мониторинга.

Когда проверка проходит успешно, количество реплик новой версии постепенно увеличивается, пока весь трафик не перейдёт на неё.

В «нативном» Kubernetes Canary-деплой реализуется с помощью Services.

Мы создаём новый deployment с теми же label’ами, что и у стабильной версии. Service будет распределять трафик между старыми и новыми pod’ами в зависимости от их количества.

Плюсы:

  • Больше контроля над процессом выката.
  • Можно использовать реальный трафик для проверки новых фич.

Минусы:

  • Дополнительные ресурсы на параллельный запуск двух версий.
  • Управлять трафиком сложно. В Kubernetes Service распределяет его просто по количеству pod’ов.
  • Например, если у вас 5 pod’ов стабильной версии и вы хотите отправить 20% трафика на новую, придётся поднять 1 pod — но он получит 17% (1 из 6).
  • Для более точного контроля придётся использовать service mesh, например Istio.

Практический пример

Настройка текущего окружения

Для простоты давайте считать, что наше продакшн-приложение — это веб-сервер Nginx, который раздаёт критически важный файл index.html.

1. Деплой webapp v1 через манифест my-webapp.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  selector:
    matchLabels:
      app: webapp
  replicas: 2
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: yaiiteng/my-nginx:v1
        ports:
        - containerPort: 80

2. Создание сервиса для доступа к приложению извне

Чтобы упростить пример, используем NodePort-сервис.

В реальном продакшене, скорее всего, вы бы применили Ingress или LoadBalancer.

Создадим манифест my-webapp-services.yml:

apiVersion: v1
kind: Service
metadata:
  name: webapp-service
  labels:
    app: webapp
spec:
  selector:
    app: webapp
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 32001

3. Применяем ресурсы через kubectl

kubectl apply -f my-webapp.yml
kubectl apply -f my-webapp-services.yml
В реальных проектах обычно используют Helm Charts, чтобы упаковать и версионировать все манифесты.

На этом этапе у вас будут развернуты нужные ресурсы в кластере.

Доступ к Nginx можно получить по адресу:

http://<kubernetes-node>:32001

Отлично, теперь попробуем задеплоить версию v2.

Представим, что в ней произошли серьёзные изменения, и ваш CI-пайплайн уже собрал Docker-образ my-nginx:v2.

Дальше мы протестируем разные стратегии деплоя, чтобы обновить приложение с v1 до v2.

Rolling Update

Стратегия RollingUpdate — это стратегия деплоя по умолчанию в Kubernetes.

Мы не задавали никакой стратегии в нашем my-webapp.yml при создании, но Kubernetes автоматически добавил в раздел spec такие параметры:

  • spec.strategy.type: RollingUpdate — указывает, что деплой будет выполняться по стратегии rolling update.
  • spec.strategy.rollingUpdate.maxSurge: 25% — максимум на 25% можно создавать pod’ов сверх нужного количества реплик во время обновления.
  • spec.strategy.rollingUpdate.maxUnavailable: 25% — допускается, что до 25% pod’ов могут быть недоступны в процессе деплоя.

Чтобы задеплоить новую версию, всё, что нужно сделать — поменять тег образа в my-webapp.yml:

containers:
- name: webapp
  image: yaiiteng/my-nginx:v2

и затем выполнить:

kubectl apply -f my-webapp.yml

После применения манифеста Kubernetes начнёт обновление:

старые pod’ы будут удаляться по одному, а на их место постепенно поднимутся новые с версией v2.

Так как у нас всего 2 реплики, процесс будет выглядеть примерно так:

Да, приложение обновлено до v2

Что происходит «под капотом»

Kubernetes уменьшает количество pod’ов в текущем ReplicaSet, создаёт новый ReplicaSet для версии v2 и постепенно увеличивает количество его реплик, пока не достигнет нужного числа.

Recreate

Чтобы использовать стратегию Recreate, достаточно в манифесте указать:

spec:
  strategy:
    type: Recreate

В этом случае Kubernetes одновременно завершит все существующие pod’ы и только после этого создаст новые.

Полный пример манифеста:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  labels:
    app: webapp
spec:
  selector:
    matchLabels:
      app: webapp
  replicas: 2
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: webapp
    spec:
      containers:
      - name: webapp
        image: yaiiteng/my-nginx:v2
        ports:
        - containerPort: 80

После того как обновите YAML и выполните команду:

kubectl apply -f my-webapp.yml

Kubernetes сначала убьёт все старые pod’ы, а затем пересоздаст новые — в том же количестве реплик.

Минус очевиден: пока старые pod’ы удаляются и новые ещё не запустились, приложение полностью недоступно.

Но если вы работаете в тестовом окружении или нужно быстро накатить изменения без сложных сценариев, Recreate — простой и прямолинейный вариант.

Дополнительные советы

1.Обновлять образ в деплойменте можно и через команду set image. Она подтянет новый образ и обновит запущенный деплоймент, но манифест при этом не изменится. Если вам нужно зафиксировать изменения в коде инфраструктуры, правильнее обновить манифест и применить его через kubectl apply -f.

kubectl set image deployment.v1.apps/nginx-deployment nginx=nginx:1.16.1

2.Посмотреть историю выката версий можно через kubectl rollout history:

kubernetes/deployment $ kubectl rollout history deploy webapp
deployment.apps/webapp
REVISION  CHANGE-CAUSE
1         <none>
2         <none>

kubernetes/deployment $

3.Откат делается опцией undo у команды rollout:

kubernetes/deployment $ kubectl rollout undo  deploy/webapp
deployment.apps/webapp rolled back
kubernetes/deployment $

В следующей части посмотрим, как делать Canary Deployment и Blue/Green деплой.

Report Page