Мониторинг приложения микрослужб в AKS

Azure Monitor
Служба Azure Kubernetes (AKS)

В этой статье описаны рекомендации по мониторингу приложения микрослужб, работающего в Служба Azure Kubernetes (AKS). К определенным темам относятся сбор данных телеметрии, мониторинг состояния кластера, метрики, ведение журнала, структурированное ведение журнала и распределенная трассировка. Последний показан на этой схеме:

Diagram that shows the architecture of a drone delivery application.

Скачайте файл Visio для этой архитектуры.

Сбор данных телеметрии

В любом сложном приложении в определенный момент возникают проблемы. Если вы используете приложение для микрослужб, вам необходимо отслеживать, что происходит между десятками и даже сотнями служб. Чтобы понять, что происходит, необходимо собрать данные телеметрии из приложения. Данные телеметрии можно разделить на следующие категории: журналы, трассировки и метрики.

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

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

  • Диапазоны — это единицы работы в трассировки. Каждый диапазон связан с одной трассировкой и может быть вложен с другими диапазонами. Они часто соответствуют отдельным запросам в межслужбовой операции, но они также могут определять работу в отдельных компонентах в службе. Диапазоны также отслеживают исходящие вызовы из одной службы в другую. (Иногда диапазоны называются записями зависимостей.)

Метрики — это числовые значения, которые можно проанализировать. Их можно использовать для наблюдения за системой в режиме реального времени (или близко к реальному времени) или для анализа тенденций производительности с течением времени. Чтобы понять систему целостно, необходимо собирать метрики на различных уровнях архитектуры, от физической инфраструктуры до приложения, в том числе:

  • Метрики уровня узла, в том числе использование ЦП, памяти, сети, диска и файловой системы. Системные метрики помогают понять выделение ресурсов для каждого узла в кластере и устранить неполадки.

  • Метрики контейнеров. Для контейнерных приложений необходимо собирать метрики на уровне контейнера, а не только на уровне виртуальной машины.

  • Метрики приложения. Эти метрики относятся к пониманию поведения службы. Примеры включают количество входящих HTTP-запросов в очереди, задержку запроса и длину очереди сообщений. Приложения также могут использовать пользовательские метрики, относящиеся к домену, например количество бизнес-транзакций, обрабатываемых в минуту.

  • Метрики зависимых служб. Службы иногда вызывают внешние службы или конечные точки, например управляемые службы PaaS или SaaS. Сторонние службы могут не предоставлять метрики. Если они нет, необходимо полагаться на собственные метрики приложения для отслеживания статистики задержки и частоты ошибок.

Мониторинг состояния кластера

Используйте Azure Monitor для мониторинга работоспособности кластеров. На следующем снимке экрана показан кластер с критическими ошибками в развернутых пользователем модулях pod:

Screenshot that shows the Monitor dashboard.

Здесь вы можете детализировать дополнительные сведения о проблеме. Например, если состояние pod задано ImagePullBackoff, Kubernetes не удалось извлечь образ контейнера из реестра. Эта проблема может быть вызвана недопустимым тегом контейнера или ошибкой проверки подлинности во время извлечения из реестра.

Если контейнер завершается сбоем, контейнер State становится Waitingв виде Reason CrashLoopBackOff. В типичном сценарии, когда модуль pod является частью набора реплика и политикой Alwaysповторных попыток, эта проблема не отображается как ошибка в состоянии кластера. Однако вы можете выполнять запросы или настраивать оповещения для этого условия. Дополнительные сведения см. в статье "Общие сведения о производительности кластера AKS" с помощью аналитики контейнеров Azure Monitor.

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

Screenshot that shows the workbooks for an AKS resource.

Метрики

Мы рекомендуем использовать Monitor для сбора и просмотра метрик для кластеров AKS и любых других зависимых служб Azure.

  • Для метрик кластера и контейнеров включите аналитику контейнеров Azure Monitor. Если эта функция включена, монитор собирает метрики памяти и процессора из контроллеров, узлов и контейнеров с помощью API метрик Kubernetes. Дополнительные сведения о метриках, доступных из аналитики контейнеров, см. в статье "Общие сведения о производительности кластера AKS" с помощью аналитики контейнеров Azure Monitor.

  • Используйте приложение Аналитика для сбора метрик приложения. Аналитика приложения — это расширяемая служба управления производительностью приложений (APM). Чтобы использовать его, необходимо установить пакет инструментирования в приложении. Этот пакет отслеживает приложение и отправляет данные телеметрии в приложение Аналитика. Он также может извлечь данные телеметрии из среды узла. Затем данные отправляются в Monitor. Приложение Аналитика также обеспечивает встроенную корреляцию и отслеживание зависимостей. (См. раздел Распределенная трассировка, далее в этой статье.)

