CI/CD Kubernetes платформа Gitorion. Canary-релизы

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Привет всем! Перед деплоем нового релиза приложения в продакшен хорошей практикой является оценка его работы с запросами от реальных пользователей. Если разом заменить текущий релиз приложения на новый, есть вероятность в случае ошибки в программном обеспечении повредить данные большого числа пользователей или получить непрогнозируемое поведение нового релиза под нагрузкой. Чтобы избежать указанных трудностей используют Canary-релизы - это когда рядом с актуальным релизом приложения в продакшене развертывают релиз с новой версией приложения и направляют на него часть запросов от реальных пользователей. В данной статье мы расскажем о нашем опыте внедрения Canary-релизов в CI/CD платформу Gitorion.

Схема стенда

Варианты реализации Canary-релизов рассмотрим на примере, приведенном на рисунке ниже. В кластере Kubernetes развернуто приложение, состоящее из микросервисов frontend и backend. В контуре production развернут текущий актуальный релиз приложения, с которым работают клиенты в данный момент. В контуре staging развернут, протестирован и продемонстрирован заказчику новый релиз приложения. Точку входа в кластер и доступ клиентов к приложению выполняет контроллер Ingress-nginx. Теперь нужно протестировать в production новый релиз приложения из контура staging.

Схема стенда
Схема стенда

Canary-релизы c помощью контроллера Ingress-nginx

Данный вариант подойдет для микросервисов, подключенных как бэкенд непосредственно к контроллеру Ingress-nginx. В нашем примере это микросервис frontend. В контуре production создайте службу (Service) с именем "frontend-canary" и Deployment с именем "frontend-canary", который запускает модуль с контейнером, созданным из Docker-образа "Image: frontend:30257". Данный Docker-образ "Image: frontend:30257" использован для запуска контейнера с новой версией приложения в контуре staging (на картинке ниже выделили красным цветом).

Canary-релиз для фронтенда
Canary-релиз для фронтенда

Ниже приведем yaml-манефест Ingress уже созданный в production контуре, который направляет трафик для домена gitorion.ru в службу с именем "frontend", которая в свою очередь передает запросы в модуль с текущей версией приложения.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    meta.helm.sh/release-name: frontend
    meta.helm.sh/release-namespace: production
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: frontend
  namespace: production
spec:
  ingressClassName: nginx
  rules:
  - host: gitorion.ru
    http:
      paths:
      - backend:
          service:
            name: frontend
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - gitorion.ru
    secretName: infrastructure-tls

Добавьте в production еще один Ingress с именем "frontend-canary", который направит 10% трафика, предназначенного тому же домену gitorion.ru, в службу с именем "frontend-canary", которая в свою очередь направит запрос в модуль с новой версией приложения.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    meta.helm.sh/release-name: frontend-canary
    meta.helm.sh/release-namespace: production
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: canary
    nginx.ingress.kubernetes.io/canary-weight: "10"
  generation: 1
  labels:
    app.kubernetes.io/managed-by: Helm
  name: frontend-canary
  namespace: production
spec:
  ingressClassName: nginx
  rules:
  - host: gitorion.ru
    http:
      paths:
      - backend:
          service:
            name: frontend-canary
            port:
              number: 80
        path: /
        pathType: Prefix
  tls:
  - hosts:
    - gitorion.ru
    secretName: infrastructure-tls

В аннотации "nginx.ingress.kubernetes.io/canary-weight" задайте, какой процент запросов реальных пользователей контроллер Ingress-nginx должен направить на Canary-релиз приложения. Постепенно увеличивайте значение "nginx.ingress.kubernetes.io/canary-weight" в ходе тестирования, наращивая количество запросов от реальных пользователей в модуль с новым релизом приложения.

Непрерывную доставку (Continuous Delivery) в CI/CD платформе Gitorion выполняет Jenkins, поэтому мы добавили параметризованный пайплайн, создающий в production контуре Service, Deployment и Ingress с именами ''frontend-canary" и позволяющий менять значение параметра "nginx.ingress.kubernetes.io/canary-weight" в аннотации Ingress "backend-canary".

Пайплайн Jenkins для Canary-релиза фронтенда
Пайплайн Jenkins для Canary-релиза фронтенда

В случае успешного завершения тестирования, задайте значение параметра 0 в списке "Какой процент запросов направить на Canary-релиз", и пайплайн удалит Ingress, Service и Deployment с именем "frontend-canary". Теперь тимлид может уверенно запустить пайплайн, который развернет контейнер с новой версией приложения из Docker-образа "Image: frontend:30257" в контур production.

Canary-релизы с помощью Kubernetes Service Mesh

Теперь разберем, как развернуть Canary-релиз, в случае если микросервис не подключен непосредственно к контроллеру Ingress-nginx или точка входа в кластер Kubernetes реализована не с помощью Ingress-nginx. На нашем стенде это микросервис backend.

В Kubernetes вновь созданные модули получают динамический IP-адрес из подсети IP-адресов для модулей. Если Deployment или StatefulSet запускает несколько модулей приложения при горизонтальном масштабировании, точку единого входа организуют с помощью службы (Service). На модули навешивают метки (Labels), и служба с помощью селектора (Selector) направляет запросы в модули микросервиса с заданной меткой. Трафик равномерно балансируется между всеми модулями.

