Что такое Istio? Это так называемый Service mesh, технология, которая добавляет уровень абстракции над сетью. Мы перехватываем весь или часть трафика в кластере и производим определенный набор операций с ним. Какой именно? Например, делаем умный роутинг, или реализуем подход circuit breaker, можем организовывать «canary deployment», частично переключая трафик на новую версию сервиса, а можем ограничивать внешние взаимодействия и контролировать все походы из кластера во внешнюю сеть. Есть возможность задавать policy правила для контроля походов между разными микросервисами. Наконец, мы можем получить всю карту взаимодействия по сети и сделать унифицированный сбор метрик полностью прозрачно для приложений.
Про механизм работы можно прочитать в официальной документации. Istio — это действительно мощный инструмент, который позволяет решить множество задач и проблем. В этой статье я бы хотел ответить на основные вопросы, которые обычно возникают в начале работы с Istio. Это поможет вам разобраться с ним быстрее.

Istio состоит из двух основных зон — control plane и data plane. Control plane содержит в себе основные компоненты, которые обеспечивают корректную работу остальных. В текущей версии (1.0) control plane имеет три основных компонента: Pilot, Mixer, Citadel. Citadel мы рассматривать не будем, он нужен для генерации сертификатов для обеспечения работы mutual TLS между сервисами. Давайте посмотрим подробнее на устройство и предназначение Pilot и Mixer.

Pilot — это главный управляющий компонент, который распространяет всю информацию о том, что у нас есть в кластере – сервисы, их endpoint’ы и routing правила (например, правила для Canary deployment или правила circuit breaker).
Mixer — опциональный компонент control plane, который предоставляет возможность сбора метрик, логов и любой информации о сетевом взаимодействии. Также он следит за соблюдением Policy правил и соблюдением rate limit’ов.
Data plane реализуется с помощью sidecar контейнеров-прокси. По умолчанию используется мощный прокси-сервер envoy. Он может быть заменен на другую реализацию, например nginx (nginmesh).
Для того, чтобы Istio работал полностью прозрачно ��ля приложений, есть система автоматического inject’инга. Последняя реализация подходит для версий Kubernetes 1.9+ (mutational admission webhook). Для Kubernetes версий 1.7, 1.8 есть возможность использовать Initializer.
Sidecar контейнеры соединяются с Pilot по протоколу GRPC, который позволяет оптимизировать модель пушинга изменений, происходящих в кластере. GRPC начал использоваться в Envoy начиная с версии 1.6, в Istio он используется с версии 0.8 и представляет из себя pilot-agent — обертку на golang над envoy, которая конфигурирует параметры запуска.
Pilot и Mixer являются полностью stateless компонентами, все состояние держат в памяти. Конфигурация для них задается в виде Kubernetes Custom Resources, которые сохраняются в etcd.
Istio-agent получает адрес Pilot и открывает GRPC stream к нему.
Как я уже сказал, Istio реализует всю функциональность полностью прозрачно для приложений. Давайте разберемся как. Алгоритм такой:
В итоге мы получаем целую сеть envoy прокси-серверов, которые мы можем настраивать из одной точки (Pilot). Все inbound и outbound запросы проходят через envoy. Причем, перехватывается только TCP трафик. Это значит, что Kubernetes service IP резолвится с помощью kube-dns по UDP без изменения. Затем уже после резолва происходит перехват исходящего запроса и обработка envoy’ем, который уже решает на какой endpoint нужно отправить запрос (или не отправить, в случае политик доступа или сработки circuit breaker алгоритма).
С Pilot разобрались, теперь нужно понять как работает Mixer и зачем он нужен. Прочитать официальную документацию по нему можно тут.
Mixer в текущем виде представляет из себя два компонента: istio-telemetry, istio-policy (до версии 0.8 это был один компонент istio-mixer). И тот, и другой представляют из себя mixer, каждый из которых отвечают за свою задачу. Istio telemetry принимает по GRPC от sidecar контейнеров Report информацию о том, кто куда идет и с какими параметрами. Istio-policy принимает Check запросы для проверки удовлетворения Policy правилам. Poilicy check проводятся, конечно, не на каждый запрос, а кэшируются на клиенте (в sidecar) на определенное время. Report check’и отправляются batch запросами. Как настраивать и какие именно параметры нужно отсылать посмотрим чуть позже.
Mixer предполагается как высокодоступный компонент, который обеспечивает бесперебойную работу по сборке и обработке telemetry данных. Система получается в итоге как многоуровневый буфер. Изначально данные буферизируются на стороне sidecar контейнеров, затем на стороне mixer и потом отправляются в так называемые mixer backend’ы. В итоге, если какой-то из компонентов системы отказывает, буфер растет и после восстановления системы флашится. Mixer backend’ы представляют из себя конечные точки отправки данных о телеметрии: statsd, newrelic и тд. Можно написать свой backend, это достаточно просто, и мы посмотрим как это сделать.

