Руководство по системному администрированию#
Термины и определения#
Термин/Аббревиатура |
Определение |
|---|---|
CPU |
Central Processing Unit, центральный процессор |
CRD |
Артефакт CustomResourceDefinition, позволяет определять пользовательские ресурсы — в нем можно указать тип и схему ресурса |
Endpoint |
Сетевая точка, обеспечивающая взаимодействие с поставщиком |
gRPC |
Современная высокопроизводительная платформа, которая используется для развития устаревшего протокола удаленного вызова процедур (RPC) |
Host |
Узел локальной сети, любое устройство, предоставляющее сервисы формата «клиент-сервер» в режиме сервера по каким-либо интерфейсам и уникально определенное на этих интерфейсах |
Ingress gateway |
Ресурс Istio, который описывает правила маршрутизации и балансировки входящих запросов. Альтернатива K8s Ingress, настраивается через ресурсы Gateway, Virtual Service и при необходимости DestinationRule |
IOPS |
Количество операций ввода/вывода |
K8s |
Kubernetes, платформа с открытым исходным кодом для управления кластерами приложений и сервисами на основе контейнеров |
OS |
OpenShift, открытая и расширяемая платформа приложений-контейнеров |
RAM |
Random Access Memory, оперативная память |
RL Operator |
Компонент SRLS, обеспечивающий конфигурирование Ingress Gateway в соответствии с CRD в runtime |
RL Service |
Компонент SRLS, сервис расчета лимитов, принимает gRPC-запросы от Ingress Gateway в прикладных namespace, содержащих информацию о домене (в качестве домена используется название namespace), о вызываемом сервисе и данные из заголовка synapse-consumerid |
SRLS (SRL) |
Программный компонент Synapse Rate Limiter Service (Synapse Rate Limit), сервис ограничения (квотирования) входящих запросов, необходим для ограничения прикладной нагрузки (payload) со стороны потребителя на защищаемые сервисы, исполняемые в рамках Synapse Service Mesh |
Unimon |
Программный компонент Объединенный мониторинг Unimon (MONA) программного продукта Platform V Monitor (OPM) |
Децентрализованный Rate Limit |
Компонент Rate Limit, специфичный для одного namespace |
Pod |
Набор контейнеров внутри узла кластера Kubernetes или Red Hat OpenShift (опционально) |
Сценарии администрирования#
Администратор контролирует:
работоспособность Pod по логам, статус liveness-проб среды контейнеризации Kubernetes или Red Hat OpenShift (опционально);
данные мониторинга и метрики;
своевременный перевыпуск сертификатов для Egress, RL Service, Fluent-bit (LOGA) (в случае конфигурации с включенным шифрованием в каналах передачи данных).
Сценарии администрирования связаны с установкой, настройкой и разбором инцидентов по программному компоненту SRLS. Действия описаны:
в документе «Руководство по установке» в разделе «Установка»;
в данном документе в разделе «Часто встречающиеся проблемы и пути их устранения»;
в документе «Руководство прикладного разработчика» в разделе «Часто встречающиеся проблемы и пути их устранения».
Системные требования#
Подробно системные требования описаны в документе «Руководство по установке» в разделе «Системные требования».
События системного журнала#
При включенной интеграции с компонентом Журналирование (LOGA) логи отправляются в Сервис для хранения лог-файлов Platform V Monitor.
Примечание Есть возможность отключить интеграцию с компонентом Журналирование (LOGA) (
FLUENT_BIT_SIDECAR_ENABLED=False), тогда логи остаются в рамках Pod.
Журналируются события уровней Error, Warn, Info, Debug, Trace. Уровень логирования задается при старте приложения в настройках, в runtime уровень логирования можно изменить через REST-сервис в терминале Pod.
Для уменьшения нагрузки на инфраструктуру не рекомендуется включать уровни Debug и Trace.
Пример лога оператора обработки загруженного артефакта GlobalRateLimit в прикладной namespace:
2023-10-19T21:02:06.562+0300 info this GRL is mine {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc"}
2023-10-19T21:02:06.563+0300 info reconcile creating external resources {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc"}
2023-10-19T21:02:06.568+0300 debug filter does not exist, try create {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc", "filterName": "da-dp2-sy-dev-srls-06-rls-cluster", "filterNamespace": "da-dp2-sy-dev-srls-06"}
2023-10-19T21:02:06.573+0300 debug filter does not exist, try create {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc", "filterName": "da-dp2-sy-dev-srls-06-serverf", "filterNamespace": "da-dp2-sy-dev-srls-06"}
2023-10-19T21:02:06.579+0300 debug filter does not exist, try create {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc", "filterName": "da-dp2-sy-dev-srls-06-servers", "filterNamespace": "da-dp2-sy-dev-srls-06"}
2023-10-19T21:02:06.582+0300 debug rateLimitConfig Updating Rate Limit config for GRL name [rate-limit-config] namespace [da-dp2-sy-dev-srls-06]... {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc"}
2023-10-19T21:02:06.583+0300 debug rateLimitConfig DependNamespace: [da-dp2-sy-dev-srls-05] {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc"}
2023-10-19T21:02:06.583+0300 debug operatorservice successfuly applied GlobalRateLimit {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc"}
2023-10-19T21:02:06.583+0300 debug reconcile Adding GRL to GRL Keeper {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc"}
2023-10-19T21:02:06.584+0300 info load new configs starting...
2023-10-19T21:02:06.584+0300 debug new config for namespace: [da-dp2-sy-dev-srls-05]
2023-10-19T21:02:06.585+0300 info load new configs success
2023-10-19T21:02:06.588+0300 info config load success to podName: [rate-limiter-service-8467777569-7fjcj] namespace: [da-dp2-sy-dev-srls-05] address: [127.0.0.6:55873]
2023-10-19T21:02:06.589+0300 info reconcile Finished processing of GRL {"controller": "globalratelimit", "controllerGroup": "ratelimit.service", "controllerKind": "GlobalRateLimit", "GlobalRateLimit": {"name":"rate-limit-config","namespace":"da-dp2-sy-dev-srls-06"}, "namespace": "da-dp2-sy-dev-srls-06", "name": "rate-limit-config", "reconcileID": "e934b300-aecc-456f-9629-e3ceffdb56bc"}
2023-10-19T20:52:36.799+0300 info redis server: 'mymaster,redis-sentinel-0.redis-sentinel:26379,redis-sentinel-1.redis-sentinel:26379,redis-sentinel-2.redis-sentinel:26379' status: in wait connection mode
2023-10-19T20:52:36.799+0300 error subscribe channelSizeConnectChange fail {"error": "redis: all sentinels specified in configuration are unreachable"}
2023-10-19T20:52:36.799+0300 error subscribe channelUpdateConfigs fail {"error": "redis: all sentinels specified in configuration are unreachable"}
События мониторинга#
Централизованный сбор метрик осуществляется путем их отправки в Объединенный мониторинг Unimon (MONA).
В соответствии с требованиями Unimon каждое приложение публикует метрики в формате Prometheus. Информация о том, как получить метрики с Pod, прописана в виде аннотаций в артефакте Service. Для сбора метрик в namespace должен быть развернут Prometheus Agent, который будет собирать метрики.
Собираемые метрики делятся на два типа:
Метрики полезной нагрузки, собираются при помощи микросервиса RL Service.
Метрики компонента SRLS, собираются внешним агентом – Prometheus Client.
Метрики полезной нагрузки#
Метрики полезной нагрузки содержат информацию о том, каким образом утилизируется ресурс приложения в части коммуникаций. Эти метрики разделены на две группы.
Группа метрик |
Как рассчитываются |
Состав метрик |
|---|---|---|
Метрики в разрезе поименованных потребителей |
По значению ключа, который имеет определенную структуру: |
— текущее значение квоты для заданного потребителя (для определения baseline на графике потребления ресурсов); |
Метрики группы анонимных потребителей |
По значению ключа, который имеет определенную структуру: |
— текущее значение квоты для группы анонимных потребителей (для определения baseline на графике потребления ресурсов); |
Метрики компонента Synapse Rate Limiter Service#
Определяют утилизацию ресурсов операционной системы, необходимых для работы самого экземпляра компонента Rate Limit. Метрики собираются с помощью Prometheus Client.
Prometheus Client — внешний по отношению к компоненту SRLS и стандартный механизм платформы Synapse по сбору метрик инфраструктуры. Для этого в сервисе RL Service необходимо предусмотреть endpoint для интеграции с Prometheus Client. Собранные метрики забирает Prometheus Client в виде JSON. Поддерживается стандартный протокол взаимодействия с Prometheus Client.
Собираемые метрики разделены на две группы.
Группа метрик |
Состав метрик |
|---|---|
Метрики утилизации вычислительных ресурсов (CPU, RAM, IOPS) |
— SRL operator: стандартные метрики Prometheus-Сlient (CPU, RAM и т.п.); |
Количественные метрики подконтрольных ресурсов |
— Количество подконтрольных namespace (доменов); |
Спецификация метрик#
Статистика в разрезе потребителей RL Service#
Значения метрик, а также их имена формируются в разрезе переменной части «key», которая состоит из следующих компонентов:
Domain — имя домена целевого сервиса (например, namespace).
Endpoint — имя целевой точки подключения (адрес сервиса, который прописан в GlobalRateLimit CRD).
Имя HTTP-header (имя заголовка, прописанного в GlobalRateLimit CRD).
Значение HTTP-header (значение заголовка, прописанного в GlobalRateLimit CRD).
Пример: Для CRD – GlobalRateLimit.
Key для пользователя с именем «client 1»:
default_endpoint_server_server_synapse_consumerid_test_client1
domain (namespace из CRD): default;
endpoint (shortname из CRD): server;
имя HTTP-header (имя заголовка, прописанного в CRD): synapse_consumerid;
значение HTTP-header (header_value из invokers (значение для клиента), прописанного в CRD): test_client1.
Метрика значения лимита для пользователя с именем «client 1» будет:
ratelimiterservice_rate_limit_default_endpoint_server_server_synapse_consumerid_test_client1_MINUTE
Имя метрики |
Описание |
|---|---|
"ratelimiterservice_rate_limit_"+key+"_"+unit |
Метрика с настройкой (показывает значение лимитов для конкретного ключа), «unit» в названии — это единица измерения времени |
"ratelimiterservice_rate_limit_"+key+total_hits" |
Общее количество обращений |
"ratelimiterservice_rate_limit_"+key+"_over_limit" |
Количество обращений, превышающих пороговое значение |
"ratelimiterservice_rate_limit_"+key+"_near_limit" |
Количество обращений, которые превышают значение коэффициента NearLimit (в настоящее время 80%), но ниже порогового значения |
"ratelimiterservice_rate_limit_"+key+"_over_limit_with_local_cache" |
Количество обращений, превышающих пороговое значение с локальным кешем |
"ratelimiterservice_rate_limit_"+key+"_within_limit" |
Количество успешных обращений (не превышающих пороговое значение) |
"ratelimiterservice_rate_limit_"+key+"_soft_limit_event" |
Количество превышений limit > soft.value квоты кратных soft.step для tenant) |
"ratelimiterservice_rate_limit_total_requests" |
Общее количество обращений на весь компонент SRLS |
"ratelimiterservice_rate_limit_success_requests" |
Количество успешных обращений на весь компонент SRLS |
"ratelimiterservice_rate_limit_"+key+"_total_requests" |
Общее количество обращений на endpoint |
"ratelimiterservice_rate_limit_"+key+"_success_requests" |
Количество успешных обращений на endpoint |
Для получения метрики в рамках namespace необходимо сложить метрики от всех запущенных Pod с компонента SRLS. Это связано с распределением запросов в результате балансировки между запущенными Pod.
Пример: В рамках namespace запущено два Pod c компонента SRLS (pod1, pod2). Для получения количества обращений для ключа key, превышающих пороговое значение (over_limit), нужно сложить значение метрики "ratelimiterservice_rate_limit_"+key+"_over_limit" у pod1 и pod2:
namespace.ratelimiterservice_rate_limit_"+key+"_over_limit = pod1.ratelimiterservice_rate_limit_"+key+"_over_limit + pod2.ratelimiterservice_rate_limit_"+key+"_over_limit
Формирование key для различных режимов работы SRLS#
Переменная часть key зависит от режима работы SRLS и версии Envoy. Правила формирования key представлены в таблице.
Режим работы |
Тип потребителя |
Ключ |
|---|---|---|
Rate Limit Header |
Анонимный |
|
Неизвестный |
|
|
Известный |
|
|
Rate Limit Prefix |
Анонимный |
|
Неизвестный |
|
|
Известный |
|
|
Rate Limit Method |
Анонимный |
|
Неизвестный |
|
|
Известный |
|
|
Rate Limit Path |
Неизвестный |
|
Известный |
|
Здесь параметры:
domain — имя домена целевого сервиса (например, имя namespace);
shortname — shortname для endpoint из GlobalRateLimit;
header — имя заголовка, по которому производится идентификация потребителя;
header_value — значение заголовка {header} (идентификатор потребителя для режима «Rate Limit Header» и его расширений);
unknown_header_value — идентификатор потребителя, отсутствующий в
invokers(метрики с данным параметром появляются только после поступления запросов от неизвестного потребителя);prefix — префикс URL-адреса, для которого заданы лимиты в GlobalRateLimit;
method — HTTP-метод (GET, POST и другие);
tenant — тенант,
resourceNameиз GlobalRateLimit (идентификатор потребителя для режима «Rate Limit Path»).
При формировании
keyвсе символы, удовлетворяющие регулярному выражению\W+, заменяются нижним подчеркиванием (_). Например,header_value«client-1» преобразуется в «client_1», аuri_prefix«/foo» — в «_foo».
Статистика RL Service#
Имя метрики |
Описание |
|---|---|
"ratelimiterservice_config_load_success" |
Статистика успешных загрузок конфигурации |
"ratelimiterservice_config_load_error" |
Статистика ошибок загрузки конфигурации |
"ratelimiterservice_should_rate_limit_redis_error" |
Статистика ошибок типа redis.RedisError (ошибки, которые могут возникнуть при парсинге конфигурации) |
"ratelimiterservice_should_rate_limit_service_error" |
Статистика ошибок типа ServiceError (ошибки типа: не указан конфиг, не указан домен, не указан дескриптор) |
"ratelimiterservice_should_rate_limit_unknown_prefix_error" |
Статистика ошибок типа UnknownPrefixError (ошибки типа: неизвестный префикс в запросе) |
"ratelimiterservice_should_rate_limit_url_mask_error" |
Статистика ошибок типа UrlMaskError (ошибки типа: указана некорректная маска) |
"ratelimiterservice_should_rate_limit_url_mask_appled_error" |
Статистика ошибок типа UrlMaskAppledError (ошибки типа: при наложении маски возникли ошибки (для типа «Path») у запроса отсутствует структура "rn/…:…:…/) |
"ratelimiterservice_should_rate_limit_modify_header_error" |
Статистика ошибок типа ModifyHeaderError (ошибки типа: невозможно применить правило модификации для указанного заголовка) |
"ratelimiterservice_ratelimit_server_"+method+"_total_requests" |
Общее количество запросов gRPC-сервера, где "method" — это имя gRPC-метода (например, |
"ratelimiterservice_ratelimit_server_"+method+"_response_time" |
Время, потраченное на ответ gRPC-сервером, где "method" — это имя gRPC-метода (например, |
"available" |
Доступность RL Service (0 — не доступен, 1 — доступен) |
Статистика по legacy-запросам (протокол rls.proto) RL Service#
Имя метрики |
Описание |
|---|---|
"ratelimiterservice_should_rate_limit_legacy_req_conversion_error" |
Статистика ошибок при конвертации legacy-запросов в актуальные запросы |
"ratelimiterservice_should_rate_limit_legacy_resp_conversion_error" |
Статистика ошибок при конвертации актуальных ответов в legacy-ответы |
"ratelimiterservice_should_rate_limit_legacy should_rate_limit_error" |
Статистика ошибок лимитера для legacy-запросов |
Метрики локального кеш (служебные метрики) RL Service#
Имя метрики |
Описание |
|---|---|
"ratelimiterservice_localcache_averageAccessTime" |
Возвращает среднее время доступа к записи (записи с большим временем доступа будут удалены, когда они будут перезаписаны новым значением) |
"ratelimiterservice_localcache_entryCount" |
Возвращает количество элементов, находящихся в настоящее время в кеше |
"ratelimiterservice_localcache_evacuateCount" |
Показатель, указывающий сколько раз происходило удаление из кеша |
"ratelimiterservice_localcache_expiredCount" |
Показатель, указывающий сколько раз произошло истечение срока действия для записи кеша |
"ratelimiterservice_localcache_hitCount" |
Метрика, которая возвращает количество раз, когда ключ был найден в кеше |
"ratelimiterservice_localcache_lookupCount" |
Метрика, которая возвращает количество попыток поиска в кеше по заданному ключу |
"ratelimiterservice_localcache_missCount" |
Метрика, которая возвращает количество раз, когда ключ не был найден в кеше |
"ratelimiterservice_localcache_overwriteCount" |
Метрика, которая указывает, сколько раз записи были перезаписаны |
Метрики RL Operator#
Имя метрики |
Описание |
|---|---|
rloperator_is_leader |
1 — данный экземпляр оператора активный |
rloperator_new_grl_counter |
Счетчик новых артефактов Global Rate Limits |
rloperator_update_grl_counter |
Счетчик обновленных артефактов Global Rate Limits |
rloperator_delete_grl_counter |
Счетчик удаленных артефактов Global Rate Limits |
rloperator_apply_success_counter |
Счетчик успешно обработанных артефактов Global Rate Limits (новые или обновленные) |
rloperator_apply_failure_counter |
Счетчик артефактов Global Rate Limits, обработка которых завершилась ошибкой |
available |
Доступность RL Operator (0 — не доступен, 1 — доступен) |
rloperator_config_download_success |
Счетчик успешных загрузок конфигурации на уровне namespace (RL Operator → RL Service) |
rloperator_config_download_error |
Счетчик ошибок загрузки конфигурации на уровне namespace (RL Operator → RL Service) |
rloperator_redis_error |
Счетчик ошибок типа redis.RedisError |
rloperator_service_error |
Счетчик ошибок ServiceError |
rloperator_cron_job_error |
Счетчик ошибок cron job |
rloperator_config_unmarshal_error |
Счетчик ошибок преобразования конфигурации (YAML-документ) в программный объект |
rloperator_srls_connect_count |
Число RL Service, подключенных к RL Operator |
Метрики Redis#
"prefix" может принимать только два значения:
redis_pool_ — используется для pool соединений «основного» Redis;
redis_per_second_pool_ — используется для pool соединений «дополнительного» Redis; (при включенном режиме работы с двумя Redis одновременно используется для расчетов «в секунду»).
Имя метрики |
Описание |
|---|---|
"ratelimiterservice_"+prefix+"cx_active" |
Число активных соединений в рамках pool |
"ratelimiterservice_"+prefix+"cx_total" |
Общее число соединений в рамках pool |
"ratelimiterservice_"+prefix+"cx_local_close" |
Число закрытых соединений в рамках pool |
Часто встречающиеся проблемы и пути их устранения#
Код ошибки |
Пример ошибки |
Решение |
|---|---|---|
'grpc-status', '12' |
2022-02-22T13:51:47.544976Z debug envoy http [external/envoy/source/common/http/conn_manager_impl.cc:1729] [C8647][S166541960535733715] encoding headers via codec (end_stream=true): ':status', '200' 'content-type', 'application/grpc' 'grpc-status', '12' 'date', 'Tue, 22 Feb 2022 13:51:47 GMT' 'server', 'istio-envoy' |
Для анализа необходимо проследить цепочку от Ingress в прикладном namespace до Rate Limit в централизованном namespace. Для анализа необходимо включить расширенное логирование на Egress в прикладном namespace и Ingress в namespace централизованного Rate Limit. Это можно сделать с помощью: |
Pod RL Service завершается с ошибкой |
time="2022-08-04T14:30:21Z" level=warning msg="connecting to redis on mymaster,redis-sentinel-0.redis-sentinel:26379,redis-sentinel-1.redis-sentinel:26379,redis-sentinel-2.redis-sentinel:26379 with pool size 10" panic: dial tcp: lookup redis-sentinel-2.redis-sentinel on 29.66.0.10:53: no such host |
Необходимо удостовериться, что 3 Pods вида |
Не срабатывает RateLimit |
— |
Проверить, что: |