Приложение Аналитика имеет максимальную пропускную способность, измеряемую в событиях в секунду, и она регулирует данные телеметрии, если скорость данных превышает предел. Дополнительные сведения см. в разделе "Ограничения для приложений Аналитика". Создайте разные экземпляры приложений Аналитика для каждой среды, чтобы среды разработки и тестирования не соревновались с рабочей телеметрией для квоты.

Одна операция может генерировать множество событий телеметрии, поэтому если приложение испытывает большой объем трафика, его запись телеметрии, скорее всего, будет регулироваться. Чтобы устранить эту проблему, вы можете выполнить выборку для уменьшения трафика телеметрии. Компромисс заключается в том, что метрики будут менее точными, если инструментирование не поддерживает предварительную агрегирование. В этом случае для устранения неполадок будет меньше примеров трассировки, но метрики поддерживают точность. Дополнительные сведения см. в статье Выборка в Application Insights. Вы также можете уменьшить объем данных, предварительно агрегируя метрики. То есть вы можете вычислить статистические значения, такие как среднее и стандартное отклонение, и отправить эти значения вместо необработанной телеметрии. В этой записи блога описывается подход к использованию приложений Аналитика в масштабе: мониторинг и аналитика Azure в масштабе.

Если скорость данных достаточно высока, чтобы активировать регулирование, а выборка или агрегирование недопустимы, попробуйте экспортировать метрики в базу данных временных рядов, например Azure Data Обозреватель, Prometheus или InfluxDB, запущенную в кластере.

  • Azure Data Обозреватель — это служба azure, высокомасштабируемая служба анализа данных для данных журналов и данных телеметрии. Она поддерживает несколько форматов данных, язык расширенных запросов и подключения для использования данных в популярных инструментах, таких как Jupyter Notebook и Grafana. В Обозреватель данных Azure есть встроенные соединители для приема данных журналов и метрик с помощью Центры событий Azure. Дополнительные сведения см. в статье Прием данных мониторинга и отправка запросов к ним в Azure Data Explorer.

  • InfluxDB — это система принудительной отправки. Агент должен принудительно отправлять метрики. Стек TICK можно использовать для настройки мониторинга Kubernetes. Затем вы можете отправить метрики в InfluxDB с помощью Telegraf, который является агентом для сбора и создания отчетов метрик. Для нерегулярных событий и строковых типов данных можно использовать ПотокиDB.

  • Prometheus — это система извлечения по запросу. Она периодически извлекает метрики из настроенных расположений. Prometheus может сломать метрики, созданные Azure Monitor или kube-state-metrics. Kube-state-metrics — это служба, которая собирает метрики с сервера API Kubernetes и делает их доступными для Prometheus (или скребка, совместимого с конечной точкой клиента Prometheus). Для системных метрик используйте экспортер узлов, который является экспортером Prometheus для системных метрик. Prometheus поддерживает данные с плавающей запятой, но не строковые данные, поэтому он подходит для системных метрик, но не журналов. Сервер метрик Kubernetes — это агрегатор данных об использовании ресурсов на уровне кластера.

Ведение журналов

Ниже приведены некоторые из общих проблем ведения журнала в приложении микрослужб:

  • Основные сведения о сквозной обработке запроса клиента, когда для обработки одного запроса можно вызвать несколько служб.
  • Объединение журналов из нескольких служб в единое агрегированное представление.
  • Анализ журналов, поступающих из нескольких источников, использующих собственные схемы ведения журнала или не имеющих конкретной схемы. Журналы могут создаваться сторонними компонентами, которые не контролируются.
  • Архитектуры микрослужб часто создают больший объем журналов, чем традиционные монолиты, так как есть больше служб, сетевых вызовов и шагов в транзакции. Это означает, что ведение журнала может быть узким местом производительности или ресурсов для приложения.

Существуют некоторые дополнительные проблемы для архитектур на основе Kubernetes:

  • Контейнеры могут перемещаться и планироваться повторно.
  • В Kubernetes имеется абстракция сети, использующая виртуальные IP-адреса и сопоставления портов.

В Kubernetes стандартный подход к ведению журнала предназначен для контейнера для записи журналов в stdout и stderr. Подсистема контейнеров перенаправляет эти потоки в драйвер ведения журнала. Чтобы упростить запросы и предотвратить возможную потерю данных журнала, если узел перестает отвечать, обычный подход заключается в сборе журналов с каждого узла и отправке их в центральное место хранения.

