Установка RPLW в DropApp
Порядок установки
- Проверьте и подготовьте параметры в common репозитории стенда для воркера (RPLW).
- Используя средства Pipeline, выполните миграцию конфигурационных файлов GraDeLy на узел.
- Внесите в конфигурационные файлы GraDeLy на узле необходимые изменения.
- Проверьте и подготовьте параметры k8s в namespace.
- Удалите устаревшие ресурсы Kubernetes.
- Настройте секреты в системе управления секретами HashiCorp Vault.
- Настройте интеграцию с компонентом IGEG.
- Настройте интеграцию с компонентом Журналирование (LOGA).
- Настройте интеграцию с компонентом Объединенный мониторинг Unimon (MONA).
- Настройте интеграцию с Kafka.
- Настройте интеграцию с компонентом OTTS.
- Настройте интеграцию с HashiCorp Vault.
- Предустановите конфигурацию.
- Произведите полную установку GraDeLy.
- Определите максимальную производительность.
Убедитесь, что создан пользователь (роль) в БД источника и приемника для выполнения репликации и выданы ему необходимые права (обязательный). Воспользуйтесь Подготовкой БД источника и БД приемника для работы с GraDeLy.
Шаг 1. Проверьте и подготовьте параметры в common репозитории стенда для воркера (RPLW) (обязательный)
Последовательность действий
-
Параметры
${стенд}/installer/system/efs/config/parameters/ssl.confДля RPLW:
ssl.ose.istio.rplw.kafka.fqdns - FQDN серверов kafka через запятуюssl.ose.istio.rplw.kafka.ips - IP-адреса серверов kafka через запятую в порядке, совпадающем с предыдущем значением; если IP не используется, выставляется значение nonessl.ose.istio.rplw.psql.fqdns - FQDN серверов БД источников/приемников Postgres через запятуюssl.proxy.type - тип proxy на ингресс-контроллере (nginx или haproxy)ssl.ose.secman.host - адрес сервера secmanssl.ose.secman.port - порт для подключения к серверу secmanrplw.ose.deployment.spec.template.metadata.annotations.vault.hashicorp.com.namespace - имя namespace в vault, где хранятся секреты проектаrplw.ose.deployment.spec.template.metadata.annotations.vault.hashicorp.com.role.module - имя роли в vault, от которой будут выполняться API-вызовы vault-agent для namespace modulerplw.ose.deployment.spec.template.metadata.annotations.vault.hashicorp.com/client-max-retries - максимальное количество попыток переподключения к серверу vaultrplw.ose.deployment.spec.template.metadata.annotations.vault.hashicorp.com/agent-limits-cpu - максимальное значение ресурсов по CPU для sidecar vault-agentrplw.ose.deployment.spec.template.metadata.annotations.vault.hashicorp.com/agent-limits-mem - максимальное значение ресурсов по RAM для sidecar vault-agentrplw.ose.deployment.spec.template.metadata.annotations.vault.hashicorp.com/agent-requests-cpu - минимальное значение ресурсов по CPU для sidecar vault-agentrplw.ose.deployment.spec.template.metadata.annotations.vault.hashicorp.com/agent-requests-mem - минимальное значение ресурсов по CPU для sidecar vault-agent -
Параметры
${стенд}/parameters/common.conf.ymlДля RPLW:
DB_SCHEMA_worker - схема БД приемника, для проливки скриптов LBRPLW_POSTGRES_DB_URL_worker - адрес в БД приемника в формате jdbc:postgresql://x.x.x.x:port/db_name, если кластер БД то jdbc:postgresql://x.x.x.x:port,x.x.x.x:port/db_name?targetServerType=master&prepareThreshold=0registry - адрес registryregistry_path - путь до директории с компонентом в registryregistry_path_igeg - путь до компонента образа istioregistry_path_otts - путь до компонента образа ottregistry_path_loga - путь до компонента образа fluent-bit -
Параметры
${стенд}/installer/system/efs/config/parameters/_global.resources.confglobal.platform.auth.host - адреса backend Keycloak через запятуюglobal.platform.iam.auth.host - адрес Keycloakglobal.platform.iam.auth.port - порт Keycloakglobal.platform.audit.proxy.https.host - адрес Audit c ОТТglobal.platform.audit.proxy.https.host_no_ott - адрес Audit без ОТТglobal.platform.audit.proxy.https.port - порт Auditglobal.platform.audit.proxy.https.url.path - путь до endpoint аудита PVMglobal.platform.secman.kv.basepath - адрес хранилища секретов kv в Secmanglobal.platform.secman.pki.basepath - адрес хранилища секретов pki в Secmanglobal.platform.secman.kv.jdbcpath - имя секрета сертификатов БД конфигураций в kv Secmanglobal.platform.secman.kv.auditpath - имя секрета сертификатов Audit конфигураций в kv Secmanglobal.platform.secman.kv.ottpath - имя секрета сертификатов OTT конфигураций в kv Secmanglobal.platform.secman.pki.ott - путь до секрета в PKI (OTT)global.platform.secman.kv.ingresspath - путь до KV Ingressglobal.platform.secman.pki.audit - путь до секрета в PKI (Audit)global.platform.secman.pki.logger - путь до секрета в PKI (Logger)global.platform.secman.kv.iamsecret - секрет от Keycloakglobal.platform.secman.kv.loggerpath - путь до секрета в KV (Logger) -
Параметры
${стенд}/installer/system/efs/config/parameters/_global.ott.confДля RPLW:
global.platform.rplw.ott.module.id - Имя модуля, указанное в поле CN запроса и сертификата клиента ОТТglobal.platform.rplw.ott.service.hosts - Адрес сервера OTTS -
Параметры
${стенд}/installer/system/efs/config/parameters/openShift.confglobal.platform.logger.kafka.bootstrap.serversglobal.platform.logger.kafka.topicglobal.platform.ose.kafka.ports# Лимит использования Pod-ами эфемерного хранилищаglobal.ose.deployment.spec.template.spec.containers.resources.limits.ephemeral-storage -
Параметры для каждого из двух namespaces
${стенд}/multiClusters.json{"datacenters": {"<nameCluster>": {"openshiftCluster": "<url>","openshiftSATokenCred": "<token>","openshiftProjectName": "<namespace>","openshiftControlPlaneProject": "<nameCP>","openshiftControlPlaneIstiodPort": "<portCP>","openshiftControlPlaneIstiodService": "<istiodName>","openshiftControlPlaneJaegerPort": "<jaegerPort>","openshiftControlPlaneJaegerService": "<jaegerService>","openshiftNewRoute": "<routeFQDN>","openshiftAppsDomain": "<domain>","openshiftRoutersFQDN": ["<addressCluster>"],"overrides": []}}}где
<nameCluster> – имя кластера k8s;<url> – адрес кластера k8s;<token> – токен с доступом для деплоя в namespace;<namespace> – имя namespace k8s;<nameCP> – имя controlPanel k8s;<portCP> – порт controlPanel k8s;<istiodName> – имя istiod k8s;<jaegerPort> – порт jaeger k8s;<jaegerService> – имя jaegerService k8s;<routeFQDN> – часть имени FQDN для формирования Route;<domain> – домен кластера ("apps.dap.devpub.example.ru");<addressCluster> – адрес кластера k8s.
Проверка результата
Параметры в common репозитории стенда для воркера подготовлены.
Шаг 2. Мигрируйте конфигурационные файлы GraDeLy (обязательный)
Последовательность действий
Перед развертыванием самого приложения необходимо произвести шаблонизацию и миграцию параметров из дистрибутива на среду (параметров среды и параметров программного обеспечения).
Данные для шаблонизации и миграции находятся в папке дистрибутива conf/config/parameters.
Параметры в конфигурационных файлах дистрибутива могут содержать плейсхолдеры на общие параметры установки, конкретные значения которых должны подставляться при установке. Конкретные значения параметров установки хранятся отдельно в файлах стендов, наличие этих данных обеспечивается администраторами стендов, куда производится установка продукта.
Для RPLW:
└── conf
└── config
└── parameters
├── rplw.all.conf
├── rplw.istio.all.conf
├── rplw-module.conf
├── rplw.fluentbit-sidecar.all.conf
Проверка результата
Конфигурационные файлы мигрированы.
Шаг 3. Внесите в конфигурационные файлы GraDeLy на узле необходимые изменения (обязательный)
Последовательность действий
Для реализации поддержки нескольких схем доступа к секретам приложения и потребителей нужно заполнить нижеследующие параметры в rplw-module.conf:
# Для каждой интеграции адрес секрета KV, хранимый в vault, представляется в виде конкатинации двух параметров <имя_модуля>.ose.secman.kv.<имя_интеграции>.basepath и <имя_модуля>.ose.secman.kv.<имя_интеграции>.secret_name
# Для каждой интеграции секрета PKI, генерируемы vault, происходит по двум параметрам: <имя_модуля>.ose.secman.pki.<имя_интеграции>.basepath - движок PKI (имеет список разрешенных common names) и <имя_модуля>.ose.secman.pki.<имя_интеграции>.common_name - common name
# Для входящего трафика и интеграции с ОТТ, внесен тогглер (true/false) <имя_модуля>.ose.secman.kv.<ingress/ott>.add-old-ca-chain, который контролирует подключение KV секрета, для добавления цепочки сертификатов в корневой сертификат (согласно архитектуре: на grdl-console-ui нет ОТТ)
# Для интеграции с БД, Kafka и "из консоли в воркера" KV конкатинация состоит из <имя_модуля>.ose.secman.kv.<имя_интеграции>.basepath и FQDN имени сервиса интеграции, соотвественно данных параметров в ConfigMap нет
rplw-module.ose.secman.kv.psql-cred.basepath=
rplw-module.ose.secman.pki.ingress.basepath=
rplw-module.ose.secman.pki.ingress.common_name=
rplw-module.ose.secman.kv.ingress.add-old-ca-chain=
rplw-module.ose.secman.kv.ingress.old-ca-chain.secret_name=
rplw-module.ose.secman.kv.ingress.old-ca-chain.secret_path=
rplw-module.ose.secman.kv.ingress.basepath=
rplw-module.ose.secman.pki.ott.basepath=
rplw-module.ose.secman.pki.ott.common_name=
rplw-module.ose.secman.kv.ott.add-old-ca-chain=
rplw-module.ose.secman.kv.ott.old-ca-chain.secret_name=
rplw-module.ose.secman.kv.ott.old-ca-chain.secret_path=
rplw-module.ose.secman.kv.ott.basepath=
rplw-module.ose.secman.kv.ott.secret_name=
rplw-module.ose.secman.pki.audit.basepath=
rplw-module.ose.secman.pki.audit.common_name=
rplw-module.ose.secman.kv.audit.basepath=
rplw-module.ose.secman.kv.audit.secret_name=
rplw-module.ose.secman.pki.to_console.basepath=
rplw-module.ose.secman.pki.to_console.common_name=
rplw-module.ose.secman.kv.to_console.basepath=
rplw-module.ose.secman.kv.to_console.secret_name=
rplw-module.ose.secman.pki.logger.basepath=
rplw-module.ose.secman.pki.logger.common_name=
rplw-module.ose.secman.kv.logger.basepath=
rplw-module.ose.secman.kv.logger.secret_name=
rplw-module.ose.secman.pki.psql-eg.basepath=
rplw-module.ose.secman.pki.psql-eg.common_name=
rplw-module.ose.secman.kv.psql-eg.basepath=
rplw-module.ose.secman.pki.kafka.basepath=
rplw-module.ose.secman.pki.kafka.common_name=
rplw-module.ose.secman.kv.kafka.basepath=
rplw-module.secrets.engine=
rplw-module.hot-reload-dir-signing=
-
rplw-module.conf:# Имя приложения. Изменять не требуется.application-module.name=rplw-module# Автоматическое формирование FQDN. Изменять не требуется.rplw-module.ose.istio.ingress.route.spec.host.http.consoleFQDN={{ lookup('custom_vars', 'application-console.name') }}-{{ lookup('custom_vars', 'distrib.release.version') }}.{{ lookup('custom_vars', 'global.multiClusters.openshiftNewRoute') }}# Url для подключения module к console при стартеrplw-module.console.url=http://{{ lookup('custom_vars', 'rplw-module.ose.istio.ingress.route.spec.host.http.consoleFQDN') }}/# Параметры логированияrplw-module.log.root.level=inforplw-module.logger.root.level=INFOrplw-module.logger.org.springframework.level=INFOrplw-module.logger.org.springframework.web.level=INFOrplw-module.logger.ru.gradely.level=INFOrplw-module.label=# Rate limiter# Включение Rate limiterrplw-module.rate-limiter-enabled=false# Префикс метрикrplw-module.rate-limiter-metric-prefix=grdl_modulerplw-module.rate-limiter-buckets=[{"uri":"/general","maxTokens":1000,"refillIntervalSec":1}]# Включение работы воркера под ИТУЗrplw-module.db.admin-role-enable=true# Автосоздание системных таблиц при использовании ИТУЗrplw-module.auto-create-system-tables-enable=false# Автосоздание ресурсов на БД-источнике: publication и replication slot.# Для воркеров в контейнерной среде параметр может включаться централизованно через конфигурацию поставки.rplw-module.db.auto-create-resources.enabled=false# Автоматическое добавление новых таблиц в publication при обработке DDL CREATE TABLE.rplw-module.db.auto-create-resources.ddl.enabled=false# Режим инициализации DDL-инфраструктуры для автосопровождения publication.rplw-module.db.auto-create-resources.ddl.init-mode=SQL# Схема для служебных объектов DDL-инициализации.rplw-module.db.auto-create-resources.ddl.schema=grdl# Разрешенные проекты для данного воркераrplw-module.allowed-projects=# Путь до каталога с секретом в SECMAN:rplw-module.ose.secman.kv.ddl.basepath=# Имя секрета, в котором содержатся role_id и secret_id, для авторизации в secman по rest-api. Секрет хранится в KV2# Структура секрета:# ключ role_id, значение - сам roleid# ключ secret_id, значение - сам secret_idrplw-module.ose.secman.kv.ddl.secret_name=# Список путей к хранилищам кастомных секретов для БД# Пример:# Заполнено до движка KV2# rplw-module.psql.json.list=[{"as_name":"test","creds":[{"prefix":"A/IFT/RPLW/KV2/","secret_path":"ift1"}],[{"prefix":"A/IFT/RPLW/KV2/","secret_path":"ift2"}]}]# diff-init-module.secrets.engine=KV2## Заполнено до движка PG# rplw-module.psql.json.list=[{"as_name":"test","creds":[{"prefix":"A/IFT/RPLW/PG/","secret_path":"ift1"}],[{"prefix":"A/IFT/RPLW/PG/","secret_path":"ift2"}]}]# diff-init-module.secrets.engine=PG## Заполнено для работы по старому по FQDN# rplw-module.psql.json.list= ОСТАВИТЬ ПУСТЫМ# rplw-module.secrets.engine= Заполнить PG или KV2rplw-module.psql.json.list= -
rplw.istio.all.conf:# Включение/отключение sidecar istio-proxyrplw.ose.deployment.spec.template.annotations.istio.inject=true# Включение/отключение секретов для pull image из docker registryrplw.ose.deployment.spec.template.spec.imagePullSecrets.enabled=true# Имя секретаrplw.ose.deployment.spec.template.spec.imagePullSecrets.name={registry_name}# Управление PeerAuthentication# Включение/отключение развертывания манифеста PeerAuthenticationrplw.ose.istio.peer-authentication.enable=true# Управление режимом работы:rplw.ose.istio.peer-authentication.mode=STRICT -
rplw.fluentbit-sidecar.all.conf:fluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.limits.cpu=200mfluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.limits.memory=600Mifluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.limits.ephemeral-storage=${global.ose.deployment.spec.template.spec.containers.resources.limits.ephemeral-storage|2Gi}fluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.requests.cpu=200mfluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.requests.memory=600Mifluent-bit-sidecar.kafka.bootstrap.servers=${global.platform.logger.kafka.bootstrap.servers}fluent-bit-sidecar.kafka.topic=${global.platform.logger.kafka.topic}
Проверка результата
Изменения в конфигурационные файлы внесены.
Шаг 4. Проверьте и подготовьте параметры k8s в namespace (обязательный)
Последовательность действий
Для этого создайте imagePullSecret:
kind: Secret
apiVersion: v1
metadata:
name: ${rplw.ose.deployment.spec.template.spec.imagePullSecrets.name}
data:
.dockerconfigjson: >-
"Строка подключения к docker registry в base64"
type: kubernetes.io/dockerconfigjson
Проверка результата
Параметры k8s подготовлены.
Шаг 5. Удалите все устаревшие ресурсы Kubernetes (обязательный)
Список ресурсов для удаления
- Gateways
- Destination rules
- Virtualservices
- Serviceentries
- Ingress
- Services
- ConfigMap
- Deployments
- Virtual Services
Проверка результата
Устаревшие ресурсы k8s удалены.
Шаг 6. Настройте секреты в системе управления секретами HashiCorp Vault (обязательный)
Последовательность действий
Воспользуйтесь подразделом Администрирование через DropApp раздела Сценарии администрирования документа Руководство администратора.
Проверка результата
Секреты настроены.
Шаг 7. Интеграция с компонентом граничного прокси (IGEG) (обязательный)
Последовательность действий
Интеграция с граничным прокси настраивается Администратором стенда в ${стенд}/multiClusters.json
Убедитесь, что в конфигурации ConfigMap rplw.istio.all.conf установлен параметр: rplw.ose.deployment.spec.template.annotations.istio.inject=true и эта аннотация применена в Deployment для module.
Проверка результата
Интеграция с IGEG настроена.
Шаг 8. Интеграция с компонентом Журналирование (LOGA) (необязательный)
Последовательность действий
Пример файла rplw.fluentbit-sidecar.all.conf для интеграции с LOGA:
fluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.limits.cpu=200m
fluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.limits.memory=600Mi
fluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.limits.ephemeral-storage=${global.ose.deployment.spec.template.spec.containers.resources.limits.ephemeral-storage|2Gi}
fluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.requests.cpu=200m
fluent-bit-sidecar.ose.deployment.spec.template.spec.containers.fluent-bit-sidecar.resources.requests.memory=600Mi
fluent-bit-sidecar.kafka.bootstrap.servers=${global.platform.logger.kafka.bootstrap.servers}
fluent-bit-sidecar.kafka.topic=${global.platform.logger.kafka.topic}
Проверка результата
Интеграция с LOGA настроена.
Шаг 9. Интеграция с компонентом Объединенный мониторинг Unimon (MONA) (необязательный)
Последовательность действий
Для интеграции с MONA требуется предварительная настройка стенда администраторами.
Параметры берутся из настроек стенда.
Проверка результата
Интеграция с MONA настроена.
Шаг 10. Интеграция с Kafka (обязательный)
Последовательность действий
Для интеграции с Kafka требуется предварительная настройка стенда Администраторами.
Параметры берутся из настроек стенда.
Проверка результата
Интеграция с Kafka настроена.
Шаг 11. Интеграция с компонентом OTTS (обязательный)
Последовательность действий
Настройка интеграции производится на подах Ingress Gateway и Egress Gateway каждого Namespace.
Пример grdl.all.conf:
# Container limits
grdl.ott.limits.cpu = 200m
grdl.ott.limits.memory = 600Mi
grdl.ott.limits.ephemeral-storage = 1Gi
grdl.ott.requests.cpu = 200m
grdl.ott.requests.memory = 600Mi
# App vars
grdl.ott.module.id = {{ lookup('vars','global.platform.grdl.ott.module.id') }}
grdl.ingress.ott.audit2.proxy.url = http://localhost:6992
grdl.egress.ott.audit2.proxy.url = http://localhost:6991
Пример ConfigMap для Ingress Gateway:
kind: ConfigMap
apiVersion: v1
metadata:
name: grdl-console-ott-ingress-cm
labels:
owner: ott-sidecar
data:
OTT_CERTSTORE_TYPE: PEM
OTT_MODULE_ID: ott-client-grdl
OTT_CLIENT_CRT: /vault/secrets/certs/ott/ott_cert.pem
OTT_CLIENT_PRIVATE_KEY: /vault/secrets/certs/ott/ott_key.pem
OTT_SERVICE_TLS_CRT: /vault/secrets/certs/ott/ott_root.pem
OTT_SERVICE_CRT: /vault/secrets/certs/ott/ott-service.pem # обеспечение обратной совместимости с OTT сервером версии до 4.3.1
OTT_SERVICE_CLIENT_TRUSTED_CRT_RATE: '60' # период обновления кеша сертификатов серверов OTT, в секундах (при подключении к OTT серверу 4.3.1+)
OTT_OPER_MODE: validate # <mode> = "sign" для egress GW, "validate" - для ingress GW; не задавать этот параметр при интеграции со сборкой envoy от synapse security
OTT_SERVICE_HOSTS: >-
ott-server-host1:port,ott-server-host2:port # список серверов:портов сервиса OTTS для балансировки нагрузки, или аналогичный список nginx OTTS
JAVA_TOOL_OPTIONS: -Dlogging.config=/mnt/ott-logback/logback.xml -Dlogback.configurationFile=/mnt/ott-logback/logback.xml -XX:MaxRAMPercentage=55.0 -Dspring.profiles.active=probes
OTT_AUTH_TLS_TRUST_MODE: 'true'
# изменить значения параметров ниже при необходимости, по умолчанию - не менять
OTT_CLIENT_MMT-COMPATIBILITY-MODE: 'false' # режим совместимости с ММТ 3 поколения, включать для взаимодействия с Платформой 3-го поколения, ожидаемая структура path HTTP-запроса: /<receiver_id>/<api.name>/<api.method> или /<api.name>/<api.method>
OTT_GRPC_PORT: /mnt/ott-uds-socket/ott.socket
OTT_SERVICE_URL: 'https://stub-host:stub-port/ott-service/rest/token' # шаблон URL сервиса OTTS, при балансировке значения будут подставляться из OTT_SERVICE_HOSTS
OTT_AUTHZ_VERSION: '1.0' # версия метода авторизации
OTT_AUTHZ_REALM: ott
OTT_HTTP_PORT: '8090' # порт OTTS Sidecar для readiness probe, при необходимости можно выбрать любой другой свободный порт
OTT_ANONYMOUS_REQUESTS_ENABLED: 'false' # анонимный режим, для включения необходимо выставить в 'true'
OTT_CLIENT_DEFAULT_REALM: mmt
OTT_CLIENT_MMT_RESOURCE_ATTRID: 'urn:censored:names:censored:1.0:api:interface:fullname'
OTT_CLIENT_MMT_ACTION_ATTRID: 'urn:censored:names:censored:1.0:action:id'
OTT_APPLICATION_ATTRIBUTE_ID: 'urn:censored:names:censored:1.0:module:id' # здесь строка остается неизменной, на свой идентификатор приложения менять не нужно
При использовании IAM необходимо указать параметр OTT_AUTH_TLS_TRUST_MODE: 'true'
Пример ConfigMap для Egress Gateway:
kind: ConfigMap
apiVersion: v1
metadata:
name: grdl-console-ott-egress-cm
labels:
owner: ott-sidecar
data:
OTT_CERTSTORE_TYPE: PEM
OTT_MODULE_ID: ott-client-grdl
OTT_CLIENT_CRT: /vault/secrets/certs/ott/ott_cert.pem
OTT_CLIENT_PRIVATE_KEY: /vault/secrets/certs/ott/ott_key.pem
OTT_SERVICE_TLS_CRT: /vault/secrets/certs/ott/ott_root.pem
OTT_SERVICE_CRT: /vault/secrets/certs/ott/ott-service.pem # обеспечение обратной совместимости с OTT сервером версии до 4.3.1
OTT_SERVICE_CLIENT_TRUSTED_CRT_RATE: '60' # период обновления кеша сертификатов серверов OTT, в секундах (при подключении к OTT серверу 4.3.1+)
OTT_OPER_MODE: sign # <mode> = "sign" для egress GW, "validate" - для ingress GW; не задавать этот параметр при интеграции со сборкой envoy от synapse security
OTT_SERVICE_HOSTS: >-
ott-server-host1:port,ott-server-host2:port # список серверов:портов сервиса OTTS для балансировки нагрузки, или аналогичный список nginx OTTS
JAVA_TOOL_OPTIONS: -Dlogging.config=/mnt/ott-logback/logback.xml -Dlogback.configurationFile=/mnt/ott-logback/logback.xml -XX:MaxRAMPercentage=55.0 -Dspring.profiles.active=probes
# изменить значения параметров ниже при необходимости, по умолчанию - не менять
OTT_CLIENT_MMT-COMPATIBILITY-MODE: 'false' # режим совместимости с ММТ 3 поколения, включать для взаимодействия с Платформой 3-го поколения, ожидаемая структура path HTTP-запроса: /<receiver_id>/<api.name>/<api.method> или /<api.name>/<api.method>
OTT_GRPC_PORT: /mnt/ott-uds-socket/ott.socket
OTT_SERVICE_URL: 'https://stub-host:stub-port/ott-service/rest/token' # шаблон URL сервиса OTTS, при балансировке значения будут подставляться из OTT_SERVICE_HOSTS
OTT_AUTHZ_VERSION: '1.0' # версия метода авторизации
OTT_AUTHZ_REALM: ott
OTT_HTTP_PORT: '8090' # порт OTTS Sidecar для readiness probe, при необходимости можно выбрать любой другой свободный порт
OTT_ANONYMOUS_REQUESTS_ENABLED: 'false' # анонимный режим, для включения необходимо выставить в 'true'
OTT_CLIENT_DEFAULT_REALM: mmt
OTT_CLIENT_MMT_RESOURCE_ATTRID: 'urn:censored:names:censored:1.0:api:interface:fullname'
OTT_CLIENT_MMT_ACTION_ATTRID: 'urn:censored:names:censored:1.0:action:id'
OTT_APPLICATION_ATTRIBUTE_ID: 'urn:censored:names:censored:1.0:module:id' # здесь строка остается неизменной, на свой идентификатор приложения менять не нужно
Подробное описание интеграции доступно в документации на продукт One-Time Password (OTP)/OTT (версия 5.15)
Проверка результата
Интеграция с OTTS настроена.
Шаг 12. Интеграция с HashiCorp Vault (обязательный)
Последовательность действий
HashiCorp Vault — это система управления секретами и шифрованием на основе идентификационных данных. Взаимодействие с сервером SecMan производится с помощью Vault Agent sidecar, который поставляется в целевой pod с помощью инжектора.
Пример инжектора в Deployment:
# ...
template:
metadata:
labels:
secman-injector: enabled
# ...
Инжектор Vault Agent изменяет спецификации pod, чтобы включить контейнеры Vault Agent, которые отображают секреты Vault в разделяемом томе памяти с использованием шаблонов Vault Agent. Выводя секреты на общий том, контейнеры внутри модуля могут использовать секреты Vault, не зная о Vault. Инжектор — это Kubernetes Mutation Webhook Controller. Контроллер перехватывает события модуля и применяет изменения к модулю, если в запросе существуют аннотации. Эта функциональность предоставляется проектом vault-k8s и может быть автоматически установлена и настроена с помощью диаграммы Vault Helm.
Параметры инжектора и действий с секретами HashiCorp Vault передаются в блоке аннотаций.
Пример записи сертификата из Key Value хранилища HashiCorp Vault в файловую систему пода с использованием языка шаблонов GO Template:
template:
metadata:
labels:
# ...
annotations:
# ...
vault.hashicorp.com/agent-inject-secret-ott_root.pem: 'true'
vault.hashicorp.com/secret-volume-path-ott_root.pem: /vault/secrets/certs/ott
vault.hashicorp.com/agent-inject-file-ott_root.pem: ott_root.pem
vault.hashicorp.com/agent-inject-template-ott_root.pem: |
{{ '{{- with secret "' +
'DEV_censored/A/IFT3/GRDL/KV2/' +
'ott' +
'" -}}' }}
{{ '{{ .Data.data.cacert }}' }}
{{ '{{ end -}}' }}
# ...
GraDeLy поддерживает два типа секретов:
- KV-секреты — секреты, сгенерированные с движком KV Secrets Engine.
- PG — секреты, расположенные в PG-хранилище.
Конфигурационные параметры генерации секретов:
rplw-module.k8s.secman.engine.ott=KV
rplw-module.k8s.secman.engine.ingress=PKI
rplw-module.k8s.secman.engine.audit=KV
rplw-module.k8s.secman.engine.toconsole=PKI
rplw-module.k8s.secman.engine.logger=KV
rplw-module.k8s.secman.engine.psql=PKI
rplw-module.k8s.secman.engine.kafka=KV
Поддержка alias для KV2
В конфигурации воркера установите параметры:
rplw-module.secrets.engine=kv2
rplw-module.psql.json.list=[{"as_name":"test","creds":[{"prefix":"A/IFT/AS/KV2/","secret_path":"jdbc-1"},{"prefix":" A/IFT/AS/KV2/","secret_path":"jdbc-2"},{"prefix":" A/IFT/AS/KV2/","secret_path":"jdbc-3"}]}]
В опциях соединения к БД в UI укажите параметр "secret_path": "<Путь до секрета в HashiCorp Vault>"
Для формирования путей до секретов в HashiCorp Vault по старой логике с использованием FQDN баз данных оставьте пустым параметр конфигураций rplw-module.psql.json.list=.
Поддержка alias для PG
В конфигурации воркера установите параметры:
gdl.secrets.engine=pg
rplw-module.psql.json.list=[{"as_name":"test","creds":[{"prefix":"DEV/database/pg/static-creds/","secret_path":"secret-rec"},{"prefix":"DEV/database/pg/static-creds/","secret_path":"secret_src"}]}]
В опциях соединения к БД в UI укажите параметр "secret_path": "<Путь до секрета в HashiCorp Vault>"
Если указанный параметр не заполнен, а gdl.secrets.engine=pg, то возникнет ошибка.
Проверка результата
Интеграция с HashiCorp Vault настроена.
Шаг 13. Предустановленные конфигурации (обязательный)
Последовательность действий
rplw.all.conf:
rplw.worker.count = 2 # количество подов воркера при деплое
rplw.ose.deployment.spec.template.spec.containers.ott-sidecar.startupProbe.failureThreshold=30
rplw.ose.deployment.spec.template.spec.containers.ott-sidecar.livenessProbe.failureThreshold=30
rplw.ose.deployment.spec.template.spec.containers.ott-sidecar.readinessProbe.failureThreshold=15
rplw.fluentbit-sidecar.all.conf:
# Параметры fluent-controller
# Перечитать конфигурацию fluent-bit
rplw.fluentbit-sidecar.conf.reload.enabled=true
# Использовать механизм Secman Hotreload
rplw.fluentbit-sidecar.vault.reload.enabled=true
rplw.istio.all.conf:
# Управление приоритетом компонентов
istio.ose.deployment.spec.template.spec.priorityClassName=
# количество реплик ingress/egress
istio.ose.istio.ingress.deployment.spec.replicas=2
# Istio control plane
rplw.ose.istio.control-plane-project={{ lookup('custom_vars', 'global.multiClusters.openshiftControlPlaneProject') }}
rplw.ose.istio.control-plane-istiod-service={{ lookup('custom_vars', 'global.multiClusters.openshiftControlPlaneIstiodService') }}
rplw.ose.istio.control-plane-istiod-port={{ lookup('custom_vars', 'global.multiClusters.openshiftControlPlaneIstiodPort') }}
# Jaeger collector
rplw.ose.istio.control-plane-jaeger-service={{ lookup('custom_vars', 'global.multiClusters.openshiftControlPlaneJaegerService') }}
rplw.ose.istio.control-plane-jaeger-port={{ lookup('custom_vars', 'global.multiClusters.openshiftControlPlaneJaegerPort') }}
rplw.ose.deployment.spec.template.spec.containers.istio-proxy.readinessProbe.failureThreshold=30
# Kafka ports
rplw.ose.istio.egress.se.tcp.kafka.number={{ lookup('custom_vars', 'global.platform.ose.kafka.ports') }}
rplw.ose.deployment.spec.template.spec.containers.egress.resources.limits.cpu=1000m
rplw.ose.deployment.spec.template.spec.containers.egress.resources.limits.memory=200Mi
rplw.ose.deployment.spec.template.spec.containers.egress.resources.requests.cpu=1000m
rplw.ose.deployment.spec.template.spec.containers.egress.resources.requests.memory=200Mi
rplw.ose.deployment.spec.template.spec.containers.ingress.resources.limits.cpu=200m
rplw.ose.deployment.spec.template.spec.containers.ingress.resources.limits.memory=200Mi
rplw.ose.deployment.spec.template.spec.containers.ingress.resources.requests.cpu=200m
rplw.ose.deployment.spec.template.spec.containers.ingress.resources.requests.memory=200Mi
rplw.ose.istio.vault-token.aud=vault
rplw-module.conf:
# Управление приоритетом компонентов
rplw-module.ose.deployment.spec.template.spec.priorityClassName=
# Параметр добавляющий аргументы запуска приложения через jvm переменную JAVA_OPTS. Будут помещены в конфигмап someFpName1.conf;
rplw-module.ose.configmap.javaArguments=-XX:+UseContainerSupport -XX:InitialRAMPercentage=40.0 -XX:MaxRAMPercentage=80.0 -XX:+UseSerialGC
# количество реплик
rplw-module.ose.deployment.spec.replicas=2
rplw-module.ose.deployment.spec.template.spec.containers.rplw-module.resources.limits.cpu=2000m
rplw-module.ose.deployment.spec.template.spec.containers.rplw-module.resources.limits.memory=4000Mi
rplw-module.ose.deployment.spec.template.spec.containers.rplw-module.resources.limits.ephemeral-storage={{ lookup('custom_vars', 'global.ose.deployment.spec.template.spec.containers.resources.limits.ephemeral-storage', default='500Mi') }}
rplw-module.ose.deployment.spec.template.spec.containers.rplw-module.resources.requests.cpu=2000m
rplw-module.ose.deployment.spec.template.spec.containers.rplw-module.resources.requests.memory=4000Mi
rplw-module.ose.kafka.port=9093
rplw-module.kafka.message-format=PARSED
rplw-module.auto-create-topics-enable=true
# Для воркеров в контейнерной среде параметр по умолчанию включен.
# При включении воркер создает основной и служебные Kafka-топики процесса; при выключении топики должны быть подготовлены заранее.
rplw-module.label=
rplw-module.hot-reload-enable=true
rplw-module.hot-reload-poll-interval=5000
rplw-module.hot-reload-retry-count=10
rplw-module.hot-reload-fail-safe-enable=true
rplw-module.hot-reload-dir-postgres=/vault/secrets/databases
rplw-module.vault.pki.mount-path=PKI
rplw-module.vault.pki.refresh-period=10m
rplw-module.vault.pki.fetch-cn='*.solution.sbt'
rplw-module.vault.pki.fetch-role=role-ga-secman-grdl-ift
rplw-module.vault.pki.fetch-ttl=2592000
rplw-module.vault.pki.alt-names=*.ift-grdl.apps.dap.devpub-01.solution.sbt,*.vdc11.db.dev.sbt,*.ift2-grdl.apps.dap.devpub-02.solution.sbt,*.ift3-grdl.apps.dap.devpub-01.solution.sbt,*.nt01-grdl.apps.dap.ntpub-01.solution.sbt,solution.sbt,db.dev.sbt,*.ift4-grdl.apps.dap.devpub-02.solution.sbt,*.grdl.apps.dap.devpub-02.solution.sbt,*.ift-grdl.apps.dap.devpub-01.solution.sbt,*.nt02-grdl.apps.dap.ntpub-01.solution.sbt,*.ift4-grdl.apps.dap.devpub-02.solution.sbt,*.solution.sbt,*.dap.ntpub-01db.solution.sbt
rplw-module.vault.pki.ip-sans=
rplw-module.capture-cache-size=12000
rplw-module.apply-cache-size=15
rplw-module.kafka-consumer-queue-size=12000
rplw-module.ose.deployment.spec.template.spec.containers.resources.limits.cpu=1000m
rplw-module.ose.deployment.spec.template.spec.containers.resources.limits.memory=200Mi
rplw-module.ose.deployment.spec.template.spec.containers.resources.requests.cpu=1000m
rplw-module.ose.deployment.spec.template.spec.containers.resources.requests.memory=200Mi
rplw-module.ose.deployment.spec.template.spec.containers.egress.resources.limits.cpu=400m
rplw-module.ose.deployment.spec.template.spec.containers.egress.resources.limits.memory=200Mi
rplw-module.ose.deployment.spec.template.spec.containers.egress.resources.requests.cpu=400m
rplw-module.ose.deployment.spec.template.spec.containers.egress.resources.requests.memory=200Mi
rplw-module.ose.deployment.spec.template.spec.containers.ingress.resources.limits.cpu=200m
rplw-module.ose.deployment.spec.template.spec.containers.ingress.resources.limits.memory=200Mi
rplw-module.ose.deployment.spec.template.spec.containers.ingress.resources.requests.cpu=200m
rplw-module.ose.deployment.spec.template.spec.containers.ingress.resources.requests.memory=200Mi
rplw-module.ose.deployment.spec.template.spec.containers.rplw-module.livenessProbe.failureThreshold=3
rplw-module.ose.deployment.spec.template.spec.containers.rplw-module.readinessProbe.failureThreshold=3
rplw-module.feature.SelfAntiAffinity.enabled=false
# Rate limiter
rplw-module.rate-limiter-buckets=[{"uri":"/general","maxTokens":1000,"refillIntervalSec":1}]
# Список БД находящихся на том же ЦОД что и воркер
rplw-module.db.urls=["fqdn1","fqdn2"]
# Список путей к хранилищам кастомных секретов для БД
# Пример:
# Заполнено до движка KV2
# rplw-module.psql.json.list=[{"as_name":"test","creds":[{"prefix":"A/IFT/RPLW/KV2/","secret_path":"ift1"}],[{"prefix":"A/IFT/RPLW/KV2/","secret_path":"ift2"}]}]
# diff-init-module.secrets.engine=KV2
#
# Заполнено до движка PG
# rplw-module.psql.json.list=[{"as_name":"test","creds":[{"prefix":"A/IFT/RPLW/PG/","secret_path":"ift1"}],[{"prefix":"A/IFT/RPLW/PG/","secret_path":"ift2"}]}]
# diff-init-module.secrets.engine=PG
#
# Заполнено для работы по старому по FQDN
# rplw-module.psql.json.list= ОСТАВИТЬ ПУСТЫМ
# rplw-module.secrets.engine= Заполнить PG или KV2
rplw-module.psql.json.list=
Проверка результата
Конфигурации предустановлены.
Шаг 14. Произведите полную установку GraDeLy (обязательный)
Последовательность действий
Для GraDeLy предусмотрена автоматизированная установка через компонент Deploy tools продукта Platform V DevOps Tools (DOT).
При выполненных предыдущих пунктах файлы сценария миграции, обновления БД повторно можно не выполнять.
Полный список файлов сценария для установки:
- MIGRATION_FP_CONF;
- FP_CONF_CHECK;
- OPENSHIFT_DEPLOY;
- OPENSHIFT_INGRESS_EGRESS_DEPLOY.
Проверка результата
Установка проведена.
Шаг 15. Определите максимальную производительность (не обязательный)
Последовательность действий
Для определения максимальной нагрузки, которую следует задать с помощью механизма Rate Limiter, проведите тест определения максимальной производительности.
Нагрузка должна быть ограничена с помощью механизма Rate Limiter на уровне, не превышающем показатели теста максимальной производительности.
Сценарий тестирования
При тестировании происходит пошаговое увеличение нагрузки с нуля до предельной (с шагом 20% от плановой). Пошаговое увеличение происходит до тех пор, пока не нарушится критерий успешности по количеству ошибок и/или времени отклика (что наступит раньше). Время работы теста на каждом шаге после стабилизации нагрузки составляет 10 минут.
Цель тестирования
По результатам тестирования устанавливается:
- уровень нагрузки L0 — последний шаг нагрузки, на котором не были нарушены критерии успешности;
- уровень нагрузки Llim — предельный уровень нагрузки, при котором не был нарушен критерий по количеству ошибок;
- уровень утилизации CPUlim — утилизация CPU на уровне нагрузки Llim.
Ожидаемый результат
-
Определен уровень максимальной производительности. L0 удовлетворяет одному из следующих уровней нагрузки (при использовании ресурсов всеми подами не больше, чем на OSE):
- Lmax для предыдущего релиза;
- Запросите аналитическую оценку команды по плановой нагрузке на сервис на год вперед, если не достигнут Lmax (при суммарных ресурсах как на OSE);
- Используйте критерий 10х от промышленной нагрузки на сервис, если не достигнута плановая нагрузка на год вперед.
-
Определен уровень нагрузки Llim.
-
Определен уровень утилизации CPUlim.
Профиль нагрузки
Моделирование нагрузки производится с использованием средств нагрузочного тестирования путем эмуляции действий определенного количества пользователей. Каждый виртуальный пользователь (программный процесс, эмулирующий действия физического пользователя АС) циклически выполняет пользовательский сценарий.
Подача нагрузки
- JMeter подает нагрузку на БД Source Pangolin, выполняя PL/pgSQL-функцию
NewOrder, которая включает в себя три операцииINSERTи одну операциюUPDATE; - Первый модуль захвата и изменений GraDeLy вычитывает сгенерированные данные из БД Source Pangolin и записывает их в Kafka;
- Модуль применения изменений вычитывает данные из Kafka и применяет их на БД Replica Pangolin.
Функция NewOrder — это бизнес-транзакция для выполнения нового заказа с помощью одной транзакции базы данных.
Представляет собой транзакцию чтения-записи среднего веса с высокой частотой выполнения. Эта транзакция является основой рабочей нагрузки.
Позволяет моделировать переменную нагрузку, характерную для оперативной активности базы данных в производственных средах.
Структура транзакции NewOrder
CREATE OR REPLACE FUNCTION benchbase.new_order(w_id smallint, d_id bigint, c_id integer, o_entry_d timestamp without time zone, i_ids integer[], i_w_ids integer[], i_qtys integer[])
RETURNS benchbase.t_order_res
LANGUAGE plpgsql
AS $function$
DECLARE
getWarehouseTaxRate text := 'SELECT W_TAX FROM benchbase.WAREHOUSE WHERE W_ID = $1';
getDistrict text := 'SELECT D_TAX, nextval(''benchbase.D_NEXT_O_ID'') FROM benchbase.DISTRICT WHERE D_ID = $1 AND D_W_ID = $2';
getCustomer text := 'SELECT C_DISCOUNT, C_LAST, C_CREDIT FROM benchbase.CUSTOMER WHERE C_W_ID = $1 AND C_D_ID = $2 AND C_ID = $3';
createOrder text := 'INSERT INTO benchbase.OORDER (O_ID, O_D_ID, O_W_ID, O_C_ID, O_ENTRY_D, O_CARRIER_ID, O_OL_CNT, O_ALL_LOCAL) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)';
createNewOrder text := 'INSERT INTO benchbase.NEW_ORDER (NO_O_ID, NO_D_ID, NO_W_ID) VALUES ($1, $2, $3)';
getItemInfo text := 'SELECT I_PRICE, I_NAME, I_DATA FROM benchbase.ITEM WHERE I_ID = $1';
getStockInfo text := 'SELECT S_QUANTITY, S_DATA, S_YTD, S_ORDER_CNT, S_REMOTE_CNT, S_DIST_%s FROM benchbase.STOCK WHERE S_I_ID = $1 AND S_W_ID = $2';
updateStock text := 'UPDATE benchbase.STOCK SET S_QUANTITY = $1, S_YTD = $2, S_ORDER_CNT = $3, S_REMOTE_CNT = $4 WHERE S_I_ID = $5 AND S_W_ID = $6';
createOrderLine text := 'INSERT INTO benchbase.ORDER_LINE (OL_O_ID, OL_D_ID, OL_W_ID, OL_NUMBER, OL_I_ID, OL_SUPPLY_W_ID, OL_DELIVERY_D, OL_QUANTITY, OL_AMOUNT, OL_DIST_INFO) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)';
all_local boolean := TRUE;
ol_cnt integer;
items benchbase.t_order_item[];
item benchbase.t_order_item;
customer_info benchbase.t_order_customer;
c_discount float;
o_carrier_id integer;
stock_info benchbase.t_order_stock;
w_tax float;
d_tax float;
d_next_o_id integer;
brand_generic char;
ol_amount float;
total float := 0;
item_data_s benchbase.t_order_item_data;
item_data benchbase.t_order_item_data[];
misc benchbase.t_order_misc;
BEGIN
ol_cnt = array_length(i_ids, 1);
ASSERT ol_cnt != 0;
ASSERT ol_cnt = array_length(i_w_ids, 1);
ASSERT ol_cnt = array_length(i_qtys, 1);
FOR i IN 1..ol_cnt LOOP
all_local = all_local AND i_w_ids[i] = w_id;
EXECUTE getItemInfo INTO item USING i_ids[i];
ASSERT item IS NOT NULL;
items = array_append(items, item);
END LOOP;
ASSERT ol_cnt = array_length(items, 1);
EXECUTE getWarehouseTaxRate INTO w_tax USING w_id;
EXECUTE getDistrict INTO d_tax, d_next_o_id USING d_id, w_id;
EXECUTE getCustomer INTO customer_info USING w_id, d_id, c_id;
c_discount = customer_info.C_DISCOUNT;
o_carrier_id = 0;
EXECUTE createOrder USING d_next_o_id, d_id, w_id, c_id, o_entry_d, o_carrier_id, ol_cnt, cast(all_local as integer);
EXECUTE createNewOrder USING d_next_o_id, d_id, w_id;
FOR i IN 1..ol_cnt LOOP
EXECUTE FORMAT(getStockInfo, to_char(d_id, 'FM09')) INTO stock_info USING i_ids[i], i_w_ids[i];
stock_info.S_YTD = stock_info.S_YTD + i_qtys[i];
IF stock_info.S_QUANTITY >= i_qtys[i] + 10 THEN
stock_info.S_QUANTITY = stock_info.S_QUANTITY - i_qtys[i];
ELSE
stock_info.S_QUANTITY = stock_info.S_QUANTITY + 91 - i_qtys[i];
END IF;
stock_info.S_ORDER_CNT = stock_info.S_ORDER_CNT + 1;
IF i_w_ids[i] != w_id THEN
stock_info.S_REMOTE_CNT = stock_info.S_REMOTE_CNT + 1;
END IF;
EXECUTE updateStock USING stock_info.S_QUANTITY, stock_info.S_YTD, stock_info.S_ORDER_CNT, stock_info.S_REMOTE_CNT, i_ids[i], i_w_ids[i];
IF position('ORIGINAL' IN items[i].I_DATA) != 0 AND position('ORIGINAL' IN stock_info.S_DATA) != 0 THEN
brand_generic = 'B';
ELSE
brand_generic = 'G';
END IF;
ol_amount = i_qtys[i] * items[i].I_PRICE;
total = total + ol_amount;
EXECUTE createOrderLine USING d_next_o_id, d_id, w_id, i, i_ids[i], i_w_ids[i], o_entry_d, i_qtys[i], ol_amount, stock_info.S_DIST;
item_data_s = ROW(items[i].I_NAME, stock_info.S_QUANTITY, brand_generic, items[i].I_PRICE, ol_amount);
item_data = array_append(item_data, item_data_s);
END LOOP;
total = total * (1 - c_discount) * (1 + w_tax + d_tax);
misc = ROW(w_tax, d_tax, d_next_o_id, total);
RETURN ROW(customer_info, misc, item_data);
END;
$function$
;
Вызов функции NewOrder
select benchbase.new_order((CEIL(RANDOM() * 10))::smallint, (CEIL(RANDOM() * 10))::int8, CEIL(RANDOM() * 3000)::integer, current_timestamp::timestamp, ARRAY[CEIL(RANDOM() * 100000)::int], ARRAY[CEIL(RANDOM() * 10)::int], ARRAY[1]);
Схема данных

