Веб-интерфейсы, связанные с модулем: istio

На данный момент поддерживаются следующие версии Istio:

  • 1.12 (устарела, скоро будет снята с поддержки);
  • 1.13 (устарела, скоро будет снята с поддержки);
  • 1.16 (устарела, скоро будет снята с поддержки);
  • 1.19

Задачи, которые решает Istio

Istio — фреймворк централизованного управления сетевым трафиком, реализующий подход Service Mesh.

В частности, Istio прозрачно решает для приложений следующие задачи:

Рекомендуем ознакомиться с видео, где мы обсуждаем архитектуру Istio и оцениваем накладные расходы.

Mutual TLS

Данный механизм — это главный метод взаимной аутентификации сервисов. Принцип основывается на том, что при всех исходящих запросах проверяется серверный сертификат, а при входящих — клиентский. После проверок sidecar-proxy получает возможность идентифицировать удаленный узел и использовать эти данные для авторизации либо в прикладных целях.

Каждый сервис получает собственный идентификатор в формате <TrustDomain>/ns/<Namespace>/sa/<ServiceAccount>, где TrustDomain в нашем случае — это домен кластера. Каждому сервису можно выделять собственный ServiceAccount или использовать стандартный «default». Полученный идентификатор сервиса можно использовать как в правилах авторизации, так и в прикладных целях. Именно этот идентификатор используется в качестве удостоверяемого имени в TLS-сертификатах.

Данные настройки можно переопределить на уровне namespace.

Авторизация

Управление авторизацией осуществляется с помощью ресурса AuthorizationPolicy. В момент, когда для сервиса создается этот ресурс, начинает работать следующий алгоритм принятия решения о судьбе запроса:

  • Если запрос попадает под политику DENY — запретить запрос.
  • Если для данного сервиса нет политик ALLOW — разрешить запрос.
  • Если запрос попадает под политику ALLOW — разрешить запрос.
  • Все остальные запросы — запретить.

Иными словами, если явно что-то запретить, работает только запрет. Если же что-то явно разрешить, будут разрешены только явно одобренные запросы (запреты при этом имеют приоритет).

