В преддверии старта курса "Инфраструктурная платформа на основе Kubernetes" подготовили традиционный перевод полезной статьи.


Работать с целевыми уровнями обслуживания (SLO) намного проще при наличии сервисной сетки

Ознакомившись с этим руководством, вы научитесь легко задавать целевые уровни обслуживания (SLO, от англ. Service Level Objectives) для работоспособности сервисов в Kubernetes с помощью Prometheus, базы данных временных рядов с открытым исходным кодом, и Linkerd, сверхлегкой сервисной сетки с открытым исходным кодом. Вы узнаете, как с помощью сервисной сетки можно получать согласованные показатели для параметров, которые вы хотите измерять, что является одним из самых сложных аспектов SLO.

Однако, перед тем как начать, давайте разберемся, почему SLO и Kubernetes идут рука об руку.

Доводы в пользу применения SLO с Kubernetes и сервисной сеткой

SLO, или целевые уровни обслуживания, стали в последнее время популярным средством определения надежности приложений. Согласно описанию, приведенному в книге Google о SRE, с помощью SLO разработчики приложений и специалисты, занимающиеся обеспечением надежности информационных систем, могут явным образом определять устойчивость своих приложений к риску, задавая допустимый уровень сбоев с последующей оценкой соотношения риска к преимуществам с учетом этого показателя.

Владельцы платформ, которых больше интересуют сами платформы, а не работающие на их базе приложения, используют SLO иначе: SLO позволяют им определять состояние сервисов, размещенных на платформе, при этом им не нужно ничего знать об истории работы этих сервисов. Это особенно полезно в Kubernetes, где у вас могут работать сотни или даже тысячи сервисов в десятках кластеров. Вместо того чтобы вдаваться в контекст работы каждого сервиса, с помощью SLO можно получать оценки, не зависящие от контекста. (См. SLO или показатели для Kubernetes.)

К счастью, получать SLO для состояния сервисов в Kubernetes намного проще, чем кажется. Ведь при работе с SLO сложнее всего получать согласованные, унифицированные показатели, но именно в этом и помогает сервисная сетка! Например, Linkerd предоставляет унифицированный и согласованный уровень значений golden metrics (золотые показатели) — доля успешных попыток, задержки, объемы запросов — для всех ваших сервисов без дополнительного конфигурирования. При наличии показателей Linkerd получение базовых SLO для состояния сервисов сводится к простым математическим вычислениям.

(Разумеется, сервисная сетка не является всеобъемлющим решением для SLO, поскольку она, например, не позволяет получать показатели для конкретных приложений. Однако, в частности, для таких часто используемых показателей работоспособности, как доля успешных попыток и задержка, можно легко создать SLO состояния сервисов на основе данных сервисной сетки.)

Давайте разберем пример.

Вычисление SLO с помощью Linkerd и Prometheus

В этом руководстве мы разберем, как настроить простой SLO для доли успешных попыток со скользящим окном для gRPC-сервиса, работающего в Kubernetes. Разумеется, используемые нами здесь методы подходят для различных показателей и SLO.

Сначала давайте рассмотрим, как Linkerd получает свои золотые показатели. При добавлении сервисной сетки Linkerd к сервису она автоматически определяет все вызовы HTTP и gRPC, входящие в блоки сервиса (pods) и исходящие из них. Она регистрирует класс ответа и задержку этих вызовов, а также агрегирует их во внутренний экземпляр Prometheus. Этот экземпляр Prometheus обеспечивает работу панели мониторинга и интерфейса командной строки Linkerd, а также содержит отслеживаемые золотые показатели для всех сервисов из сетки.

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

Настройка: установка интерфейса командной строки Linkerd в Kubernetes

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

Сначала давайте установим интерфейс командной строки Linkerd:

curl -sL https://run.linkerd.io/install | sh
export PATH=$PATH:$HOME/.linkerd2/bin