Если подытожить, схема работы с istio-telemetry такова.
Теперь посмотрим, как развернуть в системе Istio, состоящий только из основных компонентов (Pilot и sidecar envoy).
Для начала посмотрим на основную конфигурацию (mesh), которую читает Pilot:
Все основные компоненты управления (control plane) расположим в namespace istio-system в Kubernetes.
Минимально нам нужно развернуть только Pilot. Для этого воспользуемся такой конфи��урацией.
И настроим вручную injecting sidecar контейнера.
Init container:
И sidecar:
Для того, чтобы все успешно запустилось, нужно завести ServiceAccount, ClusterRole, ClusterRoleBinding, CRD для Pilot, описания которых можно найти тут.
В итоге сервис, в который мы inject’им sidecar с envoy, должен успешно запуститься, получить весь discovery из пилота и обрабатывать запросы.
Важно понимать, что все компоненты control plane являются stateless приложениями и могут быть без проблем горизонтально масштабированы. Все данные лежат в etcd в виде кастомных описаний ресурсов Kubernetes.
Также у Istio (пока что экспериментально) есть возможность запуска вне кластера и возможность смотреть и шарить service discovery между несколькими Kubernetes кластерами. Подробнее об этом можно почитать тут.
При мультикластерной установке следует учитывать следующие ограничения:
Это начальные сведения, которые помогут вам приступить к работе с Istio. Однако есть еще множество подводных камней. Например, особенности роутинга внешнего трафика (наружу кластера), подходы к отладке sidecar’ов, профилирование, настройка mixer и написание кастомного mixer backend, настройка tracing механизма и его работа с помощью envoy.
Всё это мы рассмотрим в следующих публикациях. Задавайте ваши вопросы, постараюсь их осветить.
Про механизм работы можно прочитать в официальной документации. Istio — это действительно мощный инструмент, который позволяет решить множество задач и проблем. В этой статье я бы хотел ответить на основные вопросы, которые обычно возникают в начале работы с Istio. Это поможет вам разобраться с ним быстрее.

Принцип работы
Istio состоит из двух основных зон — control plane и data plane. Control plane содержит в себе основные компоненты, которые обеспечивают корректную работу остальных. В текущей версии (1.0) control plane имеет три основных компонента: Pilot, Mixer, Citadel. Citadel мы рассматривать не будем, он нужен для генерации сертификатов для обеспечения работы mutual TLS между сервисами. Давайте посмотрим подробнее на устройство и предназначение Pilot и Mixer.

