VirtualService и DestinationRule в Istio: Готовые конфиги для Canary и A/B-тестов | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

VirtualService и DestinationRule в Istio: Готовые конфиги для Canary и A/B-тестов

12 июня 2026 8 мин. чтения

Управление трафиком в сервисной сетке Istio строится на двух ключевых ресурсах: VirtualService и DestinationRule. VirtualService определяет, куда и по каким правилам направлять входящие запросы. DestinationRule задает политики балансировки нагрузки и отказоустойчивости для конечных подов. Без понимания их совместной работы попытки внедрить canary-развертывания или A/B-тесты приводят к ошибкам и неработающим конфигурациям.

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

VirtualService и DestinationRule: как они работают вместе

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

Последовательность такова:

  1. Запрос поступает в sidecar-прокси Envoy.
  2. Envoy проверяет конфигурацию VirtualService для целевого хоста. Он определяет, соответствует ли запрос условиям (match), например, наличию заголовка или определенному URI, и выбирает конечный subset с указанным весом (weight).
  3. После определения целевого хоста и subset Envoy обращается к DestinationRule. Это правило указывает, на какие конкретные поды (по лейблам) нацелен subset, и применяет настройки балансировки, таймауты и политики обнаружения выбросов.

VirtualService без DestinationRule может выполнять базовую маршрутизацию. Однако для продакшен-среды с требованиями к отказоустойчивости и балансировке DestinationRule становится критически важным.

VirtualService: дирижер маршрутов вашего трафика

VirtualService позволяет декларативно управлять маршрутизацией трафика к сервисам в mesh. Его ключевые поля:

  • hosts: список имен сервисов Kubernetes, к которым применяются правила. Это могут быть полные FQDN или короткие имена в пределах namespace.
  • http, tcp, tls: массивы правил для соответствующего протокола.
  • Внутри правил http используются:
    • match: условия для выбора запроса (заголовки, URI, метод).
    • route: определение целевого destination (host и subset) и распределения весов трафика между ними.

Простейший VirtualService, который просто проксирует весь трафик на сервис catalog-service, выглядит так:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: catalog-vs
spec:
  hosts:
  - catalog-service
  http:
  - route:
    - destination:
        host: catalog-service

Этот пример служит базой. Мощь VirtualService раскрывается при добавлении условий match и разделении трафика между несколькими destination.

DestinationRule: политики балансировки и отказоустойчивости

DestinationRule определяет, что происходит с трафиком после того, как VirtualService направил его к конкретному хосту. Этот ресурс задает политики на уровне конечных подов.

Основные поля DestinationRule:

  • host: целевой сервис Kubernetes, к которому применяется правило.
  • subsets: логические группы подов внутри сервиса. Чаще всего subsets создаются по лейблам версии (version: v1, version: v2). Именно на эти subsets ссылается поле destination.subset в VirtualService.
  • trafficPolicy: сердце DestinationRule. Здесь настраиваются:
    • loadBalancer: стратегия балансировки (ROUND_ROBIN, LEAST_CONN, RANDOM).
    • connectionPool: ограничения на соединения и запросы для защиты от перегрузки.
    • outlierDetection: автоматическое исключение неработающих подов из балансировки.
    • tls: настройки безопасности подключения.

Без DestinationRule Istio использует настройки по умолчанию. Для production-среды их почти всегда требуется донастраивать.

Готовые конфигурации для ключевых сценариев

Следующие примеры YAML-манифестов готовы к применению. Вам нужно заменить имена сервисов, namespace и значения лейблов на соответствующие вашей среде. Применить конфигурации можно командой kubectl apply -f <file-name>.yaml.

Canary-развертывание (весовая маршрутизация)

Цель: направить 10% трафика на новую версию (canary) микросервиса, оставив 90% на стабильной версии. Предполагается, что у вас есть два деплоймента одного сервиса с лейблами version: v1 (stable) и version: v2 (canary).

Сначала создаем DestinationRule, определяющую subsets:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: catalog-dr
spec:
  host: catalog-service
  subsets:
  - name: stable
    labels:
      version: v1
  - name: canary
    labels:
      version: v2

Затем настраиваем VirtualService для распределения трафика по весам:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: catalog-vs
spec:
  hosts:
  - catalog-service
  http:
  - route:
    - destination:
        host: catalog-service
        subset: stable
      weight: 90
    - destination:
        host: catalog-service
        subset: canary
      weight: 10

Чтобы увеличить долю трафика на canary, постепенно меняйте значения weight в VirtualService (например, на 50/50, затем 10/90) и повторно применяйте манифест. Важно: обе версии сервиса должны иметь совместимый API, чтобы не ломать запросы пользователей.

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

A/B-тестирование (маршрутизация по HTTP-заголовкам)

Цель: направлять трафик на новую версию интерфейса только для пользователей с заголовком user-type: beta-tester. Это позволяет тестировать фичи на внутренней аудитории или определенных сегментах.

DestinationRule остается аналогичной предыдущему примеру, определяя subsets stable и new-ui.

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: frontend-dr
spec:
  host: frontend-service
  subsets:
  - name: stable
    labels:
      version: v1
  - name: new-ui
    labels:
      version: v2

VirtualService использует секцию match для фильтрации трафика:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: frontend-vs
spec:
  hosts:
  - frontend-service
  http:
  - match:
    - headers:
        user-type:
          exact: beta-tester
    route:
    - destination:
        host: frontend-service
        subset: new-ui
  - route:
    - destination:
        host: frontend-service
        subset: stable

Правила в VirtualService обрабатываются сверху вниз. Первое правило перехватывает запросы с нужным заголовком и направляет их на subset new-ui. Все остальные запросы попадают на последнее правило без условия match и идут на стабильную версию. Этот же подход можно использовать для маршрутизации по геолокации, типу устройства или другим параметрам в заголовках.

Повышение отказоустойчивости: таймауты, повторные попытки и Circuit Breaker

Продакшен-конфигурация требует настройки политик устойчивости для предотвращения каскадных сбоев. В этом примере сочетаются настройки в VirtualService и DestinationRule.

VirtualService настраивает таймауты и повторные попытки:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: payment-vs
spec:
  hosts:
  - payment-service
  http:
  - route:
    - destination:
        host: payment-service
    timeout: 3s
    retries:
      attempts: 3
      perTryTimeout: 2s
      retryOn: connect-failure,refused-stream,unavailable

DestinationRule определяет политики балансировки, пула соединений и автоматического исключения неисправных инстансов:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: payment-dr
spec:
  host: payment-service
  trafficPolicy:
    loadBalancer:
      simple: LEAST_CONN
    connectionPool:
      tcp:
        maxConnections: 100
        connectTimeout: 250ms
      http:
        http2MaxRequests: 1000
        maxRequestsPerConnection: 10
    outlierDetection:
      consecutive5xxErrors: 5
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 50

Эти настройки означают:

  • timeout и retries в VS: запрос отменяется через 3 секунды, при сбоях соединения делается до 3 повторных попыток с лимитом 2 секунды на каждую.
  • loadBalancer: LEAST_CONN в DR: трафик направляется на под с наименьшим числом активных соединений.
  • connectionPool ограничивает нагрузку на сервис, предотвращая его перегрузку.
  • outlierDetection исключает под из балансировки на 30 секунд, если он вернул 5 ошибок 5xx подряд в течение 10-секундного окна. Максимум можно исключить 50% подов.

Подобные настройки критически важны для stateful-сервисов, таких как базы данных или платежные шлюзы. Для комплексной миграции таких нагрузок в Kubernetes обратитесь к руководству по миграции приложений в Kubernetes.

Диагностика и решение типичных проблем

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

Команды istioctl для проверки конфигурации

Утилита istioctl предоставляет прямую проверку того, что видит sidecar-прокси конкретного пода.

  • istioctl proxy-config routes <pod-name>.<namespace> --name <service-port> – показывает все маршруты, сконфигурированные для указанного пода. Ищите свой хост и ожидаемые веса или subset.
  • istioctl proxy-config clusters <pod-name>.<namespace> – отображает кластеры (цели), известные прокси. Убедитесь, что нужный сервис и subset присутствуют в списке.
  • istioctl analyze <namespace> – выполняет статический анализ конфигураций Istio в namespace и выявляет распространенные ошибки, например, ссылки на несуществующие subset в DestinationRule.

Что делать, если трафик не идет по новому правилу?

Следуйте этому чек-листу:

  1. Проверьте namespace. VirtualService и DestinationRule должны быть применены в том же namespace, что и целевой сервис, либо в spec.hosts должен быть указан полный FQDN (например, catalog-service.my-namespace.svc.cluster.local).
  2. Сравните имена хостов. Поле spec.hosts в VirtualService и spec.host в DestinationRule должны точно соответствовать имени сервиса Kubernetes, на который вы хотите направить трафик.
  3. Убедитесь в существовании subset. Лейблы, указанные в subsets DestinationRule (например, version: v2), должны присутствовать на целевых подах сервиса. Проверьте командой kubectl get pods -l version=v2.
  4. Используйте команды отладки. Выполните istioctl proxy-config routes для пода, который отправляет трафик (клиента), и убедитесь, что он видит ваши новые правила.

Частая ошибка – несовпадение имени хоста. Сервис в Kubernetes может называться catalog-svc, а в VirtualService вы указали catalog-service. Istio не сможет сопоставить правило.

Выбор стратегии: весовая маршрутизация vs. маршрутизация по заголовкам

Выбор между этими подходами зависит от цели.

Весовая маршрутизация (Canary) идеальна для плавного, поэтапного rollout новой версии приложения для всех пользователей. Она проста в настройке и не требует изменений на стороне клиента. Ее недостаток – отсутствие селективности: вы не можете направить новую версию только на сотрудников или пользователей из определенного региона.

Маршрутизация по HTTP-заголовкам (A/B-тестирование) позволяет тестировать изменения на строго определенных сегментах трафика. Это основа для feature flags (флагов функций). Для ее работы клиентское приложение или ingress-контроллер должны добавлять соответствующие заголовки в запрос. Этот подход часто используется вместе с весовой маршрутизацией: сначала новую версию тестирует внутренняя аудитория (по заголовку), затем она постепенно открывается для небольшого процента всех пользователей (по весу), и далее процент увеличивается.

Для управления входящим HTTP/HTTPS-трафиком и добавления необходимых заголовков вам потребуется правильно настроенный Ingress. Детали этого процесса описаны в практическом руководстве по настройке Service и Ingress в Kubernetes.

Использование сервисной сетки, такой как Istio, для управления трафиком – это естественная эволюция от базовых механизмов Kubernetes. Чтобы понять полный контекст и альтернативы, изучите обзор управления и маршрутизации сетевого трафика в Kubernetes.

Поделиться:
Сохранить гайд? В закладки браузера