(Linkerd также можно загрузить непосредственно со страницы выпусков Linkerd.)

Далее, проверим, что ваш кластер Kubernetes может работать с Linkerd, установим Linkerd и проверим установку:

linkerd check --pre
linkerd install | kubectl apply -f -
linkerd check

Наконец, установим демонстрационное приложение Emojivoto, с которым мы будем работать:

curl -sL https://run.linkerd.io/emojivoto.yml   | linkerd inject -   | kubectl apply -f -

Теперь мы готовы получать реальные показатели. Но сначала давайте поговорим о самом важном показателе в SLO: бюджете ошибок.

Бюджет ошибок

Бюджет ошибок — это, пожалуй, самая важная часть SLO. Но что же это такое и как получить эту величину?

Начнем с примера. Скажем, вы решили, что в вашем сервисе доля успешных попыток за последние 7 дней должна составлять 80 %. Это и есть наш SLO. Это заявление можно разбить на три базовых компонента: индикатор уровня сервиса (service level indicator — SLI), который и является нашим показателем; цель, которая является нашим пороговым значением; и временное окно. В данном случае:

SLI: доля успешных попыток сервиса

Цель: 80 %

Временное окно: 7 дней

Этот SLO означает, что 20 % всех запросов в течение 7-дневного периода наблюдений могут завершиться неудачно, и мы не будем считать это проблемой. Исходя из этого, наш бюджет ошибок — это просто показатель того, сколько из этих 20 % мы «потребили» в рамках заданного временного окна.

Например, если за последние 7 дней мы успешно обслужили 100 % всех ответов, то у нас остается 100 % бюджета ошибок — все запросы были обработаны без ошибок. С другой стороны, если за последние 7 дней мы успешно обслужили 80 % всех ответов, то у нас остается 0 % бюджета ошибок. А если за этот период процент успешных ответов у нас опустился ниже 80 %, то наш бюджет ошибок будет отрицательным и заданный SLO будет нарушен.

Бюджет ошибок вычисляется по следующей формуле:

Бюджет ошибок = 1–[(1–соблюдение)/(1–цель)]

Где соблюдение — это индикатор SLI, измеренный в заданном временном окне. Таким образом, чтобы вычислить бюджет ошибок, мы измеряем индикатор SLI в заданном временном окне (чтобы рассчитать соблюдение) и сравниваем его с целью.

Вычисление бюджета ошибок с помощью Prometheus

Вернемся к практике. Давайте откроем экземпляр Prometheus в плоскости управления Linkerd, которую мы установили на предыдущем шаге, с пробросом порта:

# Get the name of the prometheus pod
$ kubectl -n linkerd get pods
NAME                                      READY   STATUS    RESTARTS   AGE
..
linkerd-prometheus-54dd7dd977-zrgqw       2/2     Running   0          16h

Обозначив имя блока как PODNAME, мы можем сделать следующее:

kubectl -n linkerd port-forward linkerd-prometheus-PODNAME 9090:9090

Теперь мы можем открыть localhost:9090 и начать экспериментировать с PromQL, языком запросов Prometheus.

Панель мониторинга Prometheus
Панель мониторинга Prometheus

Для использования этого руководства не требуется знать синтаксис в совершенстве, однако освежить память и просмотреть примеры точно не помешает!

Построение запросов Prometheus

Выше мы привели примеры с 100 и 80 % ответов — это был наш показатель соответствия для заданного временного периода. Давайте начнем с того, что вычислим этот показатель с помощью запроса Prometheus. В качестве нашего сервиса мы будем использовать сервис голосования Emojivoto, который находится в пространстве имен emojivoto как развертываемый ресурс.

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

Запрос:

response_total{deployment="voting", direction="inbound", namespace="emojivoto"}

Результат:

response_total{classification="success",deployment="voting",direction="inbound",namespace="emojivoto",..} 46499
response_total{classification="failure",deployment="voting",direction="inbound",namespace="emojivoto",..} 8652

