1. Введение
В этом руководстве мы рассмотрим основы архитектуры сервисной сетки и поймем, как она дополняет архитектуру распределенной системы.
В первую очередь мы сосредоточимся на Istio, который является реализацией сервисной сетки. В процессе мы рассмотрим базовую архитектуру Istio и поймем, как извлечь из нее пользу в Kubernetes.
2. Что такое сервисная сетка?
За последние пару десятилетий мы видели, как монолитные приложения начали распадаться на более мелкие приложения. Он обрел беспрецедентную популярность благодаря облачным вычислениям и архитектуре микросервисов . Кроме того, в этом отношении только помогли технологии контейнеризации, такие как Docker , и системы оркестрации, такие как Kubernetes .
Несмотря на ряд преимуществ внедрения микросервисной архитектуры в распределенной системе, такой как Kubernetes, она имеет свою долю сложностей . Поскольку распределенные службы должны взаимодействовать друг с другом, мы должны думать об обнаружении, маршрутизации, повторных попытках и отказоустойчивости.
Есть несколько других проблем, таких как безопасность и наблюдаемость, о которых мы также должны позаботиться:
Теперь создание этих коммуникационных возможностей в каждой службе может быть довольно утомительным — тем более, когда ландшафт службы растет и связь становится сложной. Именно в этом нам может помочь сервисная сетка. По сути, сервисная сетка снимает с себя ответственность за управление всеми коммуникациями между сервисами в рамках распределенной программной системы.
Сервисная сетка способна сделать это через массив сетевых прокси. По сути, запросы между службами направляются через прокси-серверы, которые работают вместе со службами, но находятся вне уровня инфраструктуры:
Эти прокси в основном создают ячеистую сеть для сервисов — отсюда и название сервисная сетка! С помощью этих прокси сервисная сеть может контролировать каждый аспект связи между сервисами. Таким образом, мы можем использовать его для устранения восьми ошибок распределенных вычислений , набора утверждений, описывающих ложные предположения, которые мы часто делаем о распределенных приложениях.
3. Особенности сервисной сетки
Давайте теперь разберемся с некоторыми функциями, которые может предоставить нам сервисная сетка. Обратите внимание, что список фактических функций зависит от реализации сервисной сетки. Но, в целом, следует ожидать большинства этих возможностей во всех реализациях.
Мы можем разделить эти функции на три категории: управление трафиком, безопасность и наблюдаемость.
3.1. Управление движением
Одной из фундаментальных особенностей сервисной сетки является управление трафиком. Это включает в себя динамическое обнаружение служб и маршрутизацию. Это также позволяет использовать некоторые интересные варианты использования, такие как теневое копирование и разделение трафика . Они очень полезны для выполнения канареечных выпусков и A/B-тестирования.
Поскольку вся связь между службами обрабатывается сеткой служб, она также обеспечивает некоторые функции обеспечения надежности . Например, сервисная сетка может обеспечивать повторные попытки, тайм-ауты, ограничение скорости и автоматические выключатели. Эти встроенные функции восстановления после сбоев делают связь более надежной.
3.2. Безопасность
Сервисная сетка обычно также обрабатывает аспекты безопасности связи между сервисами . Это включает принудительное шифрование трафика с помощью взаимного TLS (MTLS), обеспечение аутентификации с помощью проверки сертификата и обеспечение авторизации с помощью политик доступа.
Также могут быть интересные варианты использования безопасности в сервисной сетке. Например, мы можем достичь сегментации сети, позволяя одним службам обмениваться данными и запрещая другим. Более того, сервисная сетка может предоставить точную историческую информацию для требований аудита.
3.3. Наблюдаемость
Надежная наблюдаемость является основным требованием для обработки сложной распределенной системы. Поскольку сервисная сетка обрабатывает всю коммуникацию, она правильно подходит для обеспечения функций наблюдения. Например, он может предоставить информацию о распределенной трассировке.
Сервисная сетка может генерировать множество показателей, таких как задержка, трафик, ошибки и насыщенность . Более того, сервисная сетка также может генерировать журналы доступа, предоставляя полную запись для каждого запроса. Они весьма полезны для понимания поведения отдельных служб, а также всей системы.
4. Введение в Istio
Istio — это реализация Service Mesh с открытым исходным кодом, первоначально разработанная IBM, Google и Lyft. Он может прозрачно накладываться на распределенное приложение и обеспечивать все преимущества сервисной сетки, такие как управление трафиком, безопасность и наблюдаемость.
Он предназначен для работы с различными развертываниями, такими как локальные, размещенные в облаке, в контейнерах Kubernetes и в сервисерах, работающих на виртуальных машинах. Хотя Istio не зависит от платформы , он довольно часто используется вместе с микросервисами, развернутыми на платформе Kubernetes.
По сути, Istio работает, развертывая расширенную версию Envoy в качестве прокси для каждого микросервиса в качестве sidecar:
Эта сеть прокси представляет собой уровень данных архитектуры Istio. Конфигурация и управление этими прокси выполняются из плоскости управления:
Плоскость управления — это, по сути, мозг сервисной сетки . Он обеспечивает обнаружение, настройку и управление сертификатами для прокси-серверов Envoy в плоскости данных во время выполнения.
Конечно, мы сможем осознать преимущества Istio только тогда, когда у нас будет большое количество микросервисов, взаимодействующих друг с другом. Здесь прокси-серверы sidecar образуют сложную сервисную сетку на выделенном уровне инфраструктуры:
Istio достаточно гибок в плане интеграции с внешними библиотеками и платформами. Например, мы можем интегрировать Istio с внешней платформой ведения журналов, телеметрией или системой политик.
5. Понимание компонентов Istio
Мы видели, что архитектура Istio состоит из плоскости данных и плоскости управления. Кроме того, есть несколько основных компонентов, обеспечивающих работу Istio.
В этом разделе мы подробно рассмотрим эти основные компоненты.
5.1. Плоскость данных
Плоскость данных Istio в основном состоит из расширенной версии прокси-сервера Envoy . Envoy — это пограничный и сервисный прокси с открытым исходным кодом, который помогает отделить сетевые проблемы от базовых приложений. Приложения просто отправляют и получают сообщения на localhost
и обратно , не зная топологии сети.
По своей сути Envoy — это сетевой прокси, работающий на уровнях L3 и L4 модели OSI . Он работает, используя цепочку подключаемых сетевых фильтров для обработки соединений. Кроме того, Envoy поддерживает дополнительный фильтр уровня L7 для HTTP-трафика. Более того, Envoy имеет первоклассную поддержку транспорта HTTP/2 и gRPC.
Многие из функций, которые Istio предоставляет в качестве сервисной сетки, на самом деле активируются базовыми встроенными функциями прокси-серверов Envoy:
- Управление трафиком: Envoy позволяет применять детальное управление трафиком с богатыми правилами маршрутизации для трафика HTTP, gRPC, WebSocket и TCP.
- Отказоустойчивость сети: Envoy включает встроенную поддержку автоматических повторных попыток, разрыва цепи и внедрения ошибок.
- Безопасность: Envoy также может применять политики безопасности и применять контроль доступа и ограничение скорости при обмене данными между базовыми службами.
Еще одна причина, по которой Envoy так хорошо работает с Istio, — его расширяемость. Envoy предоставляет подключаемую модель расширения на основе WebAssembly . Это весьма полезно при применении пользовательских политик и создании телеметрии. Кроме того, мы также можем расширить прокси-сервер Envoy в Istio, используя расширения Istio, основанные на API песочницы Proxy-Wasm.
5.2. Плоскость управления
Как мы видели ранее, плоскость управления отвечает за управление и настройку прокси-серверов Envoy в плоскости данных. В плоскости управления за это отвечает компонент istiod
. Здесь istiod
отвечает за преобразование высокоуровневых правил маршрутизации и поведения управления трафиком в специфичные для Envoy конфигурации и распространение их на sidecars во время выполнения.
Если мы вспомним архитектуру плоскости управления Istio из прошлого, то заметим, что раньше она представляла собой набор независимых компонентов, работающих вместе. Он включает в себя такие компоненты, как Pilot для обнаружения служб, Galley для настройки, Citadel для создания сертификатов и Mixer для расширения. Из-за сложности эти отдельные компоненты были объединены в один компонент под названием istiod
.
По сути, istiod
по-прежнему использует тот же код и API, что и отдельные компоненты ранее. Например, Pilot отвечает за абстрагирование механизмов обнаружения сервисов для конкретных платформ и их синтез в стандартном формате, который могут использовать сайдкары. Следовательно, Istio может поддерживать обнаружение для нескольких сред, таких как Kubernetes или виртуальные машины.
Кроме того, istiod
также обеспечивает безопасность, обеспечивая надежную аутентификацию между службами и конечными пользователями со встроенным управлением идентификацией и учетными данными. Более того, с помощью istiod
мы можем применять политики безопасности на основе идентификации службы. Процесс istiod
также действует как центр сертификации (CA) и генерирует сертификаты для облегчения взаимного обмена данными TLS (MTLS) в плоскости данных.
6. Как работает Istio
Мы узнали, каковы типичные особенности сервисной сетки. Кроме того, мы рассмотрели основы архитектуры Istio и ее основные компоненты. Теперь пришло время понять, как Istio обеспечивает эти функции с помощью основных компонентов своей архитектуры.
Мы сосредоточимся на тех же категориях функций, которые мы рассмотрели ранее.
6.1. Управление движением
Мы можем осуществлять детальный контроль над трафиком в сервисной сетке с помощью API управления трафиком Istio. Мы можем использовать эти API для добавления собственных конфигураций трафика в Istio. Кроме того, мы можем определить ресурсы API, используя определения пользовательских ресурсов (CRD) Kubernetes. Ключевыми ресурсами API, которые помогают нам контролировать маршрутизацию трафика, являются виртуальные сервисы и правила назначения:
По сути, виртуальный сервис позволяет нам настроить маршрутизацию запросов к сервису в сервисной сетке Istio. Следовательно, виртуальная служба состоит из одного или нескольких правил маршрутизации, которые оцениваются по порядку. После оценки правил маршрутизации виртуальной службы применяются правила назначения. Правила назначения помогают нам контролировать трафик к месту назначения — например, группируя экземпляры службы по версии.
6.2. Безопасность
Безопасность в Istio начинается с предоставления надежных идентификаторов для каждой службы. Агенты Istio, работающие вместе с каждым прокси-сервером Envoy, работают с istiod
для автоматизации смены ключей и сертификатов:
Istio предоставляет два типа аутентификации — одноранговую аутентификацию и аутентификацию по запросу . Одноранговая аутентификация используется для аутентификации между сервисами, где Istio предлагает взаимный TLS в качестве решения с полным стеком. Проверка подлинности запроса используется для проверки подлинности конечного пользователя, когда Istio предлагает проверку веб-токена JSON (JWT) с использованием специального поставщика проверки подлинности или поставщика OpenID Connect (OIDC).
Istio также позволяет нам принудительно контролировать доступ к сервисам, просто применяя к ним политику авторизации. Политика авторизации обеспечивает контроль доступа к входящему трафику в прокси-сервере Envoy. Благодаря этому мы можем применять контроль доступа на различных уровнях: сетке, пространстве имен и сервисе.
6.3. Наблюдаемость
Istio генерирует подробную телеметрию, такую как метрики, распределенные трассировки и журналы доступа для всех взаимодействий служб в сети. Istio генерирует широкий набор метрик уровня прокси, сервис-ориентированных метрик и метрик плоскости управления .
Ранее архитектура телеметрии Istio включала Mixer в качестве центрального компонента. Но, начиная с Telemetry v2, функции, предоставляемые Mixer, были заменены прокси-плагинами Envoy:
Более того, Istio генерирует распределенные трассировки через прокси Envoy. Istio поддерживает ряд трассировочных серверов, таких как Zipkin , Jaeger , Lightstep и Datadog . Мы также можем контролировать частоту дискретизации для генерации трассировки. Кроме того, Istio также создает журналы доступа для служебного трафика в настраиваемых форматах.
7. Практические занятия с Istio
Теперь, когда мы прошли достаточное количество предыстории, мы готовы увидеть Istio в действии. Для начала мы установим Istio в кластере Kubernetes. Далее мы будем использовать простое приложение на основе микросервисов, чтобы продемонстрировать возможности Istio в Kubernetes.
7.1. Монтаж
Существует несколько способов установки Istio, но самый простой из них — загрузить и извлечь последнюю версию для конкретной ОС, например Windows. Извлеченный пакет содержит двоичный файл клиента istioctl в каталоге
bin
. Мы можем использовать istioctl
для установки Istio в целевом кластере Kubernetes:
istioctl install --set profile=demo -y
При этом компоненты Istio устанавливаются в кластере Kubernetes по умолчанию с демонстрационным профилем. Мы также можем использовать любой другой профиль поставщика вместо демо.
Наконец, нам нужно указать Istio автоматически внедрять прокси-сервер Envoy sidecar , когда мы развертываем любое приложение в этом кластере Kubernetes:
kubectl label namespace default istio-injection=enabled
Здесь мы используем kubectl
, предполагая, что кластер Kubernetes, такой как Minikube, и Kubernetes CLI kubectl
уже доступны на нашей машине.
7.2. Образец заявления
В целях демонстрации мы представим очень простое приложение для размещения онлайн-заказов. Это приложение состоит из трех микросервисов, которые взаимодействуют друг с другом для выполнения запроса конечного пользователя на заказ:
Мы не будем вдаваться в подробности этих микросервисов, но их довольно просто создать с помощью Spring Boot и REST API . Самое главное, мы создаем образ Docker для этих микросервисов , чтобы мы могли развернуть их в Kubernetes.
7.3. Развертывание
Развернуть контейнерную рабочую нагрузку в кластере Kubernetes, таком как Minikube , довольно просто. Мы будем использовать типы ресурсов Deployment
и Service для объявления рабочей нагрузки и доступа к ней.
Обычно мы определяем их в файле YAML:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: order-service
namespace: default
spec:
replicas: 1
template:
metadata:
labels:
app: order-service
version: v1
spec:
containers:
- name: order-service
image: kchandrakant/order-service:v1
resources:
requests:
cpu: 0.1
memory: 200
---
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: order-service
Это очень простое определение Развертывания
и Сервиса
для заказа-сервиса
. Точно так же мы можем определить файл YAML для службы инвентаризации
и службы доставки
.
Развернуть эти ресурсы с помощью kubectl
также довольно просто:
kubectl apply -f booking-service.yaml -f inventory-service.yaml -f shipping-service.yaml
Поскольку мы включили автоматическое внедрение прокси-серверов Envoy для пространства имен по умолчанию, обо всем позаботятся за нас. Кроме того, мы можем использовать команду istioctl kube -
inject
для ручного внедрения прокси-сервера Envoy.
7.4. Доступ к приложению
Теперь Istio в первую очередь отвечает за обработку всего сетевого трафика. Следовательно, любой трафик в сеть или из нее по умолчанию запрещен . Istio использует шлюзы для управления входящим и исходящим трафиком из сетки. Таким образом, мы можем точно контролировать трафик, который входит или выходит из сетки. Istio предоставляет несколько предварительно настроенных развертываний прокси-сервера шлюза: istio-ingressgateway
и istio-egressgateway
.
Мы создадим шлюз и виртуальную службу для нашего приложения, чтобы это произошло:
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: booking-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: booking
spec:
hosts:
- "*"
gateways:
- booking-gateway
http:
- match:
- uri:
prefix: /api/v1/booking
route:
- destination:
host: booking-service
port:
number: 8080
Здесь мы используем контроллер входящего трафика по умолчанию, предоставляемый Istio. Кроме того, мы определили виртуальный сервис для направления наших запросов в службу бронирования
.
Точно так же мы также можем определить выходной шлюз для исходящего трафика из сетки.
8. Распространенные варианты использования Istio
Теперь мы увидели, как развернуть простое приложение в Kubernetes с помощью Istio. Но мы по-прежнему не используем ни одну интересную функцию, которую дает нам Istio. В этом разделе мы рассмотрим некоторые распространенные варианты использования сервисной сетки и поймем, как использовать Istio для их реализации в нашем простом приложении.
8.1. Маршрутизация запроса
Есть несколько причин, по которым мы можем захотеть обрабатывать маршрутизацию запросов определенным образом. Например, мы можем развернуть несколько версий микросервиса, такого как служба доставки,
и хотим направить только небольшой процент запросов в новую версию.
Для этого мы можем использовать правила маршрутизации виртуального сервиса:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: shipping-service
spec:
hosts:
- shipping-service
http:
- route:
- destination:
host: shipping-service
subset: v1
weight: 90
- destination:
host: shipping-service
subset: v2
weight: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: shipping-service
spec:
host: shipping-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Правила маршрутизации также позволяют нам определять условия соответствия на основе таких атрибутов, как параметр заголовка. Кроме того, поле назначения указывает фактическое место назначения для трафика, соответствующего условию.
8.2. Размыкание цепи
Прерыватель цепи — это в основном шаблон проектирования программного обеспечения для обнаружения сбоев и инкапсуляции логики предотвращения дальнейшего каскадного сбоя . Это помогает создавать устойчивые микросервисные приложения, которые ограничивают влияние сбоев и пиковых задержек.
В Istio мы можем использовать конфигурацию trafficPolicy в DestinationRule
,
чтобы применить разрыв цепи при вызове службы, такой как inventory-service
:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: inventory-service
spec:
host: inventory-service
trafficPolicy:
connectionPool:
tcp:
maxConnections: 1
http:
http1MaxPendingRequests: 1
maxRequestsPerConnection: 1
outlierDetection:
consecutive5xxErrors: 1
interval: 1s
baseEjectionTime: 3m
maxEjectionPercent: 100
Здесь мы настроили DestinationRule
с maxConnections равным
1, httpMaxPendingRequests равным
1 и maxRequestsPerConnection равным
1. Фактически это означает, что если мы превысим количество одновременных запросов более чем на 1, прерыватель цепи начнет перехватывать некоторые запросы. .
8.3. Включение взаимного TLS
Взаимная аутентификация относится к ситуации, когда две стороны одновременно аутентифицируют друг друга в протоколе аутентификации, таком как TLS . По умолчанию весь трафик между сервисами с прокси использует взаимный TLS в Istio. Однако сервисы без прокси продолжают получать трафик в виде обычного текста.
Хотя Istio автоматически переводит весь трафик между сервисами с прокси-серверами на взаимный TLS, эти сервисы по-прежнему могут получать обычный текстовый трафик. У нас есть возможность применить взаимный TLS для всей сетки с помощью политики PeerAuthentication
:
apiVersion: "security.istio.io/v1beta1"
kind: "PeerAuthentication"
metadata:
name: "default"
namespace: "istio-system"
spec:
mtls:
mode: STRICT
У нас также есть варианты принудительного применения взаимного TLS для каждого пространства имен или службы, а не для всей сети. Однако политика PeerAuthentication
для конкретной `` службы имеет приоритет над политикой для всего пространства имен .
8.4. Контроль доступа с помощью JWT
JSON Web Token (JWT) — это стандарт для создания данных, полезная нагрузка которых содержит JSON, подтверждающий ряд утверждений . Это стало широко применяться для передачи удостоверений и стандартных или настраиваемых утверждений аутентифицированных пользователей между поставщиком удостоверений и поставщиком услуг.
Мы можем включить политику авторизации в Istio, чтобы разрешить доступ к такому сервису, как booking-service
на основе JWT:
apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
name: require-jwt
namespace: default
spec:
selector:
matchLabels:
app: booking-service
action: ALLOW
rules:
- from:
- source:
requestPrincipals: ["testing@foreach.com/testing@foreach.io"]
Здесь AuthorizationPolicy
принуждает все запросы иметь действительный JWT с requestPrincipal
, установленным на определенное значение. Istio создает атрибут requestPrincipal
, объединяя утверждения iss
и sub
JWT.
9. Запоздалые мысли
Итак, мы уже видели, как сервисная сетка, такая как Istio, упрощает нашу жизнь при решении ряда общих проблем в распределенной архитектуре, такой как микросервисы. Но, несмотря ни на что, Istio — сложная система, что увеличивает сложность итогового развертывания . Как и любая другая технология, Istio не является панацеей, и ее следует использовать с должным вниманием.
9.1. Должны ли мы всегда использовать сервисную сетку?
Хотя мы видели достаточно причин для использования сервисной сетки, давайте приведем некоторые причины, которые могут побудить нас отказаться от ее использования:
- Сервисная сетка обрабатывает всю связь между сервисами за счет дополнительных затрат на развертывание и эксплуатацию сервисной сетки. Для более простых приложений это может быть неоправданным.
- Поскольку мы уже привыкли справляться с некоторыми из этих проблем, таких как разрыв цепи в коде приложения, это может привести к дублированию обработки в сервисной сетке.
- Возрастающая зависимость от внешней системы, такой как сервисная сетка, может отрицательно сказаться на переносимости приложений, особенно в связи с отсутствием отраслевых стандартов для сервисной сетки.
- Поскольку сервисная сетка обычно работает путем перехвата трафика сетки через прокси-сервер, она потенциально может добавить нежелательную задержку к запросам.
- Сервисная сетка добавляет множество дополнительных компонентов и конфигураций, требующих точной обработки; это требует опыта и увеличивает кривую обучения
- Наконец, мы можем в конечном итоге смешать операционную логику, которая должна быть в сервисной сетке, с бизнес-логикой, которой не должно быть в сервисной сетке.
Следовательно, как мы видим, история сервисной сетки не только о преимуществах, но это не значит, что они не соответствуют действительности. Для нас важно тщательно оценить наши требования и сложность нашего приложения, а затем сопоставить преимущества сервисной сетки с их дополнительной сложностью.
9.2. Какие есть альтернативы Istio?
Хотя Istio довольно популярен и поддерживается некоторыми лидерами отрасли, это, безусловно, не единственный доступный вариант. Хотя мы не можем провести здесь тщательное сравнение, давайте рассмотрим пару этих вариантов, Linkerd и Consul.
Linkerd — сервисная сетка с открытым исходным кодом, созданная для платформы Kubernetes . Он также довольно популярен и в настоящее время имеет статус инкубирующего проекта в CNCF . Его принципы работы аналогичны любой другой сервисной сетке, такой как Istio. Он также использует TCP-прокси для обработки сетевого трафика. Linkerd использует микропрокси, написанный на Rust и известный как Linkerd-proxy.
В целом Linkerd менее сложен, чем Istio, учитывая, что он поддерживает только Kubernetes. Но, кроме этого, список функций, доступных в Linkerd, очень похож на те, что доступны в Istio. Базовая архитектура Linkerd также очень похожа на архитектуру Istio . По сути, Linkerd состоит из трех основных компонентов: пользовательского интерфейса, плоскости данных и плоскости управления.
Consul — это реализация сервисной сетки с открытым исходным кодом от HashiCorp . Его преимущество заключается в хорошей интеграции с набором других продуктов для управления инфраструктурой от HashiCorp, что обеспечивает более широкие возможности. Плоскость данных в Consul обладает гибкостью для поддержки прокси-сервера, а также собственной модели интеграции. Он поставляется со встроенным прокси, но также может хорошо работать с Envoy.
Помимо Kubernetes, Consul предназначен для работы с другими платформами, такими как Nomad . Consul работает, запуская агент Consul на каждом узле для проверки работоспособности. Эти агенты взаимодействуют с одним или несколькими серверами Consul, которые хранят и реплицируют данные. Хотя он предоставляет все стандартные функции сервисной сетки, такой как Istio, это более сложная система для развертывания и управления .
10. Заключение
Подводя итог, в этом руководстве мы рассмотрели основные концепции шаблона сервисной сетки и функции, которые он нам предоставляет. В частности, мы подробно рассмотрели Istio. Это касалось базовой архитектуры Istio и ее основных компонентов. Далее мы подробно рассмотрели установку и использование Istio для некоторых распространенных вариантов использования.