Тестовые данные
Тестовые данные сгенерированы с помощью BenchBase с использованием бенчмарка TPC-C.
Пример конфигурации для генерации тестовых данных
<?xml version="1.0"?>
<parameters>
<type>POSTGRES</type>
<driver>org.postgresql.Driver</driver>
<url> </url>
<username> </username>
<password> </password>
<reconnectOnConnectionFailure>true</reconnectOnConnectionFailure>
<isolation>TRANSACTION_READ_COMMITTED</isolation>
<batchsize>100</batchsize>
<scalefactor>10</scalefactor>
<terminals>1000</terminals>
<works>
<work>
<time>1200</time>
<rate>3000</rate>
<weights>45,43,4,4,4</weights>
</work>
</works>
<transactiontypes>
<transactiontype>
<name>NewOrder</name>
</transactiontype>
<transactiontype>
<name>Payment</name>
</transactiontype>
<transactiontype>
<name>OrderStatus</name>
</transactiontype>
<transactiontype>
<name>Delivery</name>
</transactiontype>
<transactiontype>
<name>StockLevel</name>
</transactiontype>
</transactiontypes>
</parameters>
Тестирование базовой конфигурации
grdl.properties
gdl.apply-cache-size=20
gdl.capture-cache-size=12000
gdl.kafka-consumer-queue-size=12000
Параметры модуля применения изменений Applier