Azure Monitor интегрируется с AKS для поддержки этого подхода. Монитор собирает журналы контейнеров и отправляет их в рабочую область Log Analytics. Оттуда можно использовать язык запросов Kusto для записи запросов в объединенных журналах. Например, вот запрос Kusto для отображения журналов контейнеров для указанного модуля pod:

ContainerLogV2
| where PodName == "podName" //update with target pod
| project TimeGenerated, Computer, ContainerId, LogMessage, LogSource

Azure Monitor — это управляемая служба, и настройка кластера AKS для использования Monitor — это простое изменение конфигурации в шаблоне CLI или Azure Resource Manager. (Дополнительные сведения см. в разделе Как включить аналитику контейнеров Azure Monitor.) Еще одним преимуществом использования Azure Monitor является консолидация журналов AKS с другими журналами платформы Azure для обеспечения единого мониторинга.

Плата за Azure Monitor взимается за гигабайт (ГБ) данных, которые будут приема в службу. (См. раздел Цены на Azure Monitor.) В больших объемах стоимость может стать рассмотрением. Существует множество альтернатив с открытым исходным кодом для экосистемы Kubernetes. Например, многие организации используют Fluentd с Elasticsearch. Fluentd — это сборщик данных с открытым кодом, а Elasticsearch — это база данных документов, используемая для поиска. Проблема с этими параметрами заключается в том, что для них требуется дополнительная настройка и управление кластером. Для рабочей нагрузки может потребоваться поэкспериментировать с параметрами конфигурации. Кроме того, необходимо отслеживать производительность инфраструктуры ведения журнала.

OpenTelemetry

OpenTelemetry — это межиндустрионное усилие по улучшению трассировки путем стандартизации интерфейса между приложениями, библиотеками, телеметрией и сборщиками данных. При использовании библиотеки и платформы, инструментированных с помощью OpenTelemetry, большая часть работы операций трассировки, которые традиционно являются системными операциями, обрабатывается базовыми библиотеками, включая следующие распространенные сценарии:

  • Ведение журнала основных операций запроса, таких как время начала, время выхода и длительность
  • Исключения
  • Распространение контекста (например, отправка идентификатора корреляции через границы вызова HTTP)

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

Многие пакеты SDK Azure были инструментированы с помощью OpenTelemetry или находятся в процессе его реализации.

Разработчик приложений может добавить ручное инструментирование с помощью пакетов SDK OpenTelemetry для выполнения следующих действий:

  • Добавьте инструментирование, где базовая библиотека не предоставляет ее.
  • Обогатите контекст трассировки путем добавления диапазонов для предоставления единиц работы для конкретных приложений (например, цикла заказа, создающего диапазон для обработки каждой строки заказа).
  • Обогатите существующие диапазоны ключами сущностей, чтобы упростить трассировку. (Например, добавьте ключ/значение OrderID в запрос, который обрабатывает этот заказ.) Эти ключи отображаются средствами мониторинга в виде структурированных значений для запроса, фильтрации и агрегирования (без анализа строк сообщений журнала или поиска сочетаний последовательностей сообщений журнала, как и в случае с подходом к ведению журнала).
  • Распространение контекста трассировки путем доступа к атрибутам трассировки и диапазона, внедрению traceIds в ответы и полезные данные, а также считыванию идентификаторов трассировки из входящих сообщений для создания запросов и диапазонов.

Дополнительные сведения о инструментировании и пакетах SDK OpenTelemetry см. в документации по OpenTelemetry.

Application Insights

Приложение Аналитика собирает богатые данные из OpenTelemetry и его библиотек инструментирования и записывает их в эффективное хранилище данных, чтобы обеспечить многофункциональную визуализацию и поддержку запросов. Библиотеки инструментирования на основе OpenTelemetry приложения Аналитика для таких языков, как .NET, Java, Node.js и Python, упрощают отправку данных телеметрии в приложение Аналитика.

Если вы используете .NET Core, рекомендуется также рассмотреть Аналитика приложения для библиотеки Kubernetes. Эта библиотека дополняет трассировки приложений Аналитика дополнительными сведениями, например контейнером, узлом, модулем pod, метками и набором реплика.

Приложение Аналитика сопоставляет контекст OpenTelemetry с внутренней моделью данных:

  • Трассировка —> операция
  • Идентификатор трассировки —> идентификатор операции
  • Диапазон —> запрос или зависимость

