Легко и непринужденно настраиваем Istio для уменьшения нагрузки и влияния как на control, так и на data plane, используя ресурс Sidecar.


По умолчанию все прокси вашей mesh получают настройки, требуемые для достижения любых других прокси. Важно заметить, что Config — это не тоолько данные, которые вы пишете в ваши DestinationRule и VirtualService, но и описание состояния всех Endpoints ваших сервисов, поэтому, каждый раз, когда вы запускаете Deployment, или Pod переходит в состояние unready, ваш сервис масштабируется или происходит что-то еще, изменяющее состояние — настройки отсылаются всем прокси.


Это отличный сценарий, если сервисы в вашей mesh можно пересчитать по пальцам, в таком случае он помогает новым пользователям достичь своей цели с минимальными притирками, но если ваша mesh растет, вы начинаете замечать следующее:


  • Control plane (pilot или istiod) начинает жрать процессорное время, и, внезапно, сеть;
  • Использование оперативной памяти на всех прокси растет вместе с ростом mesh, поскольку они все хранят все настройки всех сервисов;
  • Pilot дольше загружает настройки на все требуемые сервисы, так что изменения требуют больше времени на распространение.

Что это значит в реальном мире?


Маловероятно, что все ваши сервисы должны общаться со всеми другими сервисами. Например, на картинке ниже изображен граф, показывающий связи сервисов в Auto Trader. Более 400 сервисов, однако среднее число N+1 соединений между сервисами равно 5. Это значит, что для подавляющего большинства случаев настройки прокси включают просто ненужные 395 наборов настроек.



Чтобы узнать еще немного цифр по графу с примера выше, сделав запрос GET :15000/config_dump на istio-proxy без настройки sidecar, мы получим результат размером в 5Мб. Умножая это число на число подов (1000) получаем порядка 5Гб полных настроек, загружаемых всеми сервисами. Это куча работы для control plane, особенно для кластера с постоянной высокой текучкой, где enpoints часто меняются.


Все эти настройки влияют по istio-proxy, кардинально увеличивая потребности в оперативной памяти. К примеру, обычный прокси, с 2 или 3 сервисами, использует примерно 25Мб оперативной памяти, поэтому 400 сервисов потребуют 250Мб. Умножая на вышесказанные 1000 прокси получаем, что вам надо будет использовать от 240Гб оперативной памяти.


Настройка Sidecar


Для решения этой проблемы Istio предоставляет ресурс Sidecar.Он определяем, какие настройки прокси должны получать от control plane. Проще говоря, он делает так: «Эй, в mesh есть 400 сервисов, но мне нужны только вот эти два».


Так что если, допустим, сервис service-a общается с двумя другими service-b и service-c, но ему не нужно соединение с остальными 397 сервисами в mesh, мы создаем ресурс Sidecar, выглядящий примерно так:


apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
  name: default
  namespace: service-a
spec:
  egress:
  - hosts:
    - "./*"              # current namespace
    - "istio-system/*"   # istio-system services
    - "service-b/*"      # dependency 1
    - "service-c/*"      # dependency 2

Это пример подразумевает, что каждый сервис развернут в своем отдельном пространстве имен.


Примечание 1: Мы здесь не используем селектор нагрузки, так что этот sidecar будет применяться на всех прокси в пространстве имен service-a


Примечание 2: Если вы примените эти настройки к существующему сервису, вам надо будет перезапустить вашу рабочую нагрузку, чтобы увидеть улучшения по оперативной памяти, поскольку если istio-proxy её запросил — он не будет её отдавать обратно операционной системе до перезапуска.


Наблюдение за Pilot


Есть несколько важных параметров для мониторинга, чтобы получить данные о том, как долго Pilot выгружает настройки:


  • pilot_xds_push_time_bucket — общее время в секундах, потраченное Pilot на выгрузку lds, rds, cds и eds.
  • pilot_proxy_convergence_time_bucket — задержка в секундах между изменением настроек и их получением в прокси
  • pilot_proxy_queue_time_bucket — время в секундах, которое прокси тратит на ожидание в очереди выгрузки настроек.

На изображении ниже наш кластер на 400 сервисов, мы никогда не выходим за пределы 1 секунды:



Определение неверных настроек


Мы выкатываем настройки Istio с использованием outboundTrafficPolicy.mode: REGISTRY_ONLY. Это по-умолчанию запрещает все, поэтому нашим пользователям надо принудительно указывать в их настройках сервисы: если они не добавят сервисы в свой Sidecar — они не будут работать. Сейчас это выражается двумя способами:


  • Код ответа, возвращаемый от локального прокси, если он пытается связаться с неопределенным в Sidecar сервисом, будет 502.
  • Выставляется параметр response_code в 502, а destination_service_name в соответствующее значение в BlackHoleCluster. Мы используем эту информацию, чтобы показывать предупреждение разработчикам. Они должны знать, что где-то ошиблись в настройках:


Результат


Потребление ресурсов на нашем производственном кластере (примерно 1500 подов, 1000 с istio-proxy) с правильно настроенным Sidecars такое:


  • control plane: 1Гб оперативной памяти, всплески по процессору редко превышают потребление одного ядра;
  • data plane: 35Гб оперативной памяти, загрузка по процессору от 7 до 25 потребляемых ядер, зависит от операций в секунду по сети.

Корректная настройка Sidecar критически важна для того, чтобы запустить Istio легко и непринужденно. Сами понимаете, что проще это все делать в самом начале, чем возвращаться и добавлять позднее.


От редакции: Для тех, кто хочет освоить в теории и на практике тонкости установки и конфигурации отказоустойчивого кластера, спикеры Слёрма создали видеокурс «Kubernetes Мега». Курс поможет начать работать с Kubernetes на продвинутом уровне.