Параметры соединения БД Replica
{
"max.pool.size": 20,
"apply.thread.count": 18,
"transaction.size": 2000,
"db.linger.ms": 3000
}
Параметры соединения Kafka
{
"max.poll.records": "1",
"batch.size": 16384,
"max.request.size": 209715200,
"compression.type": "zstd",
"compression.zstd.level": 3
}
Метрики теста
- Модуль захвата изменений capture:
vm-gdev-db-nosw-515.vdc11.db.dev.sbt - Модуль применения изменений applier:
vm-gdev-db-nosw-516.vdc11.db.dev.sbt
Network recieve/transmit

OPS(insert/update/delete)
vm-grdl-db-psql-430.vdc11.db.dev.sbt— БД Sourcevm-grdl-db-psql-433.vdc11.db.dev.sbt— БД Replica

Итог
- Максимальная производительность репликации OPS: 28900
- Максимальная производительность репликации MB/s: 8.2
Тестирование минимальной конфигурации
grdl.properties
gdl.apply-cache-size=20
gdl.capture-cache-size=12000
gdl.kafka-consumer-queue-size=500
Параметры модуля применения изменений Applier

Параметры соединения БД Replica
{
"max.pool.size": 5,
"apply.thread.count": 2,
"transaction.size": 500,
"db.linger.ms": 1000
}
Параметры соединения Kafka
{
"max.poll.records": "1",
"batch.size": 16384,
"max.request.size": 209715200,
"compression.type": "zstd",
"compression.zstd.level": 3
}
Метрики теста
- Модуль захвата изменений capture:
vm-gdev-db-nosw-513.vdc11.db.dev.sbt - Модуль применения изменений applier:
vm-gdev-db-nosw-514.vdc11.db.dev.sbt
Network recieve/transmit

OPS(insert/update/delete)
vm-grdl-db-psql-430.vdc11.db.dev.sbt— БД Sourcevm-grdl-db-psql-433.vdc11.db.dev.sbt— БД Replica

Итог
- Максимальная производительность репликации OPS: 3900
- Максимальная производительность репликации MB/s: 1.15
Проверка результата
Максимальная производительность определена.