Здесь мы видим два результата, поскольку показатели разделены одним значением метки, которым они отличаются друг от друга: classification. У нас 46 499 успешных ответов и 8652 неудачных ответов.

Отталкиваясь от этого, мы можем определить количество успешных ответов для каждой временной метки за последние 7 дней, добавив метку classification="success" и временной диапазон [7d]:

Запрос:

response_total{deployment="voting", classification="success", direction="inbound", namespace="emojivoto"}[7d]

Ответ на этот запрос будет очень большим, но его можно упростить с помощью функций PromQL increase() и sum(), выполнив группировку по меткам, чтобы выделить отдельные значения:

Запрос:

sum(increase(response_total{deployment="voting", classification="success", direction="inbound", namespace="emojivoto"}[7d])) by (namespace, deployment, classification, tls)

Результат:

{classification="success",deployment="voting",namespace="emojivoto",tls="true"} 26445.68142198795

Это означает, что за последние 7 дней в развертывании голосования было около 26 445 успешных ответов (дробная часть образуется в силу механики вычисления функции increase()).

Используя полученный результат, мы можем рассчитать наше значение соответствия, разделив это число на общее количество ответов, — просто уберите метку classification="success":

Запрос:

sum(increase(response_total{deployment="voting", classification="success", direction="inbound", namespace="emojivoto"}[7d])) by (namespace, deployment, classification, tls) / ignoring(classification) sum(increase(response_total{deployment="voting", direction="inbound", namespace="emojivoto"}[7d])) by (namespace, deployment, tls)

Результат:

{deployment="voting",namespace="emojivoto",tls="true"} 0.846113068695625

Как видим, за последние 7 дней 84,61 % ответов были успешными.

Вычисление бюджета ошибок

Итак, у нас есть базовые запросы, используемые для вычисления оставшегося бюджета ошибок. Теперь нам осталось только включить их в приведенную выше формулу:

Бюджет ошибок = 1–[(1–соблюдение)/(1–цель)]

Подставим значение нашей цели, равное 80 % (0,8):

Запрос:

1 - ((1 - (sum(increase(response_total{deployment="voting", classification="success", direction="inbound", namespace="emojivoto"}[7d])) by (namespace, deployment, classification, tls)) / ignoring(classification) sum(increase(response_total{deployment="voting", direction="inbound", namespace="emojivoto"}[7d])) by (namespace, deployment, tls)) / (1 - .80))

Результат:

{deployment="voting",namespace="emojivoto",tls="true"} 0.2312188519042635

В данном случае у нас остается 23,12 % нашего бюджета ошибок для данного развертывания голосования.

Поздравляю, вы успешно вычислили свой первый бюджет ошибок!

Регистрация результатов с помощью Grafana

Цифры — это здорово, но как насчет красивых графиков? Их есть у нас! Linkerd устанавливает экземпляр Grafana, и мы можем получить к нему доступ локально с помощью панели мониторинга Linkerd.

Сначала загрузите панель управления Linkerd, выполнив команду linkerd dashboard.

Теперь давайте откроем панель управления Grafana для пространства имен emojivoto, щелкнув логотип Grafana в соответствующем месте.

Панель управления Linkerd с интеграцией Grafana
Панель управления Linkerd с интеграцией Grafana

Прокрутив вниз до deploy/voting, мы видим панели для золотых показателей: доля успешных попыток, количество запросов и задержки. Давайте добавим панель для оставшегося бюджета ошибок.

Linkerd на панели мониторинга Grafana
Linkerd на панели мониторинга Grafana

Не будем мудрить — просто укажем название панели 7-day error budget (success rate) («Бюджет ошибок за 7 дней (доля успешных попыток)») и добавим конечный запрос, приведенный выше, в поле запроса PromQL.

В результате вы должны увидеть панель для отслеживания оставшегося бюджета ошибок для развертывания голосования!

