Как бороться с критическими изменениями в Service Mesh

Я создаю пример микросервисного приложения с Kubernetes, чтобы узнать о лучших практиках и некоторых шаблонах для будущих проектов. Я использую Istio в качестве Service Mesh для обработки трафика с востока на запад, и у меня есть базовое понимание концепций (VirtualServices, DestinationRules, ...). Сервисная сетка позволяет мне легко выпускать новые версии микросервиса и перенаправлять трафик на новый экземпляр (например, с использованием взвешенного распределения). Имея в виду семантическое управление версиями, это очень хорошо работает для обновлений Patch и Minor, поскольку они теоретически не изменяют существующий контракт и, следовательно, могут быть заменой существующей службы. Теперь мне интересно, как правильно поступать с критическими изменениями службы, поэтому обновление версии Major.

Трудно найти информацию для этого, но с той ограниченной информацией, которую я получил, я теперь думаю о двух подходах:

  1. Каждая основная версия службы (например, user-service) получает свой собственный VirtualService, чтобы клиенты могли обращаться к ней правильно (по другому имени службы, например, user-service-v1). Затем Istio используется для правильной маршрутизации трафика основной версии (например, 1.*) к различным доступным службам (например, user-service v1.3.1 и user-service v1.4.0).

  2. Я использую один общий VirtualService для конкретного микросервиса (например, user-service). Этот VirtualService содержит множество определений маршрутизации для использования, например: заголовок, отправленный клиентом (например, x-major-version=1), чтобы сопоставить запрос к месту назначения.

В целом между обоими методами нет большой разницы. Очевидно, что клиенту необходимо указать, с какой основной версией он хочет разговаривать, либо установив заголовок, либо разрешив другое имя службы. Существуют ли какие-либо ограничения описанных методов, которые делают один лучше другого? Или есть другие варианты, которые мне совершенно не хватает? Любая помощь и указатели приветствуются!


person Simon    schedule 02.11.2020    source источник
comment
Привет, @Simon! Если мы говорим об этих двух пунктах, я бы сказал, что вам следует придерживаться подхода 1 и использовать правило назначения с подмножествами для правильного распределения трафика. 1. Что вы имеете в виду под обновлением основной версии, старое приложение все еще работает, а вы создаете новое с новым образом и новой службой, и вы не хотите проверять, будет ли оно правильно работать с вашей конфигурацией istio? 2. Вы видели канареечное развертывание и зеркалирование трафика?   -  person Jakub    schedule 03.11.2020


Ответы (1)


TL; DR

Помимо того, что я упомянул в комментариях, после более подробной проверки темы я бы выбрал подход 2 с одной общей виртуальной службой для конкретного микросервиса с канареечным развертыванием и зеркальное отображение.

Подход 1

Как указано в документации

В ситуациях, когда неудобно определять полный набор правил или политик маршрутизации для конкретного хоста в одном ресурсе VirtualService или DestinationRule, может быть предпочтительнее постепенно указывать конфигурацию хоста в нескольких ресурсах. Pilot объединит такие правила назначения и объединит такие виртуальные службы, если они привязаны к шлюзу.

Итак, в теории вы можете использовать подход номер 1, но я бы сказал, что здесь слишком много конфигурации, и есть лучшая идея сделать это.

Допустим, у вас есть старое приложение с именем v1.3.1 и новое приложение с именем v1.4.0, поэтому соответствующая виртуальная служба будет выглядеть следующим образом.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-vervice1
spec:
  hosts:
  - '*'
  http:
  - name: "v1.3.1"
    route:
    - destination:
        host: service1.namespace.svc.cluster.local

---

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-service2
spec:
  hosts:
  - '*'
  http:
  - name: "v1.4.0"
    route:
    - destination:
        host: service2.namespace.svc.cluster.local

Подход 2

В практике я бы выбрал подход номер 2, например, вы можете создать 2 версии своего приложения, в приведенном ниже примере это old и new, а затем настроить для них виртуальную службу и правила назначения.

Здесь возникает вопрос: почему? Поскольку им легче управлять, по крайней мере, для меня, и здесь легко использовать канареечное развертывание и зеркалирование, подробнее об этом ниже.

Допустим, вы развернули новое приложение, вы не хотите отправлять сюда 1% входящего трафика, кроме того, вы можете использовать зеркало, поэтому каждый запрос, который отправляется на старую службу, будет отражаться на новую службу в целях тестирования.

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: vs-vervice
spec:
  hosts:
  - '*'
  http:
  - name: "old"
    route:
    - destination:
        host: service.namespace.svc.cluster.local
        subset: v1
      weight: 99
    mirror:
      host: service.namespace.svc.cluster.local
      subset: v2
    mirror_percent: 100
  - name: "new"
    route:
    - destination:
        host: service.namespace.svc.cluster.local
        subset: v2
      weight: 1

---


apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews-destination
spec:
  host: service.namespace.svc.cluster.local
  subsets:
  - name: v1
    labels:
      version: v1  <--- label on old pod
  - name: v2
    labels:
      version: v2  <--- label on new pod

Тестирование нового приложения

Очевидно, что клиенту необходимо указать, с какой основной версией он хочет разговаривать, либо установив заголовок, либо разрешив другое имя службы.

На самом деле это зависит от конфигурации, если вы используете вышеуказанный вариант с версиями new и old, то это то, что канареечное развертывание, например. взвешенное распределение, используется для. Вы можете указать процент трафика, который должен быть отправлен в новую версию вашего приложения. Конечно, вы можете указать заголовки или префиксы в своей виртуальной службе, чтобы пользователи могли использовать старую или новую версию вашего приложения.

Канарское развертывание

Как упоминалось, здесь

Одним из преимуществ проекта Istio является то, что он обеспечивает контроль, необходимый для развертывания канареечных сервисов. Идея канареечного развертывания (или развертывания) состоит в том, чтобы представить новую версию службы, сначала протестировав ее с использованием небольшого процента пользовательского трафика, а затем, если все пойдет хорошо, увеличивать, возможно, постепенно, процент при одновременном поэтапном отказе. старая версия. Если что-то пойдет не так, мы прервемся и вернемся к предыдущей версии. В своей простейшей форме трафик, отправляемый в канареечную версию, представляет собой случайно выбранный процент запросов, но в более сложных схемах он может быть основан на регионе, пользователе или других свойствах запроса.

В зависимости от вашего уровня знаний в этой области вы можете задаться вопросом, зачем вообще нужна поддержка Istio для канареечного развертывания, учитывая, что такие платформы, как Kubernetes, уже предоставляют способ развертывания версий и канареечного развертывания. Проблема решена, да? Не совсем так. Хотя такой способ развертывания работает в простых случаях, он очень ограничен, особенно в крупномасштабных облачных средах, получающих большой (и особенно разный) трафик, где необходимо автомасштабирование.

istio

В Istio маршрутизация трафика и развертывание реплик - две полностью независимые функции. Количество модулей, реализующих сервисы, может свободно увеличиваться и уменьшаться в зависимости от нагрузки трафика, что полностью ортогонально управлению маршрутизацией трафика версий. Это значительно упрощает управление канареечной версией при наличии автомасштабирования. Фактически автомасштабирующие устройства могут реагировать на изменения нагрузки в результате изменений маршрутизации трафика, но, тем не менее, они функционируют независимо и ничем не отличаются от изменений нагрузки по другим причинам.

Правила маршрутизации Istio также предоставляют другие важные преимущества; вы можете легко управлять точными процентными показателями трафика (например, направлять 1% трафика, не требуя 100 модулей), и вы можете управлять трафиком, используя другие критерии (например, маршрутизировать трафик для определенных пользователей в канареечную версию). Чтобы проиллюстрировать это, давайте посмотрим на развертывание службы helloworld и посмотрим, насколько простой становится проблема.

Существует пример.

Зеркальное отображение

Второе, что часто используется для тестирования новой версии приложения, - это зеркалирование трафика.

Как упоминалось, здесь

Используя Istio, вы можете использовать зеркалирование трафика для дублирования трафика на другую службу. Вы можете включить правило зеркалирования трафика как часть канареечного конвейера развертывания, что позволит вам анализировать поведение службы перед отправкой ей реального трафика.

Если вы ищете передовой опыт, я бы рекомендовал начать с этого руководства На среднем уровне, потому что здесь это очень хорошо объясняется.

Как работает зеркалирование трафика

Зеркалирование трафика работает следующим образом:

  • Вы развертываете новую версию приложения и включаете зеркалирование трафика.

  • Старая версия отвечает на запросы, как и раньше, но также отправляет асинхронную копию новой версии.

  • Новая версия обрабатывает трафик, но не отвечает пользователю.

  • Операционная группа следит за новой версией и сообщает о любых проблемах группе разработчиков.

введите описание изображения здесь

Поскольку приложение обрабатывает живой трафик, это помогает команде обнаруживать проблемы, которые они обычно не обнаруживают в опытной среде. Вы можете использовать инструменты мониторинга, такие как Prometheus и Grafana, для записи и мониторинга результатов ваших тестов.

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

Стоит отметить, что если вы используете API-интерфейсы записи, такие как заказ или оплата, то зеркальный трафик будет означать, что API-интерфейсы записи, такие как заказ, несколько раз. Эта тема подробно описана здесь Кристиан Поста.


Дайте мне знать, если вы хотите еще что-то обсудить.

person Jakub    schedule 30.11.2020
comment
Большое спасибо за отличный ответ! Я свяжусь с вами, если мне нужно будет обсудить другие архитектурные вопросы;) - person Simon; 30.11.2020