Руководство по системному администрированию#
Термины и определения#
Термин/Аббревиатура |
Определение |
|---|---|
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 (опционально);
данные мониторинга и метрики;
своевременный перевыпуск сертификатов для Ingress.
Сценарии администрирования связаны с установкой, настройкой и разбором инцидентов по программному компоненту SRLS. Действия описаны:
в документе «Руководство по установке» в разделе «Установка»;
в данном документе в разделе «Часто встречающиеся проблемы и пути их устранения»;
в документе «Руководство прикладного разработчика» в разделе «Часто встречающиеся проблемы и пути их устранения».
Системные требования#
Подробно системные требования описаны в документе «Руководство по установке» в разделе «Системные требования».
События системного журнала#
При включенной интеграции с компонентом Журналирование (LOGA) логи отправляются в Сервис для хранения лог-файлов Platform V Monitor.
Примечание Есть возможность отключить интеграцию с компонентом Журналирование (LOGA) (
FLUENT_BIT_SIDECAR_ENABLED=False), тогда логи остаются в рамках pod.
Журналируются события уровней Error, Warn, Info, Debug, Trace. Уровень логирования задается при старте приложения в настройках, в runtime уровень логирования можно изменить через REST-сервис в терминале pod.
Для уменьшения нагрузки на инфраструктуру не рекомендуется включать уровни Debug и Trace.
Пример лога оператора обработки загруженного артефакта GlobalRateLimit в прикладной namespace:
{"level":"debug","time":"2021-08-27T12:13:57+03:00","message":"GlobalRateLimit ADDED: namespace=[synapse-dev-sandbox3] name=[rate-limit-config] \n"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Updated configmap with the following: map[kordon2.yaml:domain: kordon2\ndescriptors:\n - key: generic_key\n value: server\n rate_limit:\n requests_per_unit: 7\n unit: second\n descriptors:\n - key: header_match\n value: header-absent\n rate_limit:\n requests_per_unit: 7\n unit: second\n - key: server.synapse-consumerid\n value: alpha\n rate_limit:\n requests_per_unit: 5\n unit: second\n - key: server.synapse-consumerid\n value: kordon1\n rate_limit:\n requests_per_unit: 2\n unit: second\n - key: server.synapse-consumerid\n rate_limit:\n requests_per_unit: 7\n unit: second\n synapse-dev-sandbox3.yaml:domain: synapse-dev-sandbox3\ndescriptors:\n - key: generic_key\n value: server\n rate_limit:\n requests_per_unit: 7\n ...
{"level":"debug","time":"2021-08-27T12:13:57+03:00","message":"Convert data to EnvoyFilter-s param"}
{"level":"info","time":"2021-08-27T12:13:57+03:00","message":"Add EnvoyFilter-s from params..."}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"[[EFParams [isOldEnvoyVersion: true domain: synapse-dev-sandbox3 namespace: synapse-dev-sandbox3 shortname: server endpoint: rldemoserver.synapse-dev-sandbox3.apps.syn-sb.local.host.ru:8080 rlServer: rate-limiter-service.synapse-dev-sandbox.svc.cluster.local rlServerPort: 8081 header: synapse-consumerid] EFParams [isOldEnvoyVersion: true domain: synapse-dev-sandbox3 namespace: synapse-dev-sandbox3 shortname: second endpoint: rldemosecond.synapse-dev-sandbox3.apps.syn-sb.local.host.ru:8080 rlServer: rate-limiter-service.synapse-dev-sandbox.svc.cluster.local rlServerPort: 8081 header: synapse-consumerid]]]"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Search EnvoyFilter [synapse-dev-sandbox3-rls-cluster] for namespace [synapse-dev-sandbox3]"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Filter found"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Create EnvoyFilter from params"}
{"level":"debug","time":"2021-08-27T12:13:57+03:00","message":"UPDATE EnvoyFilter [synapse-dev-sandbox3-rls-cluster] to namespace [synapse-dev-sandbox3]"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"EnvoyFilter [synapse-dev-sandbox3-rls-cluster] updated successfully"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Search EnvoyFilter [synapse-dev-sandbox3-server] for namespace [synapse-dev-sandbox3]"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Filter found"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Create EnvoyFilter from params"}
{"level":"debug","time":"2021-08-27T12:13:57+03:00","message":"UPDATE EnvoyFilter [synapse-dev-sandbox3-server] to namespace [synapse-dev-sandbox3]"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"EnvoyFilter [synapse-dev-sandbox3-server] updated successfully"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Search EnvoyFilter [synapse-dev-sandbox3-second] for namespace [synapse-dev-sandbox3]"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Filter found"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"Create EnvoyFilter from params"}
{"level":"debug","time":"2021-08-27T12:13:57+03:00","message":"UPDATE EnvoyFilter [synapse-dev-sandbox3-second] to namespace [synapse-dev-sandbox3]"}
{"level":"trace","time":"2021-08-27T12:13:57+03:00","message":"EnvoyFilter [synapse-dev-sandbox3-second] updated successfully"}
{"level":"debug","time":"2021-08-27T12:13:57+03:00","message":"Updating status GlobalRateLimit name=[rate-limit-config] in namespace=[synapse-dev-sandbox3]"}
{"level":"error","time":"2021-08-27T12:13:58+03:00","message":"Failed to update status of CRD namespace=[synapse-dev-sandbox3] name=[rate-limit-config]","error":"globalratelimits.ratelimit.service [rate-limit-config] is forbidden: User [system:serviceaccount:synapse-dev-sandbox3:rate-limiter-service] cannot update resource [globalratelimits/status] in API group [ratelimit.service] in the namespace [synapse-dev-sandbox3]"}
События мониторинга#
Централизованный сбор метрик осуществляется путем их отправки в Объединенный мониторинг 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 –
apiVersion: ratelimit.service/v1alpha1
kind: GlobalRateLimit
metadata:
name: rate-limit-config
namespace: default
spec:
endpoints:
- by_header:
anon_value: 3
header: synapse-consumerid
invokers:
- header_value: test-client1
name: client 1
soft:
step: 2
value: 10
unit: minute
value: 20
- header_value: test-client2
name: client 2
unit: minute
value: 15
- header_value: test-client3
name: client 3
unit: minute
value: 10
unit: minute
value: 5
endpoint: >-
test-server1-endpoint-default.apps.stands.solution.sbt:8080
name: test service
overall_limit: 50
shortname: server
unit: minute
envoyVersion: '1.14'
rlserver: egress-service.default.svc.cluster.local
rlserverport: 12001
type_mode: full
visibility: cluster
workloadSelector:
labels:
app: ingress-default
istio: ingress-default
Key для пользователя с именем «client 1»:
default_generic_key_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_generic_key_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
Статистика 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" — это имя HTTP-метода (GET, POST и т.д.) |
"ratelimiterservice_ratelimit_server_"+method+"_response_time" |
Время, потраченное на ответ gRPC-сервером, где "method" — это имя HTTP-метода (GET, POST и т.д.) |
"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 { IP_ADDRESS }:53: no such host |
Необходимо удостовериться, что 3 pods вида |
Не срабатывает RateLimit |
— |
Проверить, что: |