Учитывайте следующие аспекты.

  • Приложение Аналитика регулирует данные телеметрии, если скорость данных превышает максимальное ограничение. Дополнительные сведения см. в разделе "Ограничения для приложений Аналитика". Одна операция может создавать несколько событий телеметрии, поэтому если приложение испытывает большой объем трафика, скорее всего, будет регулироваться.
  • Так как приложение Аналитика пакетных данных, вы можете потерять пакет, если процесс завершается сбоем с необработанным исключением.
  • Выставление счетов Аналитика приложения основано на томе данных. Дополнительные сведения см. в статье Управление ценами и объемом данных в Application Insights.

Структурированное ведение журнала

Чтобы упростить синтаксический анализ журналов, используйте структурированное ведение журнала при возможности. При использовании структурированного ведения журнала приложение записывает журналы в структурированном формате, например JSON, а не выводит неструктурированные текстовые строки. Доступно множество структурированных библиотек ведения журнала. Например, вот инструкция ведения журнала, использующая библиотеку Serilog для .NET Core:

public async Task<IActionResult> Put([FromBody]Delivery delivery, string id)
{
    logger.LogInformation("In Put action with delivery {Id}: {@DeliveryInfo}", id, delivery.ToLogInfo());

    ...
}

Здесь вызов LogInformation включает Id параметр и DeliveryInfo параметр. При использовании структурированного ведения журнала эти значения не интерполируются в строку сообщения. Вместо этого выходные данные журнала выглядят примерно так:

