Управление трафиком в сервисной сетке Istio строится на двух ключевых ресурсах: VirtualService и DestinationRule. VirtualService определяет, куда и по каким правилам направлять входящие запросы. DestinationRule задает политики балансировки нагрузки и отказоустойчивости для конечных подов. Без понимания их совместной работы попытки внедрить canary-развертывания или A/B-тесты приводят к ошибкам и неработающим конфигурациям.
Эта статья предоставляет готовые, проверенные на практике YAML-манифесты для распространенных сценариев: плавного переноса трафика на новую версию, тестирования функций на определенных группах пользователей и повышения устойчивости продакшен-сервисов. Каждый пример сопровождается пояснением логики и командами для немедленного применения.
VirtualService и DestinationRule: как они работают вместе
Обработка запроса в Istio следует четкой последовательности. VirtualService действует как диспетчер, решающий, куда направить трафик. DestinationRule выступает как набор правил для конечного отрезка пути, определяя, как распределить нагрузку между подами и как реагировать на их сбои.
Последовательность такова:
- Запрос поступает в sidecar-прокси Envoy.
- Envoy проверяет конфигурацию VirtualService для целевого хоста. Он определяет, соответствует ли запрос условиям (match), например, наличию заголовка или определенному URI, и выбирает конечный subset с указанным весом (weight).
- После определения целевого хоста и 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.
Что делать, если трафик не идет по новому правилу?
Следуйте этому чек-листу:
- Проверьте namespace. VirtualService и DestinationRule должны быть применены в том же namespace, что и целевой сервис, либо в
spec.hostsдолжен быть указан полный FQDN (например,catalog-service.my-namespace.svc.cluster.local). - Сравните имена хостов. Поле
spec.hostsв VirtualService иspec.hostв DestinationRule должны точно соответствовать имени сервиса Kubernetes, на который вы хотите направить трафик. - Убедитесь в существовании subset. Лейблы, указанные в
subsetsDestinationRule (например,version: v2), должны присутствовать на целевых подах сервиса. Проверьте командойkubectl get pods -l version=v2. - Используйте команды отладки. Выполните
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.