Для написания правил авторизации можно использовать следующие аргументы:

  • идентификаторы сервисов и wildcard на их основе (mycluster.local/ns/myns/sa/myapp или mycluster.local/*);
  • namespace;
  • диапазоны IP;
  • HTTP-заголовки;
  • JWT-токены из прикладных запросов.

Маршрутизация запросов

Основной ресурс для управления маршрутизацией — VirtualService, он позволяет переопределять судьбу HTTP- или TCP-запроса. Доступные аргументы для принятия решения о маршрутизации:

  • Host и любые другие заголовки;
  • URI;
  • метод (GET, POST и пр.);
  • лейблы пода или namespace источника запросов;
  • dst-IP или dst-порт для не-HTTP-запросов.

Управление балансировкой запросов между endpoint’ами сервиса

Основной ресурс для управления балансировкой запросов — DestinationRule, он позволяет настроить нюансы исходящих из подов запросов:

  • лимиты/таймауты для TCP;
  • алгоритмы балансировки между endpoint’ами;
  • правила определения проблем на стороне endpoint’а для выведения его из балансировки;
  • нюансы шифрования.

Важно! Все настраиваемые лимиты работают для каждого пода клиента по отдельности! Если настроить для сервиса ограничение на одно TCP-соединение, а клиентских подов — три, то сервис получит три входящих соединения.

Observability

Трассировка

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

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

Grafana

В стандартной комплектации с модулем предоставлены дополнительные доски:

  • доска для оценки производительности и успешности запросов/ответов между приложениями;
  • доска для оценки работоспособности и нагрузки на control plane.

Kiali

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

Архитектура кластера с включенным Istio

Компоненты кластера делятся на две категории:

  • control plane — управляющие и обслуживающие сервисы. Под control plane обычно подразумевают поды istiod.
  • data plane — прикладная часть Istio. Представляет собой контейнеры sidecar-proxy.

Архитектура кластера с включенным Istio

Все сервисы из data plane группируются в mesh. Его характеристики:

  • Общее пространство имен для генерации идентификатора сервиса в формате <TrustDomain>/ns/<Namespace>/sa/<ServiceAccount>. Каждый mesh имеет идентификатор TrustDomain, который в нашем случае совпадает с доменом кластера. Например: mycluster.local/ns/myns/sa/myapp.
  • Сервисы в рамках одного mesh имеют возможность аутентифицировать друг друга с помощью доверенных корневых сертификатов.

Элементы control plane:

  • istiod — ключевой сервис, обеспечивающий решение следующих задач:
    • Непрерывная связь с API Kubernetes и сбор информации о прикладных сервисах.
    • Обработка и валидация с помощью механизма Kubernetes Validating Webhook всех Custom Resources, которые связаны с Istio.
    • Компоновка конфигурации для каждого sidecar-proxy индивидуально:
      • генерация правил авторизации, маршрутизации, балансировки и пр.;
      • распространение информации о других прикладных сервисах в кластере;
      • выпуск индивидуальных клиентских сертификатов для организации схемы Mutual TLS. Эти сертификаты не связаны с сертификатами, которые использует и контролирует сам Kubernetes для своих служебных нужд.
    • Автоматическая подстройка манифестов, определяющих прикладные поды через механизм Kubernetes Mutating Webhook:
      • внедрение дополнительного служебного контейнера sidecar-proxy;
      • внедрение дополнительного init-контейнера для адаптации сетевой подсистемы (настройка DNAT для перехвата прикладного трафика);
      • перенаправление readiness- и liveness-проб через sidecar-proxy.
  • operator — компонент, отвечающий за установку всех ресурсов, необходимых для работы control plane определенной версии.
  • kiali — панель управления и наблюдения за ресурсами Istio и пользовательскими сервисами под управлением Istio, позволяющая следующее:
    • Визуализировать связи между сервисами.
    • Диагностировать проблемные связи между сервисами.
    • Диагностировать состояние control plane.

Для приема пользовательского трафика требуется доработка Ingress-контроллера:

  • К подам контроллера добавляется sidecar-proxy, который обслуживает только трафик от контроллера в сторону прикладных сервисов (параметр IngressNginxController enableIstioSidecar у ресурса IngressNginxController).
  • Сервисы не под управлением Istio продолжают работать как раньше, запросы в их сторону не перехватываются сайдкаром контроллера.
  • Запросы в сторону сервисов под управлением Istio перехватываются сайдкаром и обрабатываются в соответствии с правилами Istio (подробнее о том, как активировать Istio для приложения).

Контроллер istiod и каждый контейнер sidecar-proxy экспортируют собственные метрики, которые собирает кластерный Prometheus.

Архитектура прикладного сервиса с включенным Istio

Особенности

  • Каждый под сервиса получает дополнительный контейнер — sidecar-proxy. Технически этот контейнер содержит два приложения:
    • Envoy — проксирует прикладной трафик и реализует весь функционал, который предоставляет Istio, включая маршрутизацию, аутентификацию, авторизацию и пр.
    • pilot-agent — часть Istio, отвечает за поддержание конфигурации Envoy в актуальном состоянии, а также содержит в себе кэширующий DNS-сервер.
  • В каждом поде настраивается DNAT входящих и исходящих прикладных запросов в sidecar-proxy. Делается это с помощью дополнительного init-контейнера. Таким образом, трафик будет перехватываться прозрачно для приложений.
  • Так как входящий прикладной трафик перенаправляется в sidecar-proxy, readiness/liveness-трафика это тоже касается. Подсистема Kubernetes, которая за это отвечает, не рассчитана на формирование проб в формате Mutual TLS. Для адаптации все существующие пробы автоматически перенастраиваются на специальный порт в sidecar-proxy, который перенаправляет трафик на приложение в неизменном виде.
  • Для приема запросов извне кластера необходимо использовать подготовленный Ingress-контроллер:
    • Поды контроллера аналогично имеют дополнительный контейнер sidecar-proxy.
    • В отличие от подов приложения, sidecar-proxy Ingress-контроллера перехватывает только трафик от контроллера к сервисам. Входящий трафик от пользователей обрабатывает непосредственно сам контроллер.
  • Ресурсы типа Ingress требуют минимальной доработки в виде добавления аннотаций:
    • nginx.ingress.kubernetes.io/service-upstream: "true" — Ingress-контроллер в качестве upstream будет использовать ClusterIP сервиса вместо адресов подов. Балансировкой трафика между подами теперь занимается sidecar-proxy. Используйте эту опцию, только если у вашего сервиса есть ClusterIP.
    • nginx.ingress.kubernetes.io/upstream-vhost: "myservice.myns.svc" — sidecar-proxy Ingress-контроллера принимает решения о маршрутизации на основе заголовка Host. Без данной аннотации контроллер оставит заголовок с адресом сайта, например Host: example.com.
  • Ресурсы типа Service не требуют адаптации и продолжают выполнять свою функцию. Приложениям все так же доступны адреса сервисов вида servicename, servicename.myns.svc и пр.
  • DNS-запросы изнутри подов прозрачно перенаправляются на обработку в sidecar-proxy:
    • Требуется для разыменования DNS-имен сервисов из соседних кластеров.

Жизненный цикл пользовательского запроса

Приложение с выключенным Istio

Приложение с включенным Istio

Как активировать Istio для приложения

Основная цель активации — добавить sidecar-контейнер к подам приложения, после чего Istio сможет управлять трафиком.

Рекомендованный способ добавления sidecar-ов — использовать sidecar-injector. Istio умеет «подселять» к вашим подам sidecar-контейнер с помощью механизма Admission Webhook. Настраивается с помощью лейблов и аннотаций:

В Deckhouse версии >= 1.55 модуль admission-policy-engine по умолчанию работает в режиме Baseline. Если его включить, init-контейнеры Istio не могут добавить необходимые правила для перехвата прикладного трафика и Поды не могут запуститься. Решение — либо поменять политику по умолчанию на Restricted, либо выставить эту политику для отдельного приложения с помощью лейбла security.deckhouse.io/pod-policy=privileged на прикладной Namespace.

  • Лейбл к namespace — обращает внимание sidecar-injector’а на ваш namespace, после установки лейбла к новым подам будут подселяться sidecar’ы:
    • istio-injection=enabled — использовать самую свежую установленную версию Istio;
    • istio.io/rev=v1x16 — использовать конкретную версию Istio для данного namespace.
  • Аннотация к поду sidecar.istio.io/inject ("true" или "false") позволяет локально переопределить политику sidecarInjectorPolicy. Эти аннотации работают только в namespace, обозначенных лейблами из списка выше.

Также существует возможность добавить sidecar к индивидуальному поду в namespace без установленных лейблов istio-injection=enabled или istio.io/rev=vXxYZ путем установки лейбла sidecar.istio.io/inject=true.

Важно! Istio-proxy, который работает в качестве sidecar-контейнера, тоже потребляет ресурсы и добавляет накладные расходы:

  • Каждый запрос DNAT’ится в Envoy, который обрабатывает это запрос и создает еще один. На принимающей стороне — аналогично.
  • Каждый Envoy хранит информацию обо всех сервисах в кластере, что требует памяти. Больше кластер — больше памяти потребляет Envoy. Решение — CustomResource Sidecar.

Также важно подготовить Ingress-контроллер и Ingress-ресурсы приложения:

  • Включить enableIstioSidecar у ресурса IngressNginxController.
  • Добавить аннотации на Ingress-ресурсы приложения:
    • nginx.ingress.kubernetes.io/service-upstream: "true" — Ingress-контроллер в качестве upstream будет использовать ClusterIP сервиса вместо адресов подов. Балансировкой трафика между подами теперь занимается sidecar-proxy. Используйте эту опцию, только если у вашего сервиса есть ClusterIP;
    • nginx.ingress.kubernetes.io/upstream-vhost: "myservice.myns.svc" — sidecar-proxy Ingress-контроллера принимает решения о маршрутизации на основе заголовка Host. Без данной аннотации контроллер оставит заголовок с адресом сайта, например Host: example.com.

Федерация и мультикластер

Доступно только в редакции Enterprise Edition.

Поддерживаются две схемы межкластерного взаимодействия:

Принципиальные отличия:

  • Федерация объединяет суверенные кластеры:
    • у каждого кластера собственное пространство имен (для namespace, Service и пр.);
    • доступ к отдельным сервисам между кластерами явно обозначен.
  • Мультикластер объединяет созависимые кластеры:
    • пространство имен у кластеров общее — каждый сервис доступен для соседних кластеров так, словно он работает на локальном кластере (если это не запрещают правила авторизации).

Федерация

Требования к кластерам

  • У каждого кластера должен быть уникальный домен в параметре clusterDomain ресурса ClusterConfiguration. По умолчанию значение параметра — cluster.local.
  • Подсети подов и сервисов в параметрах podSubnetCIDR и serviceSubnetCIDR ресурса ClusterConfiguration не должны быть уникальными.

Общие принципы федерации

  • Федерация требует установления взаимного доверия между кластерами. Соответственно, для установления федерации нужно в кластере A сделать кластер Б доверенным и аналогично в кластере Б сделать кластер А доверенным. Технически это достигается взаимным обменом корневыми сертификатами.
  • Для прикладной эксплуатации федерации необходимо также обменяться информацией о публичных сервисах. Чтобы опубликовать сервис bar из кластера Б в кластере А, необходимо в кластере А создать ресурс ServiceEntry, который описывает публичный адрес ingress-gateway кластера Б.

Включение федерации

При включении федерации (параметр модуля istio.federation.enabled = true) происходит следующее:

  • В кластер добавляется сервис ingressgateway, чья задача — проксировать mTLS-трафик извне кластера на прикладные сервисы.
  • В кластер добавляется сервис, который экспортит метаданные кластера наружу:
    • корневой сертификат Istio (доступен без аутентификации);
    • список публичных сервисов в кластере (доступен только для аутентифицированных запросов из соседних кластеров);
    • список публичных адресов сервиса ingressgateway (доступен только для аутентифицированных запросов из соседних кластеров).

Управление федерацией

Для построения федерации необходимо сделать следующее:

  • В каждом кластере создать набор ресурсов IstioFederation, которые описывают все остальные кластеры.
    • После успешного автосогласования между кластерами, в ресурсе IstioFederation заполнятся разделы status.metadataCache.public и status.metadataCache.private служебными данными, необходимыми для работы федерации.
  • Каждый ресурс(service), который считается публичным в рамках федерации, пометить лейблом federation.istio.deckhouse.io/public-service=.
    • В кластерах из состава федерации, для каждого service создадутся соответствующие ServiceEntry, ведущие на ingressgateway оригинального кластера.

Важно чтобы в этих service, в разделе .spec.ports у каждого порта обязательно было заполнено поле name.

Мультикластер

Требования к кластерам

  • Домены кластеров в параметре clusterDomain ресурса ClusterConfiguration должны быть одинаковыми для всех членов мультикластера. По умолчанию значение параметра — cluster.local.
  • Подсети подов и сервисов в параметрах podSubnetCIDR и serviceSubnetCIDR ресурса ClusterConfiguration должны быть уникальными для каждого члена мультикластера.

Общие принципы

  • Мультикластер требует установления взаимного доверия между кластерами. Соответственно, для построения мультикластера нужно в кластере A сделать кластер Б доверенным и в кластере Б сделать кластер А доверенным. Технически это достигается взаимным обменом корневыми сертификатами.
  • Для сбора информации о соседних сервисах Istio подключается напрямую к API-серверу соседнего кластера. Данный модуль Deckhouse берет на себя организацию соответствующего канала связи.

Включение мультикластера

При включении мультикластера (параметр модуля istio.multicluster.enabled = true) происходит следующее:

  • В кластер добавляется прокси для публикации доступа к API-серверу посредством стандартного Ingress-ресурса:
    • Доступ через данный публичный адрес ограничен авторизацией на основе Bearer-токенов, подписанных доверенными ключами. Обмен доверенными публичными ключами происходит автоматически средствами Deckhouse при взаимной настройке мультикластера.
    • Непосредственно прокси имеет read-only-доступ к ограниченному набору ресурсов.
  • В кластер добавляется сервис, который экспортит метаданные кластера наружу:
    • Корневой сертификат Istio (доступен без аутентификации).
    • Публичный адрес, через который доступен API-сервер (доступен только для аутентифицированных запросов из соседних кластеров).
    • Список публичных адресов сервиса ingressgateway (доступен только для аутентифицированных запросов из соседних кластеров).
    • Публичные ключи сервера для аутентификации запросов к API-серверу и закрытым метаданным (см. выше).

Управление мультикластером

Для сборки мультикластера необходимо в каждом кластере создать набор ресурсов IstioMulticluster, которые описывают все остальные кластеры.

Накладные расходы

Примерная оценка накладных расходов при использовании Istio. Для ограничения потребления ресурсов путем ограничения поля видимости sidecar возможно использование ресурса Sidecar.