На рисунке ниже новая версия приложения запущена в staging контуре в контейнере, созданном из Docker-образа "Image:backend:cad09" (выделили красным цветом). Заказчик протестировал и одобрил новую версию приложения, и пришло время протестировать его в продакшене.

В production контуре создайте еще один Deployment с именем "backend-canary", запускающий модуль с контейнером, созданным из Docker-образа "Image:backend:cad09", с новой версией приложения. Навесьте метку "app:backend" на модули нового релиза, точно такую же, как и на модулях старого релиза, и служба (Service) с именем "backend" направит часть запросов в модуль с новой версией приложения.

Canary-релиз для бэкенда
Canary-релиз для бэкенда

Cписок модулей сервиса backend в контуре production:

control@dc1-plane:~$ kubectl get pod -n production -o wide
NAME                               READY   STATUS    RESTARTS   AGE     IP             NODE          NOMINATED NODE   READINESS GATES
backend-55bd4f7b68-ckttw           1/1     Running   0          30m     10.10.137.22   dc1-worker1   <none>           <none>
backend-55bd4f7b68-m865n           1/1     Running   0          22s     10.10.137.14   dc1-worker1   <none>           <none>
backend-55bd4f7b68-t432g           1/1     Running   0          22s     10.10.137.15   dc1-worker1   <none>           <none>
backend-canary-59674db64b-rt76l    1/1     Running   0          5m52s   10.10.137.17   dc1-worker1   <none>           <none>
frontend-777d84c7cd-5d2bc          1/1     Running   0          30m     10.10.137.38   dc1-worker1   <none>           <none>

Описание службы "backend" в контуре production:

control@dc1-plane:~$ kubectl describe svc backend -n production
Name:              backend
Namespace:         production
Labels:            app=backend
                   app.kubernetes.io/managed-by=Helm
Annotations:       meta.helm.sh/release-name: backend
                   meta.helm.sh/release-namespace: production
Selector:          app=backend
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.98.154.72
IPs:               10.98.154.72
Port:              <unset>  9000/TCP
TargetPort:        9000/TCP
Endpoints:         10.10.137.22:9000,10.10.137.14:9000,10.10.137.15:9000,10.10.137.17:9000
Session Affinity:  None
Events:            <none>

Среди конечных точек Endpoints службы "backend" видим три IP-адреса модулей со старой версией приложения (10.10.137.22, 10.10.137.14, 10.10.137.15) и один IP-адрес (10.10.137.17) модуля с новой версией приложения. Cоответственно, 3/4 запросов реальных пользователей (или 75%) пойдет на старую версию приложения, 1/4 запросов (или 25%) - на новую. Добейтесь требуемого вам процентного соотношения запросов запуском соответствующего количества модулей в Deployment-ах "backend" и "backend-canary".

Мы добавили в Jenkins параметризованный пайплайн, в котором можно изменить количество реплик старого и нового релиза.

Пайплайн Jenkins для Canary-релиза бэкенда
Пайплайн Jenkins для Canary-релиза бэкенда

По кнопке "Собрать" пайплайн cоздаст в production контуре Deployment c именем "backend-canary", запускающий в модулях контейнеры из Docker-образа "Image: backend:cad09" с новой версией приложения. Тут же можно менять количество реплик для Deployment-ов старого и нового релизов. После завершения удачного тестирования, задайте значение 0 в поле "Количество реплик Canary-релиза", и пайплайн удалит Deployment с именем "backend-canary". Теперь тимлид может запустить пайплайн, выполняющий промоушен новой версии приложения из контура staging в контур production.

Заключение

В данной статье мы рассказали о нашем опыте внедрения Canary-релизов в CI/CD платформу Gitorion. Продемонстрированные практики предназначены для CI/CD цикла, развернутого в кластере Kubernetes, и реализуют канареечные развертывания как для фронтенда, так и для бэкенда. Спасибо за внимание!

Источник: https://habr.com/ru/companies/gitorion/articles/879434/


Интересные статьи

Интересные статьи

Движок, он же фреймворк (framework), 1С-Битрикс довольно популярен в странах СНГ.Подкупает он своей универсальностью, собственным маркетплейсом со множеством модулей расширения, как платных так и бесп...
Привет, Хабр!Сегодня я продолжу рассказывать про Component Object Model (COM) и атаку COM Hijacking.В предыдущей части "Тайная жизнь COM: погружение в методы hijacking" я разобрала способы h...
Название позаимствовано у Гарри Гарриcона. Но речь у нас пойдет сегодня не о фантастике, а о намного более приземленных вещах. Всякого рода рода Ethics&Compliance кейсах, о том как они разруливают...
Всем привет! На связи ИТ-команда подразделения ДОМ.РФ Земли. Мы занимаемся автоматизацией вовлечения в оборот неиспользуемых или используемых не по назначению федеральных земельных участков и объектов...
Приступая к животрепещущей теме резервного копирования на «Битрикс», прежде всего хотелось бы поблагодарить разработчиков, реализовавших автоматическое резервное копирование в облачное хранилище в вер...