Бюджет ошибок в Grafana с показателями Linkerd
Бюджет ошибок в Grafana с показателями Linkerd

Дальнейшие действия

Есть несколько способов адаптации использованных выше запросов по ситуации.

Теперь, когда у нас есть график, отслеживающий бюджет ошибок сервиса, мы можем использовать дополнительные функции PromQL, например rate(), чтобы отслеживать скорость уменьшения бюджета ошибок сервиса.

Если вы хотите, чтобы величина ошибки отображалась по-другому, попробуйте изменить визуализацию данных. Здесь я выбрал шкалу (Gauge) и добавил пороговые значения, указывающие, стоит ли мне волноваться.

Бюджет ошибок за 7 дней (доля успешных попыток) в формате шкалы (Gauge).
Бюджет ошибок за 7 дней (доля успешных попыток) в формате шкалы (Gauge).

Чтобы отслеживать оставшийся бюджет ошибок для всех сервисов, находящихся в пространстве имен emojivoto, просто удалите метку deployment="voting". Помните, что при этом в качестве цели для всех сервисов из этого пространства имен будет принято значение 80 %.

Бюджет ошибок за 7 дней (доля успешных попыток) для всех сервисов.
Бюджет ошибок за 7 дней (доля успешных попыток) для всех сервисов.

От формирования SLO к применению на практике

Вы сформулировали SLO для состояния сервисов на основе золотых показателей Linkerd, вычислили бюджет ошибок и построили графическое представление этих значений с помощью Grafana. Поздравляю!

Но что же дальше?

Не очень приятная новость состоит в том, что даже при наличии всего этого нужно проделать еще много работы, чтобы обеспечить практическое применение ваших SLO. Вам нужно будет вычислять эти показатели согласованно и соразмерно для всех релевантных сервисов на вашей платформе. Вам нужно будет передавать эти показатели другим сотрудникам вашей организации, которые должны их знать. Вам также потребуется возможность действовать, когда бюджеты ошибок начнут резко падать. Без всего этого созданные вами SLO останутся пустыми цифрами.

Мы в компании Buoyant верим в огромный потенциал SLO, особенно для Kubernetes. Отчасти это является причиной, подвигнувшей нас на создание панели мониторинга Dive, позволяющей настраивать SLO одним нажатием кнопки. Панель мониторинга Dive построена на Linkerd и использует те же показатели, чтобы автоматически отслеживать все сервисы, работающие в кластере. В Dive также есть панели мониторинга, которые можно отправлять другим специалистам, позволяющие предсказывать, когда будут нарушены заданные SLO, и много других интересных функций.

Панель мониторинга Dive, показывающая соответствие SLO и бюджета ошибок за 7-дневный срок.
Панель мониторинга Dive, показывающая соответствие SLO и бюджета ошибок за 7-дневный срок.

Но, как бы там ни было — используете ли вы Dive для отслеживания своих SLO состояния сервисов в Linkerd или вариант с применением Prometheus и Grafana, описанный выше, — мы желаем вам удачи в работе со SLO!

Похожая статья:

Зачем нужны целевые уровни обслуживания (SLO) для Kubernetes

Целевые уровни обслуживания (SLO) являются горячей темой в сфере обеспечения надежности программного обеспечения. В распространенном представлении SLO — это способ балансировать риск и преимущества для того или иного приложения. «Следует ли реализовать новую функцию для этого сервиса, даже несмотря на то, что он может выйти из строя?» Однако для тех, кто внедряет Kubernetes, SLO могут дать кое-что еще: согласованный, унифицированный способ измерения работоспособности каждого приложения в кластере, причем для этого не требуется знать историю или контекст работы любого приложения.


Узнать подробнее о курсе "Инфраструктурная платформа на основе Kubernetes". Посмотреть открытый урок по теме "Повышаем надежность развертывания в Kubernetes" можно здесь.


Читать ещё: