Руководство прикладного разработчика#
Термины и определения#
Термин/Аббревиатура |
Определение |
|---|---|
Endpoint |
Сетевая точка, обеспечивающая взаимодействие с поставщиком |
gRPC |
Современная высокопроизводительная платформа, которая используется для развития устаревшего протокола удаленного вызова процедур (RPC) |
Ingress (Egress) Gateway |
Ресурс Istio, который описывает правила маршрутизации и балансировки входящих запросов. Альтернатива K8s Ingress (Egress) Gateway, настраивается через ресурсы Gateway, Virtual Service и при необходимости DestinationRule |
K8s |
Kubernetes, платформа с открытым исходным кодом для управления кластерами приложений и сервисами на основе контейнеров |
OS |
OpenShift, открытая и расширяемая платформа приложений-контейнеров |
RL Operator |
Компонент SRLS, обеспечивающий конфигурирование Ingress (Egress) Gateway в соответствии с CRD в runtime |
RL Service |
Компонент SRLS, сервис расчета лимитов, принимает gRPC-запросы от Ingress (Egress) Gateway, содержащие информацию о домене (в качестве домена используется название прикладного namespace), о вызываемом сервисе и данные из служебного заголовка, например, synapse-consumerid |
SRLS (SRL) |
Программный компонент Synapse Rate Limiter (Synapse Rate Limit), сервис ограничения (квотирования) входящих запросов необходим для ограничения прикладной нагрузки (payload) со стороны потребителя на защищаемые сервисы, исполняемые в рамках Synapse Service Mesh |
Deploy Tools |
Программный компонент, предназначенный для автоматизации развертывания и автоматической установки технологических сервисов и бизнес-приложений на тестовых и промышленных стендах (CDJE), программного продукта Platform V DevOps Tools (DOT) |
Pod |
Набор контейнеров внутри узла кластера Kubernetes или Red Hat OpenShift (опционально) |
ТУЗ |
Технологическая учетная запись |
УЦ |
Удостоверяющий центр |
Системные требования#
Подробно системные требования описаны в документе «Руководство по установке» в разделе «Системные требования».
Подключение и конфигурирование#
В зависимости от выбранного варианта развертывания компонента SRLS (централизованный, децентрализованный) воспользуйтесь одной из инструкций:
конфигурирование артефактов среды контейнеризации и Istio для централизованного варианта развертывания;
конфигурирование артефактов среды контейнеризации и Istio для децентрализованного варианта развертывания.
Конфигурирование артефактов среды контейнеризации и Istio для централизованного варианта развертывания#
Пререквизиты#
Права доступа для Оператора Rate Limit выполнены по принципу минимальных прав для обеспечения требований безопасности. Для доступа к артефактам EnvoyFilter прикладного namespace требуется создать конфигурации ClusterRole и RoleBinding в yaml-формате.
ClusterRole:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: srls-role
rules:
- verbs:
- get
- list
- watch
- create
- update
- patch
- delete
apiGroups:
- networking.istio.io
resources:
- envoyfilters
RoleBinding, здесь необходимо указать ServiceAccount в namespace централизованного Rate Limit.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: srls-role-binding
namespace: ${namespace}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: srls-role
subjects:
- kind: ServiceAccount
name: rate-limiter-service
namespace: ${rls_namespace}
Здесь RLS-namespace — идентификатор namespace централизованного Rate Limit.
Для конфигурирования Rate Limit используется артефакт GlobalRateLimit. Для возможности его создания средствами DevOps для учетной записи Jenkins нужно добавить RoleBinding для следующей роли:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pipeline-rate-limiter-service-role
rules:
- verbs:
- create
- update
- patch
- delete
- get
- list
apiGroups:
- ratelimit.service
resources:
- globalratelimits
Конфигурирование для подключения с использованием NetworkPolicy#
Артефакт NetworkPolicy, приведенный в документе «Руководство по установке» в разделе «Сетевая видимость RL Service в рамках кластера», разрешает подключение из других namespace к Pod RL Service по порту 8081. В этом случае трафик не покидает сеть кластера Kubernetes (OpenShift опционально). Для обеспечения сетевой видимости необходимо наличие label srls: ratelimit у Pod Ingress Gateway и/или Egress Gateway, на которых выполняется квотирование. Его необходимо добавить в Deployment по пути .spec.template.metadata.labels, например:
kind: Deployment
apiVersion: apps/v1
metadata:
name: ingress-gateway
namespace: my-namespace
labels:
app: ingress-my-namespace
istio: ingress-my-namespace
proj: synapse-rls
agent: srls
spec:
replicas: 2
selector:
matchLabels:
app: ingress-my-namespace
istio: ingress-my-namespace
template:
metadata:
creationTimestamp: null
labels:
app: ingress-my-namespace
chart: gateways
istio: ingress-my-namespace
release: istio
srls: ratelimit
annotations:
sidecar.istio.io/inject: 'false'
spec:
restartPolicy: Always
В артефакте GlobalRateLimit в поле rlserver следует указать значение rate-limiter-headless-service.${rls-namespace}.svc.cluster.local, где rls-namespace — namespace централизованного SRLS, в поле rlserverport следует указать 8081.
Конфигурирование артефактов среды контейнеризации и Istio для децентрализованного варианта развертывания#
Децентрализованный вариант развертывания позволяет выбрать, как будут созданы необходимые для работы артефакты EnvoyFilter: автоматизированно или вручную.
Для автоматизированного варианта требуется предоставление соответствующих прав компоненту RL Operator.
Подробное описание приведено в документе «Руководство по установке» в разделе «Ролевая модель децентрализованного варианта развертывания».
В зависимости от выбранной ролевой модели необходимо выставить корректное значение стендозависимого параметра disable_envoy_filter_automation.
Описание параметра приведено в документе «Руководство по установке» в разделе «Параметры установки».
Для корректного отключения механизма квотирования входящих запросов при выключенном автоматизированном управлении артефактами EnvoyFilter (значение стендозависимого параметра disable_envoy_filter_automation выставлено в true) необходимо удалить как артефакт GlobalRateLimit, так и артефакты EnvoyFilter, которые были созданы по инструкции из раздела «Создание артефактов EnvoyFilter вручную».
Ниже приведена инструкция по созданию артефактов EnvoyFilter вручную.
Создание артефактов EnvoyFilter вручную#
Виды артефактов EnvoyFilter:
Кластер — необходим для настройки параметров подключения к компоненту RL Service.
Rate Limit Header — необходим для формирования запросов к RL Service в режиме работы
Rate Limit Header.Rate Limit Prefix — необходим для формирования запросов к RL Service в режиме работы
Rate Limit Prefix.Rate Limit Method — необходим для формирования запросов к RL Service в режиме работы
Rate Limit Method.Rate Limit Path — необходим для формирования запросов к RL Service в режиме работы
Rate Limit Path.
Минимальный набор артефактов включает в себя один Кластер и один артефакт для любого выбранного режима. Для каждого Endpoint, сконфигурированного в артефакте GlobalRateLimit, должен быть создан артефакт EnvoyFilter для соответствующего режима работы компонента SRLS. Допускается объединение всех артефактов EnvoyFilter в один yaml-файл.
Режимы работы описаны в разделе «Режимы работы» настоящего руководства.
Ниже приведены ссылки на соответствующие артефакты EnvoyFilter.
Артефакты EnvoyFilter приведены для версий 1.25 (версии ниже не поддерживаются).
Кластер
Ниже приведены параметры для конфигурирования артефакта EnvoyFilter для вида Кластер:
Название параметра |
Описание |
Пример |
|---|---|---|
namespace |
Идентификатор пространства имен |
my-namespace |
labels |
Список label для определения необходимого Ingress (Egress) Gateway |
app: ingress-my-namespace |
GrpcTimeout |
Максимальное время ожидания ответа на запрос к компоненту RL Service |
1s |
RlServer |
Адрес для подключения к компоненту RL Service |
rate-limiter-headless-service.my-namespace.svc.cluster.local |
RlServerPort |
Порт для подключения к компоненту RL Service |
8081 |
Cert |
Путь к клиентскому сертификату |
/etc/rls/ingress/ingress.pem |
Key |
Путь к приватному ключу сертификата |
/etc/rls/ingress/ingress.key |
TrustCA |
Путь к доверительному сертификату |
/etc/rls/ingress/ca-root.pem |
EnvoyFilter без закрытия соединения TLS.
EnvoyFilter с закрытием соединения TLS при прямом подключении.
Rate Limit Header
Ниже приведены параметры для конфигурирования артефакта EnvoyFilter для вида Rate Limit Header:
Название параметра |
Описание |
Пример |
|---|---|---|
namespace |
Идентификатор пространства имен |
my-namespace |
labels |
Список label для определения необходимого Ingress (Egress) Gateway |
app: ingress-my-namespace |
Endpoint |
Точка подключения входящего трафика |
my-server-my-namespace.domain.ru:8080 |
Shortname |
Уникальное короткое название точки подключения |
myserver |
Header |
Название заголовка для определения потребителя |
synapse-consumerid |
Опциональный блок |
Если в конфигурации GlobalRateLimit для данной точки подключения указано значение поля |
Rate Limit Prefix
Ниже приведены параметры для конфигурирования артефакта EnvoyFilter для вида Rate Limit Prefix:
Название параметра |
Описание |
Пример |
|---|---|---|
namespace |
Идентификатор пространства имен |
my-namespace |
labels |
Список label для определения необходимого Ingress (Egress) Gateway |
app: ingress-my-namespace |
Endpoint |
Точка подключения входящего трафика |
my-server-my-namespace.domain.ru:8080 |
Shortname |
Уникальное короткое название точки подключения |
myserver |
Header |
Название заголовка для определения потребителя |
synapse-consumerid |
Опциональный блок |
Если в конфигурации GlobalRateLimit для данной точки подключения указано значение поля |
Rate Limit Method
Ниже приведены параметры для конфигурирования артефакта EnvoyFilter для вида Rate Limit Method:
Название параметра |
Описание |
Пример |
|---|---|---|
namespace |
Идентификатор пространства имен |
my-namespace |
labels |
Список label для определения необходимого Ingress (Egress) Gateway |
app: ingress-my-namespace |
Endpoint |
Точка подключения входящего трафика |
my-server-my-namespace.domain.ru:8080 |
Shortname |
Уникальное короткое название точки подключения |
myserver |
Header |
Название заголовка для определения потребителя |
synapse-consumerid |
Опциональный блок |
Если в конфигурации GlobalRateLimit для данной точки подключения указано значение поля |
Rate Limit Path
Ниже приведены параметры для конфигурирования артефакта EnvoyFilter для вида Rate Limit Prefix:
Название параметра |
Описание |
Пример |
|---|---|---|
namespace |
Идентификатор пространства имен |
my-namespace |
labels |
Список label для определения необходимого Ingress (Egress) Gateway |
app: ingress-my-namespace |
Endpoint |
Точка подключения входящего трафика |
my-server-my-namespace.domain.ru:8080 |
Shortname |
Уникальное короткое название точки подключения |
myserver |
Опциональный блок |
Если в конфигурации GlobalRateLimit для данной точки подключения указано значение поля |
Добавление HTTP-заголовка в запрос на стороне потребителя без доработки кода (опционально)#
Данный заголовок должен формировать клиент (потребитель сервиса). Если клиент развернут в Red Hat OpenShift (опционально) и использует функционал Red Hat Service Mesh, то заголовок можно проставить на Egress Gateway namespace клиента с помощью артефакта VirtualService и блока headers, например:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: rldemo-server-vs
namespace: synapse-dev-sandbox
spec:
exportTo:
- .
gateways:
- rldemo-istio-egressgateway
hosts:
- rldemoserver.synapse-dev-sandbox3.apps.syn-sb.local.host.ru
http:
- headers:
request:
set:
synapse-consumerid: synapse-dev-sandbox
match:
- gateways:
- rldemo-istio-egressgateway
port: 8081
route:
- destination:
host: rldemoserver.synapse-dev-sandbox3.apps.syn-sb.local.host.ru
port:
number: 80
Миграция на текущую версию#
Миграция на текущую версию происходит путем обновления программного компонента Synapse Rate Limit, которое описано в разделе «Обновление» документа «Руководство по установке».
Быстрый старт#
Ниже приведены шаги для децентрализованного варианта развертывания компонента SRLS.
При настроенном Deploy Tools выполнить установку в прикладном namespace. Действия по установке описаны в подразделе «Автоматизированная установка сервиса с использованием Deploy Tools» документа «Руководство по установке».
Добавить артефакт GlobalRateLimit в прикладной namespace. Пример для тестового сервиса Server-Test:
kind: GlobalRateLimit
apiVersion: ratelimit.service/v1alpha1
metadata:
name: rate-limit-config
namespace: ${namespace}
spec:
envoyVersion: '1.25'
workloadSelector:
labels:
istio: ingressgateway
rlserver: rate-limiter-headless-service.${namespace}.svc.cluster.local
rlserverport: 8081
endpoints:
- endpoint: test-server-${namespace}.${cluster_domain_name}:8080 # вызываемый сервис
name: "some service" # описание сервиса
shortname: "server" # краткое название сервиса (3-10 латинских букв в нижнем регистре)
by_header:
header: synapse-consumerid # на текущий момент единственно возможный вариант
unit: second # возможные значения: second, minute, hour, day
value: 7 # применяется для всех клиентов, не указанных в invokers
visibility: namespace # на текущий момент единственно возможный вариант
invokers:
- name: "header_client1"
header_value: "client1"
unit: minute # возможные значения: second, minute, hour, day
value: 5
- name: "header_client2"
header_value: "client2"
unit: second # возможные значения: second, minute, hour, day
value: 2
Тестирование работы SRLS.
Перед тестированием убедитесь, что в namespace:
readiness/liveness-пробы Pods успешные и Pods по пробам периодически не перезапускаются.
Создались EnvoyFiltеr (
${namespace}-rls-cluster,${namespace}-server) для тестового сервиса.Обращение к Pod тестового сервиса проходит через Ingress Gateway (в логах Ingress Gateway присутствуют запросы к
test-server-${namespace}.${cluster_domain_name}:8080).
Добавьте ресурс kind: GlobalRateLimit name: rate-limit-config из пункта выше, заменив параметры ${namespace} и ${cluster_domain_name}.
C помощью утилиты Curl выполните запрос к тестовому сервису в консоли рабочей станции:
curl -v -H 'synapse-consumerid: client1' test-server-${rls_namespace}.${cluster_domain_name} 2>&1 | grep HTTP
Здесь client1 — метка клиента (invokers) для ресурса test-server-${rls_namespace}.${cluster_domain_name}:8080, заданного в ресурсе GlobalRateLimit.
Выполните N запросов от трех различных пользователей: client1, client2, client3. Убедитесь, что ограничения по каждому пользователю соответствуют указанным в настройках в ресурсе GlobalRateLimit.
При корректно выполненной настройке должен прийти ответ вида:
> GET / HTTP/1.1
< HTTP/1.1 200 OK
Согласно выставленным ограничениям для client1 (5 запросов в минуту), выполним 7 запросов к ресурсу:
for run in {1..7}; do curl -v -H 'synapse-consumerid: client1' test-server-${rls_namespace}.${cluster_domain_name} 2>&1 | grep HTTP; done
Ответ:
> GET / HTTP/1.1
< HTTP/1.1 200 OK
> GET / HTTP/1.1
< HTTP/1.1 200 OK
> GET / HTTP/1.1
< HTTP/1.1 200 OK
> GET / HTTP/1.1
< HTTP/1.1 200 OK
> GET / HTTP/1.1
< HTTP/1.1 200 OK
> GET / HTTP/1.1
< HTTP/1.1 429 Too Many Requests
> GET / HTTP/1.1
< HTTP/1.1 429 Too Many Requests
Выполнив повторно запрос до истечения заданного в настройках интервала (5 запросов в минуту для пользователя client1), можно убедиться, что запросы будут возвращать 429 ошибку. Это ожидаемое поведение.
Использование программного компонента#
Обращения к сервису Rate Limit формирует либо Ingress Gateway в прикладном namespace, доступ к ресурсам которого (namespace) необходимо ограничить, либо Egress Gateway в namespace, из которого делается вызов. Конфигурирование лимитов осуществляется через формирование артефакта GlobalRateLimit. Централизованный сервис Rate Limit разворачивается свой в каждом физическом кластере Kubernetes или Red Hat OpenShift (опционально).
Для возможности загрузки артефакта GlobalRateLimit необходимо создать роль K8s и привязать к ней ТУЗ Jenkins в namespace.
Роль:
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pipeline-rate-limiter-service-role
rules:
- verbs:
- create
- update
- patch
- delete
- get
- list
apiGroups:
- ratelimit.service
resources:
- globalratelimits
Формирование и применение артефакта GlobalRateLimit#
Конфигурирование лимитов осуществляется через артефакт GlobalRateLimit. Для применения лимитов необходимо создать артефакт GlobalRateLimit в namespace, где запущены прикладные сервисы, которые указаны в секции endpoints.
Пример конфигурации: GlobalRateLimit.
В примере для endpoint указаны три способа задания лимитов:
первый вариант (test-server1) — для обратной совместимости с версией RLS 2.0, нет возможности использовать произвольный заголовок для идентификации потребителя, нет возможности указать раздельно лимит для безымянных потребителей (отсутствует указанный заголовок в запросе) и неуказанных в конфигурации;
второй вариант (test-server2) — применение лимитов с идентификацией потребителя в заголовке, можно указать произвольный заголовок (валидный для протокола HTTP) и раздельно указать лимиты для безымянных потребителей (отсутствует указанный заголовок в запросе) и неуказанных в конфигурации, для этого введено новое поле anon_value;
третий вариант (test-server3) — применение лимитов в разрезе ResourceName, новый функционал, появившийся в релизе 2.1, для идентификации потребителя (тенанта) из URL-запроса;
четвертый вариант (test-server4) — применение лимитов с идентификацией потребителя в заголовке, отличие от второго варианта — лимиты конфигурируются для каждого указанного префикса URL в рамках одного endpoint независимо (с релиза 2.4 префиксы
/fooи/foo/barявляются независимыми с точки зрения Rate Limiter — запросы/foo/test1?param1=value1и/foo/bar/test2будут задействовать свои лимиты независимо друг от друга);пятый вариант (test-server5) — применение лимитов с идентификацией потребителя в заголовке, отличие от четвертого варианта — для одного из префиксов лимиты конфигурируются для указанных HTTP-методов в рамках одного префикса URL независимо.
При формировании артефакта необходимо указать:
workloadSelector — набор labels для определения нужных Pod Ingress (Egress) Gateway;
visibility — отвечает за область видимости данного CRD, возможные значения: cluster, namespace;
envoyVersion — отвечает за наполнение артефакта EnvoyFilter в зависимости от используемой версии Envoy, значение по умолчанию —
'1.25';endpoints — список ваших ресурсов;
rlserver — адрес RLS-сервера (для децентрализованной установки следует указать headless server rls например: «rate-limiter-headless-service», для централизованной установки здесь следует указать headless server с namespace rls, рекомендованный формат —
<headless_service_name>.<namespace>.svc.cluster.local);rlserverport — порт RLS-сервера, по умолчанию — 8081;
rlnamespace — namespace, в котором развернут централизованный оператор, данное поле необходимо указать для возможности развертывания нескольких экземпляров централизованного SRLS в рамках одного кластера Kubernetes или Red Hat OpenShift (опционально), если данное поле не задано, оператор проверит наличие прав на артефакт
EnvoyFilterв прикладном namespace;rlservercert — опциональный блок, позволяет задавать сертификаты для доступа к RLS-серверу при прямом подключении.
rlservercert состоит из следующих полей:
cert – путь к клиентскому (extendedKeyUsage = clientAuth) сертификату в файловой системе Ingress (Egress) Gateway;
key – путь к приватному ключу сертификата в файловой системе Ingress (Egress) Gateway;
trust_ca — путь к доверительному сертификату в файловой системе Ingress (Egress) Gateway.
Важно!
Потребитель сам должен обеспечить наличие данных сертификатов на Ingress (Egress) Gateway, подмонтировав их в необходимую директорию.
Для каждого endpoint:
обязательно наличие его короткого имени
shortname, используется в работе, для каждого endpoint значение shortname должно быть уникальным;endpoint — целевой адрес в формате
host:port, здесь host — DNS адрес, на который поступает входящий трафик (определяется в артефакте Route, используется в артефактах Gateway, VirtualService для манипуляции трафиком с помощью Service Mesh), port — порт, который слушает Ingress (Egress) Gateway (задается в артефакте Gateway), например, 8080 для HTTP трафика или 8443 для HTTPS трафика;overall_limit — максимальное ограничение квоты для endpoint; 0 — блокировка всех запросов, отрицательное значение — нет ограничения; если значение больше 0, дополнительно создается отдельный счетчик всех запросов на endpoint; в случае превышения запрос будет отклонен, даже если потребитель еще не исчерпал свою квоту; если используется режим работы Rate Limit Prefix, overall_limit считается общий для всех префиксов URL-запроса, указанных в конфигурации;
by_header — список настроек для функционала идентификации потребителя по HTTP-заголовку (подробное описание приведено в разделах «Rate Limit Header» и «Rate Limit Prefix» настоящего руководства);
by_path — список настроек для функционала идентификации потребителя по resourceName (подробное описание приведено в разделе «Rate Limit Path» настоящего руководства);
может быть задан лишь один из типов лимитов «by_header» или «by_path»;
overall_schedule – опциональный блок, позволяет изменять overall_limit по расписанию;
schedule – опциональный блок, позволяет изменять лимиты по расписанию.
Лимиты могут быть заданы в следующих единицах измерения:
second;
minute;
hour;
day.
Режимы работы#
Rate Limit Header#
Данный режим работы используется при задании лимитов с идентификацией потребителя по значению HTTP-заголовка. Если HTTP-заголовок отсутствует в запросе, идентифицировать пользователя невозможно, для таких запросов используется общая квота анонимных вызовов, определенная полем anon_value.
Для конфигурирования используйте специальный блок полей by_header.
Пример: some service1.
Параметры блока by_header:
header — произвольный HTTP-заголовок (валидный для протокола HTTP);
unit — опциональное поле, по умолчанию second, единица измерения лимитов, используется при расчете overall_limit, для запросов со значениями заголовка
header, не указанными в блокеinvokers, и для неидентифицированных потребителей;anon_value — опциональное поле, позволяет задать квоту для неидентифицированных (анонимных) потребителей, то есть в запросе отсутствует выбранный HTTP-заголовок; если поле не задано, используется значение поля
value;value — опциональное поле, по умолчанию 1, позволяет задать квоту для запросов со значениями заголовка
header, неуказанными в блокеinvokers, и для неидентифицированных потребителей;soft — опциональный блок, если задан, создается метрика, показывающая приближение к лимиту.
soft.value— значение квоты, после которой с шагом кратнымsoft.stepбудет инкрементирована метрика мониторинга превышения уровня soft квоты для конкретного потребителя вплоть до превышения основного лимита;invokers — опциональный блок, позволяет задать квоту для определенных потребителей независимо;
overall_schedule – опциональный блок, позволяет изменять overall_limit по расписанию.
overall_schedule и schedule состоят из следующих полей:
start – блок, позволяет задать время и дату начала изменения параметров, указанных в блоке;
stop – блок, позволяет задать время и дату окончания изменения параметров, указанных в блоке;
unit — поле, по умолчанию second, единица измерения лимитов;
value — поле, по умолчанию 1, позволяет задать квоту;
soft — опциональный блок, если задан, создается метрика, показывающая приближение к лимиту.
soft.value— значение квоты, после которой с шагом кратнымsoft.stepбудет инкрементирована метрика мониторинга превышения уровня soft квоты для конкретного потребителя вплоть до превышения основного лимита.
start и stop состоят из следующих полей:
second – блок, секунды, возможные значения – (0-59);
minute – блок, минуты, возможные значения – (0-59);
hour – блок, часы, возможные значения – (0-23);
day – блок, дни, возможные значения – (1-31);
month – блок, месяц, возможные значения – (1-12, где 1-январь);
weekday – блок, дни недели, возможные значения – (0-6, где 0-воскресенье).
Значение '*' для полей start и stop является допустимым и позволяет задать любую минуту, час, день, месяц, день недели.
Например:
overall_schedule в примере выше означает, что overall_limit 50 запросов в секунду будет изменен в период с 10 секунды до 30 секунды каждой минуты каждого часа каждого дня каждого месяца в течении всей недели на overall_limit 25 запросов в минуту.
Second |
Minute |
Hour |
Day |
Month |
Weekday |
Примечание |
|
|---|---|---|---|---|---|---|---|
start |
'1' |
'*' |
'*' |
'*' |
'*' |
'*' |
Начало каждую 1 секунду |
stop |
'10' |
'*' |
'*' |
'*' |
'*' |
'*' |
Окончание каждую 10 секунду |
start |
'1' |
'5' |
'3' |
'*' |
'*' |
'*' |
Начало каждый день в 3:05:01 |
stop |
'10' |
'20' |
'6' |
'*' |
'*' |
'*' |
Окончание каждый день в 6:20:10 |
start |
'1' |
'5' |
'3' |
'5' |
'*' |
'*' |
Начало каждый день в 3:05:01 |
stop |
'10' |
'20' |
'6' |
'7' |
'*' |
'*' |
Окончание каждый день в 6:20:10 |
start |
'1' |
'5' |
'3' |
'5' |
'*' |
'*' |
Начало 5 числа каждого месяца в 3:05:01 |
stop |
'10' |
'20' |
'6' |
'7' |
'*' |
'*' |
Окончание 7 числа каждого месяца в 6:20:10 |
start |
'1' |
'5' |
'3' |
'5' |
'11' |
'*' |
Начало 5 ноября в 3:05:01 |
stop |
'10' |
'20' |
'6' |
'7' |
'11' |
'*' |
Окончание 7 ноября в 6:20:10 |
start |
'1' |
'5' |
'3' |
'*' |
'*' |
'1' |
Начало каждый понедельник в 3:05:01 |
stop |
'10' |
'20' |
'6' |
'*' |
'*' |
'1' |
Окончание каждый понедельник в 6:20:10 |
Данные в
scheduleблокиstartиstopдолжны удовлетворять следующим требованиям:
startне должен срабатывать несколько раз до наступления событияstop;stopне должен срабатывать несколько раз до наступления событияstart;startиstopне может быть задан в несуществующую дату, например, в сентябре нет 31 дня, в феврале нет 29 дня и подобные.
В случае установки некорректных параметров в CRD GlobalRateLimit в блоке
scheduleилиoverall_schedule, в статусе CRD будет отражено место с указанием, где задан невалидный интервал времени и даты.
schedule в поле invokers: header_value: synapse-test означает, что лимит 8 запросов в секунду с soft.value=3 и soft.step=1 будет изменен каждый понедельник в период с 2 часов 5 минут 1 секунды до 6 часов 10 минут 30 секунд на 16 запросов в секунду с soft.value=5 и soft.step=2.
Для каждого invoker можно задать:
header_value — значение заголовка, указанного в поле
header;name — опциональное поле, позволяет указать метаданные для
header_value;unit — опциональное поле, по умолчанию second, единица измерения лимитов для
header_value;value — опциональное поле, по умолчанию 1, позволяет задать квоту для запросов со значением заголовка
header, равнымheader_value;soft — опциональный блок, если задан, создается метрика, показывающая приближение к лимиту.
soft.value— значение квоты, после которой с шагом кратнымsoft.stepбудет инкрементирована метрика мониторинга превышения уровня soft квоты дляheader_valueвплоть до превышения основного лимита;schedule – опциональный блок, позволяет изменять лимиты по расписанию.
Rate Limit Prefix#
Данный режим является расширением режима Rate Limit Header. Применяется в случаях, когда средствами Service Mesh входящий трафик на endpoint на Ingress Gateway распределяется по сервисам этого namespace на основе префикса URL-запроса.
Для настройки распределения трафика в Service Mesh используется артефакт VirtualService.
Пример артефакта VirtualService.
Для того чтобы для каждого префикса указать собственные значения квоты, в артефакте GlobalRateLimit в разделе by_header необходимо поле header и блок параметров uri_prefixes, в котором необходимо указать префикс в поле uri_prefix и лимиты по аналогии с режимом by-header.
Для работы функционала overall_limit необходимо указать поле unit, по умолчанию, если поле не задано, overall_limit будет рассчитываться в секундах. Счетчик overall_limit общий для всех префиксов. Остальные поля блока by_header будут проигнорированы.
Таким образом, для вызовов http://ingress-my-namespace-02.apps.domain.org/foo и http://ingress-my-namespace-02.apps.domain.org/bar/pruduct?param=1 будут применяться различные значения лимитов.
С релиза 2.4 префиксы /foo и /foo/bar являются независимыми с точки зрения Rate Limiter — для запросов http://ingress-my-namespace-02.apps.domain.org/foo/test1?param1=value1 и http://ingress-my-namespace-02.apps.domain.org/foo/bar/test2 также будут применяться различные значения лимитов.
Поле schedule в примере выше означает, что для префикса /foo/bar для client 3 будет изменен лимит 6 запросов в минуту в период с 10 секунды по 45 секунду каждой минуты каждого часа каждого дня каждого месяца на 10 запросов в секунду.
Если делается вызов с префиксом, для которого не указан лимит в артефакте GlobalRateLimit, то запросы на него будут идти без лимита. При этом в логах RL Service будут сообщения об ошибках no prefix found, valid prefixes: [/bar /foo/bar]", и метрика ошибок ratelimiterservice_should_rate_limit_unknown_prefix_error будет увеличиваться.
В случаях, когда нет необходимости считать лимиты для определенного префикса, можно указать для него в поле value значение -1.
- endpoint: 'ingress-my-namespace-02.apps.domain.org:8080'
name: srls dev 02
shortname: dev
overall_limit: 100
by_header:
header: synapse-consumerid
unit: minute
uri_prefixes:
- uri_prefix: "/healthcheck"
value: -1
- uri_prefix: "/bar"
unit: minute
value: 20
anon_value: 2
invokers:
- header_value: bar-client
name: client 2
unit: minute
value: 2
В данном примере запросы с префиксом /healthcheck будут ограничены только лимитом на весь endpoint (значением overall_limit). При этом если будут указаны блоки invokers и/или http_methods, то они будут игнорироваться.
В случаях, когда нет необходимости считать лимиты для всех префиксов, не указанных в артефакте GRL, можно для префикса / указать в поле value значение -1.
- endpoint: 'ingress-my-namespace-02.apps.domain.org:8080'
name: srls dev 02
shortname: dev
overall_limit: 100
by_header:
header: synapse-consumerid
unit: minute
uri_prefixes:
- uri_prefix: "/"
value: -1
- uri_prefix: "/bar"
unit: minute
value: 20
anon_value: 2
invokers:
- header_value: bar-client
name: client 2
unit: minute
value: 2
В данном примере лимит будет считаться только для запросов с префиксом /bar. Запросы со всеми остальными префиксами будут ограничены только лимитом на весь endpoint (значением overall_limit).
Префикс / так же может быть использован для подсчета общего лимита для всех остальных префиксов, если в поле value задано конкретное значение.
- endpoint: 'ingress-my-namespace-02.apps.domain.org:8080'
name: srls dev 02
shortname: dev
overall_limit: 100
by_header:
header: synapse-consumerid
unit: minute
uri_prefixes:
- uri_prefix: "/"
value: 10
unit: minute
- uri_prefix: "/bar"
unit: minute
value: 20
В данном примере лимит для вызовов с префиксом /bar будет 20 запросов в минуту. Запросы со всеми остальными префиксами будут ограничены лимитом 10 запросов в минуту.
Rate Limit Method#
Данный режим является расширением режима Rate Limit Prefix. Позволяет задать ограничения в разрезе HTTP-методов для отдельных префиксов URL запроса.
Для указания отдельных значений квот для различных методов в артефакте GlobalRateLimit в блоке соответствующего префикса необходимо добавить блок параметров http_methods. Блок является списком объектов, каждый из которых имеет поле непосредственно метода http_method и другие поля лимитов по аналогии с режимом Rate Limit Prefix (value, unit, anon_value, soft, schedule, invokers).
Пример конфигурации endpoint:
- endpoint: 'ingress-my-namespace-02.apps.domain.org:8080'
name: methodsservice
shortname: srvmethod
by_header:
header: synapse-consumerid
uri_prefixes:
- uri_prefix: "/foo"
unit: minute
value: 7
http_methods:
- http_method: GET
unit: minute
value: 4
- http_method: POST
unit: minute
value: 10
invokers:
- header_value: foo-POST-client
name: client 1
unit: minute
value: 5
- uri_prefix: "/bar"
unit: minute
value: 20
invokers:
- header_value: bar-client
name: client 2
unit: minute
value: 2
При отправке запросов на адрес http://ingress-my-namespace-02.apps.domain.org/foo/test методами GET и POST будут применяться различные значения лимитов.
При отправке запроса методом, для которого не указан лимит в артефакте GlobalRateLimit (например, PUT для /foo или любой запрос для /bar), будут применяться значения лимитов из самого префикса с учетом invokers из префикса.
Для снятия ограничений для отдельного метода можно указать для него в поле value значение -1. В таком случае блок invokers (при его наличии) для соответствующего метода будет проигнорирован.
- endpoint: 'ingress-my-namespace-02.apps.domain.org:8080'
name: methodsservice
shortname: srvmethod
by_header:
header: synapse-consumerid
uri_prefixes:
- uri_prefix: "/foo"
unit: minute
value: 7
http_methods:
- http_method: GET
unit: minute
value: 4
- http_method: POST
value: -1
В данном примере POST-запросы с префиксом /foo будут ограничены только лимитом на весь endpoint (значением overall_limit при его наличии).
Rate Limit CN#
Данный режим является расширением режимов Rate Limit Header и Prefix. Применяется в случаях, когда требуется идентифицировать потребителя по конкретным атрибутам поля Subject сертификата.
Для добавления в запрос заголовка со значением Subject необходимо вручную загрузить артефакт EnvoyFilter.
EnvoyFilter для Istio 1.17 (Envoy 1.25).
В соответствии с добавленным фильтром:
запросы, в которых не будет данных о клиентском сертификате, будут отклонены с ошибкой 403;
если в запросе уже будет заголовок
${header}, то он будет перезаписан.
Ниже приведены параметры для конфигурирования данного артефакта EnvoyFilter:
Название параметра |
Описание |
Пример |
|---|---|---|
namespace |
Идентификатор пространства имен |
my-namespace |
labels |
Список label для определения необходимого Ingress (Egress) Gateway |
app: ingress-my-namespace |
port |
Порт, на который отправляются запросы |
8443 |
header |
Название заголовка, в который будет записываться поле Subject |
synapse-consumerid |
При конфигурировании лимитов можно использовать как все поле Subject целиком, так и конкретный атрибут (или набор атрибутов) из него.
Для указания конкретных атрибутов необходимо добавить в артефакт GlobalRateLimit раздел modify_header.
Блок modify_header влияет на весь endpoint, указывается внутри by_header и содержит в себе два параметра:
type— тип преобразования заголовка (для режима Rate Limit CN необходимо указывать значениеcert— преобразования в терминах сертификата);rule— правило преобразования заголовка (для типаcertчерез запятую указываются необходимые атрибуты сертификата из поля Subject).
Правило преобразования rule поддерживает следующие атрибуты поля Subject сертификата:
CN: CommonName
OU: OrganizationalUnit
O: Organization
L: Locality
S или ST: StateOrProvinceName
C: CountryName
Пример поля Subject: CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, L=Moscow 10, S=Moscow, C=RU.
Примеры указания правила преобразования заголовка: rule: cn, rule: CN, o, rule: Ou,O
Пример конфигурации endpoint c modify_header:
- endpoint: 'ingress-my-namespace-02.apps.domain.org:8443'
name: srls dev 02
shortname: dev
by_header:
modify_header:
type: cert
rule: cn
anon_value: 1
header: synapse-consumerid
invokers:
- header_value: tribe-sy-dev-srls-dev-04
name: client 1
unit: minute
value: 13
unit: minute
value: 7
Предположим, что в сертификате задан Subject="CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, C=RU".
В таком случае, после применения EnvoyFilter, в пользовательский заголовок, например в synapse-consumerid, будет добавлено значение CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, C=RU.
Рассмотрим для этого примера варианты указания блока modify_header и соответствующие ему header_value для задания лимитов:
блок
modify_headerне задан — преобразование заголовка не выполняется, для задания лимита используется все значение поля Subject:
by_header:
header: synapse-consumerid
invokers:
- header_value: CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, C=RU
name: client 1
unit: minute
value: 13
unit: minute
value: 7
в
modify_headerне задано правило преобразованияrule(или задано пустое значение) — преобразование заголовка не выполняется, для задания лимита используется все значение поля Subject:
by_header:
modify_header:
type: cert
header: synapse-consumerid
invokers:
- header_value: CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, C=RU
name: client 1
unit: minute
value: 13
unit: minute
value: 7
в
modify_headerв правиле указан один атрибут, который присутствует в Subject — преобразование заголовка выполнится, для задания лимита используется значение указанного атрибута:
by_header:
modify_header:
type: cert
rule: cn
header: synapse-consumerid
invokers:
- header_value: tribe-sy-dev-srls-dev-04
name: client 1
unit: minute
value: 13
unit: minute
value: 7
в
modify_headerв правиле указано несколько атрибутов, которые присутствуют в Subject — преобразование заголовка выполнится, для задания лимита используется конкатенация значений указанных атрибутов:
by_header:
modify_header:
type: cert
rule: cn,o
header: synapse-consumerid
invokers:
- header_value: tribe-sy-dev-srls-dev-04sbertech
name: client 1
unit: minute
value: 13
unit: minute
value: 7
в
modify_headerв правиле указано несколько атрибутов, но не все они присутствуют в Subject — преобразование заголовка выполнится, для задания лимита используется конкатенация значений атрибутов, имеющихся в Subject:
by_header:
modify_header:
type: cert
rule: cn,l,st,o
header: synapse-consumerid
invokers:
- header_value: tribe-sy-dev-srls-dev-04sbertech
name: client 1
unit: minute
value: 13
unit: minute
value: 7
в
modify_headerв правиле указано несколько атрибутов, но они не присутствуют в Subject — преобразование заголовка выполнится с ошибкой и вернет исходное значение. Для задания лимита в таком случае, можно использовать все значение поля Subject. Но при этом метрика ошибок модификацииratelimiterservice_should_rate_limit_modify_header_errorбудет постоянно увеличиваться, и в логах rate-limiter-service c уровнем debug будет выводиться ошибка типа: "Error modify header: the specified cert artifact was not found in the header: CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, C=RU"
by_header:
modify_header:
type: cert
rule: l,st
header: synapse-consumerid
invokers:
- header_value: CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, C=RU
name: client 1
unit: minute
value: 13
unit: minute
value: 7
EnvoyFilter не добавлен, пользователь при запросе добавляет заголовок, например
synapse-consumerid: Kafka, но в артефакте GlobalRateLimit задан блокmodify_header— преобразование заголовка выполнится с ошибкой и вернет исходное значение. Для задания лимита в таком случае, можно использовать значение "Kafka". Но при этом метрика ошибок модификацииratelimiterservice_should_rate_limit_modify_header_errorбудет постоянно увеличиваться, и в логах rate-limiter-service c уровнем debug будет выводиться ошибка типа: "Error modify header: the specified cert artifact was not found in the header: CN=tribe-sy-dev-srls-dev-04, OU=R&D, O=sbertech, C=RU"
by_header:
modify_header:
type: cert
rule: cn
header: synapse-consumerid
invokers:
- header_value: Kafka
name: client 1
unit: minute
value: 13
unit: minute
value: 7
Rate Limit Path#
Данный режим позволяет идентифицировать потребителя (тенанта) по ResourceName из URL запроса.
Формат ResourceName состоит из трех частей: account-id, project-id, resource-id. В конфигурации Rate Limit можно задать значимую часть идентификатора потребителя с помощью маски для расчета лимита.
Варианты маски:
mask = "rn/::*" получим итоговое значение: account-idproject-idresource-id;
mask = "rn/::_" получим итоговое значение: account-idproject-id;
mask = "rn/*::" получим итоговое значение: account-id.
Формат URL запроса:
"http(s)://{HOST}:{PORT}/[{*Код продукта*}]/[{*версия*}]/rn/account-id:project-id:resource-id/{Контекст продукта}"
Пример конфигурации для режима Rate Limit Path.
Параметры блока by_path:
mask — опциональное поле, по умолчанию
rn/*:*:*, маска для определения значимой части идентификатора потребителя;unit — опциональное поле, по умолчанию
second, единица измерения лимитов, используется при расчете overall_limit и потребителей, неуказанных в блокеtenants;quotas — конфигурация квоты для потребителей, неуказанных в блоке
tenants;tenants — опциональный блок, позволяет задать квоту для определенных потребителей независимо.
Параметры блока quotas:
flat — опциональное поле, по умолчанию 1, позволяет задать квоту для запросов;
soft — опциональный блок, если задан, создается метрика, показывающая приближение к лимиту.
soft.value— значение квоты, после которой с шагом кратнымsoft.stepбудет инкрементирована метрика мониторинга превышения уровня soft квоты для конкретного потребителя вплоть до превышения основного лимита.
Для каждого tenant можно задать:
name — опциональное поле, позволяет указать метаданные для
resourceName;quotas — конфигурация квоты для потребителя, указанного в
resourceName;resourceName — идентификатор потребителя, значение необходимо указать в формате
account-id:project-id:resource-idбез разделителя, например accProjRes, если используется маска, необходимо указать только значимую часть, например accProj;unit — опциональное поле, по умолчанию second, единица измерения лимитов;
schedule – опциональный блок, позволяет изменять лимиты по расписанию.
Поле schedule в примере выше означает, что для tenant: name: server1.path будет изменен лимит 7 запросов в секунду в период с 2 часов 1 января по 12 часов 12 января на 20 запросов в минуту.
Применение нескольких артефактов GlobalRateLimit в рамках одного namespace#
В рамках одного namespace можно создать несколько артефактов GlobalRateLimit для независимого конфигурирования лимитов для сервисов. При этом можно создавать артефакты с разным значением поля workloadSelector, например, для работы как с Ingress Gateway, так и с Egress Gateway.
После создания артефакта происходит «слияние» артефактов с одним и тем же workloadSelector, на этапе «слияния» выполняется валидация конфигурации лимитов.
Осуществляется проверка на уникальность значений полей endpoint и shortname, уникальность значения поля resourceName для одного endpoint и валидация значений полей overall_schedule и schedule.
В случае ошибки валидации необходимо скорректировать значения невалидного артефакта GlobalRateLimit или удалить артефакт.
Ограничение списка namespace для централизованного SRLS#
Ограничение списка namespace для централизованного SRLS необходимо, чтобы была возможность развернуть несколько централизованных SRLS в рамках одного кластера Kubernetes или Red Hat OpenShift (опционально).
Алгоритм следующий:
Пользователь создает в своем namespace артефакт GlobalRateLimit.
RL Operator считывает поле «rlnamespace» из созданного артефакта GlobalRateLimit, сравнивает значение с идентификатором namespace, в котором RL Operator установлен.
Если значение не совпадает, RL Operator не берет в работу артефакт GlobalRateLimit.
Если значение совпадает, RL Operator формирует конфигурацию для RL Service.
Если поле «rlnamespace» не задано, RL Operator осуществляет проверку на наличие прав доступа к артефакту EnvoyFilter в namespace пользователя:
если права есть, формирует конфигурацию для RL Service;
если доступа нет, не берет в работу.
Часто встречающиеся проблемы и пути их устранения#
Код ошибки |
Пример ошибки |
Решение |
|---|---|---|
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 Pod StatefulSet redis-sentinel запущены корректно |
Некорректная балансировка запросов от Ingress Gateway до RL Service |
В случае перезапуска Pod RL Service или увеличения числа Pods, трафик на вновь созданный Pod почти не поступает |
Убедиться, что в артефакте GlobalRateLimit указан Headless Service RL Service, а не обычный. Headless Service — это Service, у которого параметр clusterIP выставлен в None |
Не срабатывает RateLimit |
- |
Проверить, что: |
Не запускается Pod |
Failed to pull image "registry.mydomain.ru/ci90000055_srls/operator@sha256:9f45c61299009bf91a63514680230151e02bc2bde35f38c14b381edacd291992": rpc error: code = Unknown desc = Error reading manifest sha256:9f45c61299009bf91a63514680230151e02bc2bde35f38c14b381edacd291992 in registry.mydomain.ru/domain/srls/operator: unauthorized: authentication required |
Предоставьте права на доступ к образу для пользователя, прописанного в ImagePullSecret rls-image-pull-secret |
Не применяется конфигурация GlobalRateLimit |
Ошибка в блоке status: endpoint [test-server1-endpoint-tribe-sy-srls-dev-03.apps.stands-vdc01.solution.test:8080] tenant.Name [server1.path] tenant.ResourceName [account-3] duplicate error: GlobalRateLimit manifest not valid |
Значение поля resourceName должно быть уникальным при конфигурировании endpoint. Скорректируйте значение поля resourceName |
Не запускается Pod RL Operator |
W0816 16:15:07.596714 1 reflector.go:424] sigs.k8s.io/controller-runtime/pkg/cache/internal/informers_map.go:262: failed to list *v1alpha1.GlobalRateLimit: globalratelimits.ratelimit.service is forbidden: User "system:serviceaccount:some-namespace:rate-limiter-service" cannot list resource "globalratelimits" in API group "ratelimit.service" at the cluster scope |
Убедитесь, что созданы артефакты ClusterRole и ClusterRoleBinding, предоставляющие права на артефакт GlobalRateLimit для ServiceAccount |
Warning в статусе GlobalRateLimit |
Сообщения с подобным текстом могут появляться в |
В сообщении говорится о некритичной ошибке конфигурации: |