Istio service mesh не так прост

Istio service mesh не так прост, по крайне мере, с ним тоже бывают проблемы. В этом посте я бы хотел затронуть две из них, с которыми посчасливилось встретиться.

Что такое Istio? Концептуальное определение — service mesh, но, согласитесь, от этого понятнее не становится. Если говорить кратко, то под Истио можно понимать инфраструктурный уровень вашей системы, который отвечает за все сетевые активности. Это и взаимодействие разных сервисов друг с другом, это и балансировка нагрузки, это и https терминирование, это и сбор различных логов, телеметрии и Distributed tracing. В общем, этот продукт умеет очень много.

Если вы не знакомы с архитектурой Istio, то можете прочитать https://blog.newrelic.com/engineering/istio-service-mesh/ — эту обзорную статью, или посмотреть хороший доклад Тупые сервисы в умных сетях: деплоим как ниндзя при помощи Istio service mesh

Почему Istio стал таким популярным? Вероятно, это связано с тем, что микросервисная архитектура захватила рынок бэкенд разработки, а еще — kubernetes стал уже своего рода Commodity — он есть у всех.

Раньше люди, даже внутри k8s, благополучно использовали ingress в связке с nginx, но, со временем, аппетиты росли. Кроме балансировки нагрузки и обратного прокси хотелось всё большего. Так и появился Istio, заменив собой привычнй nginx (для reverse proxy используется sidecar прокси Envoy).

Давайте теперь перейдем к тем проблемкам, с которыми я уже встретился вместе с Istio. Сразу хочу сказать, что виноват я сам, так как обо всём написано в документации.

Circuit breakers

В Istio можно настроить Circuit breaker функциональность, вообще не меняя код приложений. Например, можно ограничить максимальное число соединений, которое может быть одновременно установленно к вашему приложению. Делается это примерно так:

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
    trafficPolicy:
      connectionPool:
        tcp:
          maxConnections: 100

Этой конфигурацией мы ограничиваем число соединений до 100. Соответственно, если будет больше, чем 100, соединения будут автоматически отбрасываться.

Какую я встретил тут проблему? Установил какое-то маленькое значение, и потом забыл об этом месте. В результате, в системе часть запросов попросту не доходило — и я не сразу понял почему. Проблема в том, что это действие нигде не логируется, в случае срабатывания Circuit breaker (либо, я не нашёл, где есть логи). Собственно, будьте вниманительны при настройке этого значения.

Конфигурация ресурсов для Sidecar

Как мы обсудили выше, Istio для того, чтобы управлять системой, в каждый POD ваших приложений дополнительно устанавливает Sidecar контейнер. Важная мысль — этот Sidecar контейнер тоже кушает ресурсы, причём, вполне неплохо. Поэтому, вы должны мониторить не только потребление RAM или CPU ваших приложений, но и всех сайдкаров.

Сколько памяти и процессора выделяется по умолчанию, можно посмотреть тут — https://github.com/istio/istio/blob/master/install/kubernetes/helm/istio/values.yaml#L152:

    # Resources for the sidecar.
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 2000m
        memory: 1024Mi

Как вы можете видеть, лимиты не такие уж и большие. По крайне мере, эту память можно легко съесть и получить завершенный контейнер с причиной Out of memory (OOM).

Кроме того, до появления OOM клиенты будут видеть крайне странные спецэффекты. В случае HTTP-сервисов, клиенты будут получать различные коды ошибок — 500, 501, 502, 503. Причём, в access logs вообще не будет этих запросов. Поэтому, отлаживать такую ситуацию крайне сложно.

Категории: Программирование