Pilot — это главный управляющий компонент, который распространяет всю информацию о том, что у нас есть в кластере – сервисы, их endpoint’ы и routing правила (например, правила для Canary deployment или правила circuit breaker).
Mixer — опциональный компонент control plane, который предоставляет возможность сбора метрик, логов и любой информации о сетевом взаимодействии. Также он следит за соблюдением Policy правил и соблюдением rate limit’ов.
Data plane реализуется с помощью sidecar контейнеров-прокси. По умолчанию используется мощный прокси-сервер envoy. Он может быть заменен на другую реализацию, например nginx (nginmesh).
Для того, чтобы Istio работал полностью прозрачно ��ля приложений, есть система автоматического inject’инга. Последняя реализация подходит для версий Kubernetes 1.9+ (mutational admission webhook). Для Kubernetes версий 1.7, 1.8 есть возможность использовать Initializer.
Sidecar контейнеры соединяются с Pilot по протоколу GRPC, который позволяет оптимизировать модель пушинга изменений, происходящих в кластере. GRPC начал использоваться в Envoy начиная с версии 1.6, в Istio он используется с версии 0.8 и представляет из себя pilot-agent — обертку на golang над envoy, которая конфигурирует параметры запуска.
Pilot и Mixer являются полностью stateless компонентами, все состояние держат в памяти. Конфигурация для них задается в виде Kubernetes Custom Resources, которые сохраняются в etcd.
Istio-agent получает адрес Pilot и открывает GRPC stream к нему.
Как я уже сказал, Istio реализует всю функциональность полностью прозрачно для приложений. Давайте разберемся как. Алгоритм такой:
- Деплоим новую версию сервиса.
- В зависимости от подхода injecting’а sidecar контейнера добавляются istio-init контейнер и istio-agent контейнер (envoy) на этапе применения конфигурации, либо они могут быть уже вручную вставлены в описание Pod сущности Kubernetes.
- istio-init контейнер представляет из себя скрипт, который применяет правила iptables для пода. Есть два варианта для настройки заворачивания трафика в istio-agent контейнер: использовать redirect правила iptables, либо TPROXY. На момент написания статьи по умолчанию используется подход с redirect правилами. В istio-init есть возможность настроить какой именно трафик нужно перехватывать и направлять в istio-agent. Например, для того, чтобы перехватывать весь входящий и весь исходящий трафик, нужно установить параметры
-iи-bв значение*. Можно указать конкретные порты, которые нужно перехватывать. Для того, чтобы не перехватывать определенную подсеть, можно указать ее с помощью флага-x. - После исполнения init контейнеров, запускаются основные, и в том числе pilot-agent (envoy). Он подключается к уже развернутому Pilot по GRPC и получает информацию о всех существующих сервисах и routing политиках в кластере. По полученным данным, он конфигурирует cluster’ы и прописывает им непосредственно endpoint’ы наших приложений в Kubernetes кластере. Также необходимо отметить важный момент: envoy динамически настраивает listeners (пары IP, port), которые начинает слушать. Поэтому, когда запросы входят в pod, перенаправляются с помощью redirect iptables правил в sidecar, envoy уже успешно может обрабатывать эти соединения и понимать, куда нужно дальше проксировать трафик. Также на этом этапе происходит отправка информации в Mixer, который мы рассмотрим позже, и отправка tracing span’ов.
В итоге мы получаем целую сеть envoy прокси-серверов, которые мы можем настраивать из одной точки (Pilot). Все inbound и outbound запросы проходят через envoy. Причем, перехватывается только TCP трафик. Это значит, что Kubernetes service IP резолвится с помощью kube-dns по UDP без изменения. Затем уже после резолва происходит перехват исходящего запроса и обработка envoy’ем, который уже решает на какой endpoint нужно отправить запрос (или не отправить, в случае политик доступа или сработки circuit breaker алгоритма).
С Pilot разобрались, теперь нужно понять как работает Mixer и зачем он нужен. Прочитать официальную документацию по нему можно тут.
Mixer в текущем виде представляет из себя два компонента: istio-telemetry, istio-policy (до версии 0.8 это был один компонент istio-mixer). И тот, и другой представляют из себя mixer, каждый из которых отвечают за свою задачу. Istio telemetry принимает по GRPC от sidecar контейнеров Report информацию о том, кто куда идет и с какими параметрами. Istio-policy принимает Check запросы для проверки удовлетворения Policy правилам. Poilicy check проводятся, конечно, не на каждый запрос, а кэшируются на клиенте (в sidecar) на определенное время. Report check’и отправляются batch запросами. Как настраивать и какие именно параметры нужно отсылать посмотрим чуть позже.
Mixer предполагается как высокодоступный компонент, который обеспечивает бесперебойную работу по сборке и обработке telemetry данных. Система получается в итоге как многоуровневый буфер. Изначально данные буферизируются на стороне sidecar контейнеров, затем на стороне mixer и потом отправляются в так называемые mixer backend’ы. В итоге, если какой-то из компонентов системы отказывает, буфер растет и после восстановления системы флашится. Mixer backend’ы представляют из себя конечные точки отправки данных о телеметрии: statsd, newrelic и тд. Можно написать свой backend, это достаточно просто, и мы посмотрим как это сделать.

Если подытожить, схема работы с istio-telemetry такова.
- Сервис 1 посылает запрос в сервис 2.
- При выходе из сервиса 1, запрос заворачивается в его же sidecar.
- Sidecar envoy следит за тем, как проходит запрос в сервис 2 и подготавливает необходимую информацию.
- Затем отправляет её в istio-telemetry с помощью Report запроса.
- Istio-telemetry определяет, нужно ли отправлять этот Report в backend’ы, в какие именно и какие данные нужно отправлять.
- Istio-telemetry отправляет Report данные в backend если это необходимо.
Теперь посмотрим, как развернуть в системе Istio, состоящий только из основных компонентов (Pilot и sidecar envoy).
Для начала посмотрим на основную конфигурацию (mesh), которую читает Pilot:
apiVersion: v1
kind: ConfigMap
metadata:
name: istio
namespace: istio-system
labels:
app: istio
service: istio
data:
mesh: |-
# пока что не включаем отправку tracing информации (pilot настроит envoy’и таким образом, что отправка не будет происходить)
enableTracing: false
# пока что не указываем mixer endpoint’ы, чтобы sidecar контейнеры не отправляли информацию туда
#mixerCheckServer: istio-policy.istio-system:15004
#mixerReportServer: istio-telemetry.istio-system:15004
# ставим временной промежуток, с которым будет envoy переспрашивать Pilot (это для старой версии envoy proxy)
rdsRefreshDelay: 5s
# default конфигурация для envoy sidecar
defaultConfig:
# аналогично как rdsRefreshDelay
discoveryRefreshDelay: 5s
# оставляем по умолчанию (путь к конфигурации и бинарю envoy)
configPath: "/etc/istio/proxy"
binaryPath: "/usr/local/bin/envoy"
# дефолтное имя запущенного sidecar контейнера (используется, например, в именах сервиса при отправке tracing span’ов)
serviceCluster: istio-proxy
# время, которое будет ждать envoy до того, как он принудительно завершит все установленные соединения
drainDuration: 45s
parentShutdownDuration: 1m0s
# по умолчанию используются REDIRECT правила iptables. Можно изменить на TPROXY.
#interceptionMode: REDIRECT
# Порт, на котором будет запущена admin панель каждого sidecar контейнера (envoy)
proxyAdminPort: 15000
# адрес, по которому будут отправляться trace’ы по zipkin протоколу (в начале мы отключили саму отправку, поэтому это поле сейчас не будет использоваться)
zipkinAddress: tracing-collector.tracing:9411
# statsd адрес для отправки метрик envoy контейнеров (отключаем)
# statsdUdpAddress: aggregator:8126
# выключаем поддержку опции Mutual TLS
controlPlaneAuthPolicy: NONE
# адрес, на котором будет слушать istio-pilot для того, чтобы сообщать информацию о service discovery всем sidecar контейнерам
discoveryAddress: istio-pilot.istio-system:15007
Все основные компоненты управления (control plane) расположим в namespace istio-system в Kubernetes.
Минимально нам нужно развернуть только Pilot. Для этого воспользуемся такой конфи��урацией.
И настроим вручную injecting sidecar контейнера.
Init container:
initContainers:
- name: istio-init
args:
- -p
- "15001"
- -u
- "1337"
- -m
- REDIRECT
- -i
- '*'
- -b
- '*'
- -d
- ""
image: istio/proxy_init:1.0.0
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 128Mi
securityContext:
capabilities:
add:
- NET_ADMIN
И sidecar:
name: istio-proxy
args:
- "bash"
- "-c"
- |
exec /usr/local/bin/pilot-agent proxy sidecar \
--configPath \
/etc/istio/proxy \
--binaryPath \
/usr/local/bin/envoy \
--serviceCluster \
service-name \
--drainDuration \
45s \
--parentShutdownDuration \
1m0s \
--discoveryAddress \
istio-pilot.istio-system:15007 \
--discoveryRefreshDelay \
1s \
--connectTimeout \
10s \
--proxyAdminPort \
"15000" \
--controlPlaneAuthPolicy \
NONE
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: INSTANCE_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: ISTIO_META_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: ISTIO_META_INTERCEPTION_MODE
value: REDIRECT
image: istio/proxyv2:1.0.0
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
memory: 2048Mi
securityContext:
privileged: false
readOnlyRootFilesystem: true
runAsUser: 1337
volumeMounts:
- mountPath: /etc/istio/proxy
name: istio-envoy
Для того, чтобы все успешно запустилось, нужно завести ServiceAccount, ClusterRole, ClusterRoleBinding, CRD для Pilot, описания которых можно найти тут.
В итоге сервис, в который мы inject’им sidecar с envoy, должен успешно запуститься, получить весь discovery из пилота и обрабатывать запросы.
Важно понимать, что все компоненты control plane являются stateless приложениями и могут быть без проблем горизонтально масштабированы. Все данные лежат в etcd в виде кастомных описаний ресурсов Kubernetes.
Также у Istio (пока что экспериментально) есть возможность запуска вне кластера и возможность смотреть и шарить service discovery между несколькими Kubernetes кластерами. Подробнее об этом можно почитать тут.
При мультикластерной установке следует учитывать следующие ограничения:
- Pod CIDR и Service CIDR должны быть уникальны по всем кластерам и не должны пересекаться.
- Все Pod CIDR должны быть доступны от любых Pod CIDR между кластерами.
- Все Kubernetes API серверы должны быть доступны друг для друга.
Это начальные сведения, которые помогут вам приступить к работе с Istio. Однако есть еще множество подводных камней. Например, особенности роутинга внешнего трафика (наружу кластера), подходы к отладке sidecar’ов, профилирование, настройка mixer и написание кастомного mixer backend, настройка tracing механизма и его работа с помощью envoy.
Всё это мы рассмотрим в следующих публикациях. Задавайте ваши вопросы, постараюсь их осветить.