{"@t":"2019-06-13T00:57:09.9932697Z","@mt":"In Put action with delivery {Id}: {@DeliveryInfo}","Id":"36585f2d-c1fa-4a3d-9e06-a7f40b7d04ef","DeliveryInfo":{...

Это строка JSON, где @t поле является меткой времени, является строкой сообщения, @mt а остальные пары "ключ-значение" являются параметрами. Формат выходных данных JSON упрощает запрос данных структурированным образом. Например, следующий запрос Log Analytics, написанный на языке запросов Kusto, выполняет поиск экземпляров этого конкретного сообщения из всех контейнеров с именем fabrikam-delivery:

traces
| where customDimensions.["Kubernetes.Container.Name"] == "fabrikam-delivery"
| where customDimensions.["{OriginalFormat}"] == "In Put action with delivery {Id}: {@DeliveryInfo}"
| project message, customDimensions["Id"], customDimensions["@DeliveryInfo"]

Если просмотреть результат в портал Azure, вы увидите, что DeliveryInfo структурированная запись, содержащая сериализованное представление DeliveryInfo модели:

Screenshot that shows the Log Analytics workspace.

Ниже приведен пример JSON из этого примера:

{
  "Id": "36585f2d-c1fa-4a3d-9e06-a7f40b7d04ef",
  "Owner": {
    "UserId": "user id for logging",
    "AccountId": "52dadf0c-0067-43e7-af76-86e32b48bc5e"
  },
  "Pickup": {
    "Altitude": 0.29295161612934972,
    "Latitude": 0.26815900219052985,
    "Longitude": 0.79841844309047727
  },
  "Dropoff": {
    "Altitude": 0.31507750848078986,
    "Latitude": 0.753494655598651,
    "Longitude": 0.89352830773849423
  },
  "Deadline": "string",
  "Expedited": true,
  "ConfirmationRequired": 0,
  "DroneId": "AssignedDroneId01ba4d0b-c01a-4369-ba75-51bde0e76cc9"
}

Многие сообщения журнала помечают начало или конец единицы работы или подключают бизнес-сущность с набором сообщений и операций для отслеживания. Во многих случаях обогащение диапазона OpenTelemetry и запросов объектов является лучшим подходом, чем только ведение журнала начала и окончания операции. При этом добавляется этот контекст ко всем подключенным трассировкам и дочерним операциям, и он помещает эти сведения в область полной операции. Пакеты SDK OpenTelemetry для различных языков поддерживают создание диапазонов или добавление настраиваемых атрибутов в диапазонах. Например, в следующем коде используется пакет SDK Для OpenTelemetry Java, который поддерживается приложением Аналитика. Существующий родительский диапазон (например, диапазон запросов, связанный с вызовом контроллера REST и созданный веб-платформой), можно дополнить идентификатором сущности, связанной с ней, как показано ниже.

import io.opentelemetry.api.trace.Span;

// ...

Span.current().setAttribute("A1234", deliveryId);

Этот код задает ключ или значение в текущем диапазоне, которое подключено к операциям и сообщениям журнала, которые происходят в этом диапазоне. Значение отображается в объекте запроса application Аналитика, как показано ниже:

requests
| extend deliveryId = tostring(customDimensions.deliveryId)  // promote to column value (optional)
| where deliveryId == "A1234"
| project timestamp, name, url, success, resultCode, duration, operation_Id, deliveryId

Этот метод становится более мощным при использовании с журналами, фильтрацией и аннотированием трассировок журналов с контекстом диапазона, как показано ниже:

requests
| extend deliveryId = tostring(customDimensions.deliveryId)  // promote to column value (optional)
| where deliveryId == "A1234"
| project deliveryId, operation_Id, requestTimestamp = timestamp, requestDuration = duration  // keep some request info
| join kind=inner traces on operation_Id   // join logs only for this deliveryId
| project requestTimestamp, requestDuration, logTimestamp = timestamp, deliveryId, message

Если вы используете библиотеку или платформу, которая уже инструментирована с помощью OpenTelemetry, она обрабатывает создание диапазонов и запросов, но код приложения также может создавать единицы работы. Например, метод, который циклит по массиву сущностей, выполняющих работу над каждым из них, может создать диапазон для каждой итерации цикла обработки. Сведения о добавлении инструментирования в код приложения и библиотеки см. в документации по инструментированию OpenTelemery.

Распределенная трассировка

Одной из проблем при использовании микрослужб является понимание потока событий между службами. Одна транзакция может включать вызовы к нескольким службам.

Пример распределенной трассировки

В этом примере описывается путь распределенной транзакции через набор микрослужб. Пример основан на приложении доставки дронов.

Diagram that shows the architecture of a drone delivery application.

В этом сценарии распределенная транзакция включает следующие действия:

  1. Служба приема помещает сообщение в очередь Служебная шина Azure.
  2. Служба рабочего процесса извлекает сообщение из очереди.
  3. Служба рабочего процесса вызывает три внутренних службы для обработки запроса (планировщик дронов, пакет и доставка).

На следующем снимка экрана показана карта приложения для приложения доставки дронов. На этой карте показаны вызовы к общедоступной конечной точке API, которая приводит к рабочему процессу, включающем пять микрослужб.

Screenshot that shows the application map for the drone delivery application.

Стрелки из fabrikam-workflow очереди служебная шина fabrikam-ingestion показывают, где отправляются и получаются сообщения. На схеме, которую служба отправляет сообщения и которая получает. Стрелки просто показывают, что обе службы вызывает служебная шина. Но сведения о том, какая служба отправляется и которая получает, доступна в подробных сведениях:

Screenshot that shows the application map details.

Так как каждый вызов содержит идентификатор операции, вы также можете просмотреть сквозные шаги одной транзакции, включая сведения о времени и http-вызовы на каждом шаге. Ниже приведена визуализация одной такой транзакции:

Screenshot that shows an end-to-end transaction.

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

В этом примере показаны вызовы внутренней службы, которая завершается сбоем:

Screenshot that shows an application map with errors.

На этой карте показано, что большая доля (36%) вызовов службы планировщика дронов завершилась сбоем в течение периода запроса. Сквозное представление транзакций показывает, что исключение возникает при отправке HTTP-запроса PUT в службу:

Screenshot of the end-to-end transaction. It shows that an exception occurs when an HTTP PUT request is sent to the service.

При дальнейшей детализации вы увидите, что исключение является исключением сокета: "Нет такого устройства или адреса".

Fabrikam.Workflow.Service.Services.BackendServiceCallFailedException: 
No such device or address 
---u003e System.Net.Http.HttpRequestException: No such device or address 
---u003e System.Net.Sockets.SocketException: No such device or address

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

Ниже приведены некоторые распространенные причины ошибок:

  • Ошибки кода. Эти ошибки могут отображаться следующим образом:
    • Исключения. Просмотрите журналы приложения Аналитика, чтобы просмотреть сведения об исключении.
    • Сбой процесса. Просмотрите состояние контейнера и pod и просмотрите журналы контейнеров или трассировки приложений Аналитика.
    • Ошибки HTTP 5xx .
  • Исчерпание ресурсов:
    • Найдите время ожидания регулирования (HTTP 429) или время ожидания запроса.
    • Проверьте метрики контейнеров для ЦП, памяти и диска.
    • Просмотрите конфигурации для ограничений ресурсов контейнера и pod.
  • Обнаружение служб. Изучите конфигурацию службы Kubernetes и сопоставления портов.
  • Несоответствие API. Найдите ошибки HTTP 400. Если интерфейсы API имеют версию, просмотрите вызываемую версию.
  • Ошибка при извлечении образа контейнера. Просмотрите спецификацию pod. Кроме того, убедитесь, что кластер авторизован для извлечения из реестра контейнеров.
  • Проблемы с RBAC.

Следующие шаги

Дополнительные сведения о функциях в Azure Monitor, поддерживающих мониторинг приложений в AKS: