Руководство по эксплуатации ПО
"CPaaS"

Версия 1.0
28.06.2026
ООО «Интерконнект»
Версия 1.0 от 28.06.2026

1Термины и определения

Абонент:Клиент сотовой связи, по которому предполагается отслеживать сетевые события. Абонент может быть клиентом домашнего оператора или других операторов
Автоматизированная система:система, реализующая информационную технологию выполнения установленных функций с помощью персонала и комплекса средств автоматизации
ООО:Общество с ограниченной ответственностью
ПО:программное обеспечение
CAMEL:(Customized Application for Mobile Enhanced Logic) стандартизованный протокол для использования в мобильных интеллектуальных платформах
CAP:(CAMEL Application Part) прикладной протокол CAMEL
CdPN:(Called Party Number) номер вызываемого абонента
CgPN:(Calling Party Number) номер вызывающего абонента
GMSC:(Gateway Mobile Switching Center) шлюзовой центр коммутации подвижной службы сети GSM. Узел, принимающий входящий вызов и определяющий, на какой обслуживающий MSC (Serving MSC) отправлять вызов
GSM:(Global System for Mobile Communications) глобальный стандарт цифровой мобильной сотовой связи с разделением каналов по времени и частоте
gRPC:(Remote procedure calls) система удаленного вызова процедур
HLR:(Home Location Register) домашний регистр местоположения
HAProxy:серверное программное обеспечение для реализации высокой доступности и балансировки нагрузки для TCP и HTTP-приложений, посредством распределения входящих запросов на несколько обслуживающих серверов. См. https://www.haproxy.org/
HTTP:(HyperText Transfer Protocol) протокол передачи гипертекста
IMSI:(International Mobile Subscriber Identity) международный идентификатор мобильного абонента (индивидуальный номер абонента)
IMEI:(International Mobile Equipment Identity) международный идентификатор оборудования абонентской радиостанции
JSON:(JavaScript Object Notation) текстовый формат обмена данными, основанный на JavaScript
MSC:(Mobile switching center) центр коммутации
MT:(Mobile Terminated) входящий вызов
MO:(Mobile Originated) исходящий вызов
MSISDN:(Mobile Station Integrated Services Digital Network) номер мобильной станции в формате E.164
NAI:(Nature of address indicator) индикатор типа адреса
OSS:(Operations Support System) система поддержки операций
Protocol Buffers:язык описания интерфейса для системы удаленного вызова процедур
SCCP:(Signalling connection control part) часть управления сигнальными соединениями
SCP:(Signaling control point) узел управления услугами
STP:(Signaling transfer point) узел маршрутизации сигнальных сообщений
TCAP:(Transaction capabilities application part) прикладная часть возможностей транзакций
TON:(Type of number) тип номера
VLR:(Visitors location register) визитный регистр местоположения

2Введение

Данный документ (далее — Руководство) является руководством по эксплуатации программного обеспечения (далее — ПО) «CPaaS» производства компании ООО «Интерконнект», Российская Федерация.

Руководство содержит описание назначения и основных принципов работы ПО «CPaaS», архитектуру системы, требования к инфраструктуре, а также описание процедур установки, настройки, запуска, мониторинга и устранения неисправностей.

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

Все IP-адреса, идентификаторы и доменные имена приведены в качестве примеров и не имеют отношения к реальным абонентам или элементам сети.

3Общие сведения о продукте

ПО «CPaaS» представляет собой программную платформу для реализации подхода CPaaS (Communication Platform as a Service) - коммуникационной платформы как услуги. ПО «CPaaS» предназначено для использования на сетях операторов подвижной и фиксированной телефонной связи, а также на внутренних корпоративных сетях юридических лиц - от медицинских клиник и магазинов до холдингов, имеющих в распоряжении собственные выделенные сети LTE/5G.

ПО «CPaaS» применяется на сетях мобильной связи стандартов GSM, UMTS, LTE, имеющих множество географически распределенных узлов связи.

ПО «CPaaS» позволяет:

1.Оказывать услуги телефонной связи и технологически связанные с ними сервисы: запись разговоров, VoLTE-этикетки.

2.Предоставлять функциональность:

STT (Speech-to-Text) — распознавание и транскрибирование аудиофайлов;

Streaming ASR (Automatic Speech Recognition) — онлайн/потоковое распознавание фраз/слов для построения IVR-решений и интеллектуальных голосовых ассистентов;

TTS (Text-to-Speech) — генерация голосовых фраз из текста;

прочие сервисы, которые доступны у отдельных поставщиков, работающих в области искусственного интеллекта или машинного обучения (AI/ML).

3.Строить более высокоуровневые продукты на базе готовых примитивов стандартизированных API - Voice API и SMS API:

Скрытие реальных номеров при общении клиентов компании (например, телефонные звонки по онлайн-объявлениям);

Построение решений по аутентификации/верификации абонентов: двухфакторная аутентификация - 2FA, одноразовые пароли - OTP и т.п.;

Low/No Code решения - визуальные конструкторы IVR и т.п.;

Виртуальные Ассистенты;

Контакт-центры.

4.Организовать среду для разработки (SDK) клиентом дополнительных сервисов и сценариев на следующих языках программирования: C#, Java, JavaScript (Node.js), PHP, Python, Ruby, Go.

5.Масштабировать ПО «CPaaS» по мере развития сети оператора связи или клиента.

6.Осуществлять мониторинг работоспособности платформы в режиме реального времени.

7.Плавно интегрироваться в существующие каналы связи и бизнес-приложения оператора связи или клиента.

Часть функций или услуг может предоставляться существующими программными системами или подразделениями на сети оператора связи или организации - ценность объединения перечисленного функционала в ПО «CPaaS» состоит в возможности его представления в рамках целостного и единообразного API.

3.1Архитектура системы

Варианты схем построения услуг на базе ПО «CPaaS»

ПО «CPaaS» развертывается в кластере Kubernetes (за исключением компонентов sfas_aas, Kamailio и RtpEngine, разворачиваемых на отдельном хосте) и включает следующие основные программные компоненты:

apigw — API Gateway, точка входа для запросов бизнес-приложений заказчика по HTTPS (Voice API/SMS API); взаимодействует с базой данных DB CPAAS по SQL и с сервисами cpaas_billing и sengine по gRPC;

Kamailio / RtpEngine — SIP-сервер и медиарелей; принимает сигнальный (SIP/SIPS) и медийный (RTP/SRTP) трафик от сетей PSTN и оператора связи, взаимодействует с sipaas_nas по RADIUS, записывает данные в DB CPAAS по SQL и передает SIP/RTP трафик сервису sfas_aas;

sipaas_nas — компонент учета сетевого доступа (NAS) SIP-подсистемы; обменивается данными с apigw по HTTP, с Kamailio по RADIUS и с DB CPAAS по SQL;

sipaas_api — API-компонент SIP-подсистемы, обеспечивающий чтение и запись данных в DB CPAAS по SQL;

DB CPAAS (PostgreSQL, кластер cpaas-rdbms ) — реляционная СУБД, центральное хранилище конфигурационных, справочных данных и данных о вызовах;

cpaas-app — основное клиентское приложение платформы (Erlang/OTP); взаимодействует с сервисом распознавания речи VOSK server по gRPC, с хранилищем S3 по HTTP и с сервисом radio-silence по HTTP;

cpaas_billing — модуль биллинга; взаимодействует с apigw по gRPC и с DB CPAAS по SQL;

sengine — сервисный движок обработки сценариев; взаимодействует с apigw по gRPC, с сервисом TTS и хранилищем S3 по HTTP, а также со сервисом sfas_aas по AMQP/gRPC;

TTS — сервис синтеза речи (Text-to-Speech), предоставляющий sengine аудиофайлы голосовых сообщений по HTTP;

VOSK server — сервер распознавания речи (STT), развертывается в нескольких экземплярах; используется компонентами cpaas-app (по gRPC) и sfas_aas (по протоколу IFA/gRPC);

radio-silence — сервис определения тишины в аудиопотоке, взаимодействует с cpaas-app по HTTP;

sfas_aas — сервис распознавания и обработки речи как услуги; взаимодействует с хранилищем S3 по HTTP, с брокером сообщений RabbitMQ по AMQP, с sengine по gRPC, с VOSK server по IFA/gRPC, с Kamailio/RtpEngine по SIP/RTP;

S3 — объектное хранилище, совместимое с S3, для хранения медиафайлов (голосовые приветствия, аудиозаписи разговоров, файлы сценариев);

RabbitMQ (кластер cpaas-rmq) — брокер сообщений для асинхронного взаимодействия компонентов cpaas-app и sfas_aas;

Traefik — контроллер маршрутизации входящего трафика (Ingress);

MetalLB — балансировщик нагрузки для предоставления внешних IP-адресов сервисам;

CNPG Operator (CloudNativePG) — оператор Kubernetes для управления кластером PostgreSQL.

Взаимодействие с внешними системами (бизнес-приложения заказчика, сети PSTN и оператора связи) осуществляется по протоколам HTTPS, SIP(S)/(S)RTP и gRPC.

3.2Функции безопасности

ПО «CPaaS» оперирует следующими конфиденциальными данными:

абонентские номера, информация о вызовах и сообщениях;

учётные данные для подключения к БД, брокеру сообщений и объектному хранилищу.

Меры обеспечения безопасности:

учётные данные и ключи доступа хранятся в Kubernetes Secrets и не передаются в открытом виде;

взаимодействие между компонентами ограничено рамками namespace cpaas;

доступ к реестру образов контейнеров ограничен секретом sifox-imagepull-secret;

сетевая изоляция обеспечивается политиками Kubernetes (Kyverno / NetworkPolicy);

административные изменения конфигурации применяются только после перезапуска компонента.

3.3API ПО «CPaaS»

Компонент apigw предоставляет внешний REST API платформы, через который реализуются Voice API, SMS API и управление вспомогательными ресурсами (SIP-транкинг, визуальные сценарии IVR, файлы сценариев и т.п.). API построен по модели ресурсов (аккаунт, вызов, сообщение, конференция и т.д.) и использует версионирование путей: устаревающая версия /2010-04-01/... (Voice/SMS API, SIP, номера, использование, ключи), а также актуальные версии /v1/... (BYOC-транкинг, файлы сценариев) и /v2/... (визуальный конструктор сценариев Flows). Запросы к API выполняются по протоколу HTTPS, аутентификация — по схеме HTTP Basic Auth с использованием идентификатора аккаунта (Account SID) в качестве имени пользователя и токена доступа (Auth Token) в качестве пароля. Ответы API возвращаются в формате JSON.

Внимание:

Идентификатор аккаунта и токен доступа являются конфиденциальными данными и передаются получателю отдельным защищённым каналом, не публикуются в настоящем документе.

Ниже приведён перечень ресурсов и операций API, сгруппированных по функциональному назначению.

3.3.1Учётные записи (Accounts)

Базовый путь: /2010-04-01/Accounts.

МетодПутьОписание
GET/2010-04-01/AccountsПолучение списка учётных записей (основной и субаккаунтов)
POST/2010-04-01/AccountsСоздание субаккаунта
GET/2010-04-01/Accounts/{Sid}Получение учётной записи
POST/2010-04-01/Accounts/{Sid}Обновление учётной записи

3.3.2Вызовы — Voice API (Calls)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/Calls.

МетодПутьОписание
GET…/CallsПолучение списка вызовов (входящих и исходящих)
POST…/CallsИнициация исходящего вызова
GET…/Calls/{Call_Sid}Получение вызова
POST…/Calls/{Call_Sid}Обновление активного вызова: коллбэки, статус (canceled/completed) и TwiML-инструкции
DELETE…/Calls/{Call_Sid}Удаление неактивного вызова (статус canceled/completed/failed/busy/no_answer)
POST…/Calls/{Call_Sid}/RecordingsСоздание записи активного вызова
POST…/Calls/{Call_Sid}/TranscriptionsЗапуск транскрибирования вызова в реальном времени
POST…/Calls/{Call_Sid}/Transcriptions/{Transcription_Sid}Остановка транскрибирования вызова в реальном времени

3.3.3Конференции и участники (Conferences/Participants)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/Conferences.

МетодПутьОписание
GET…/ConferencesПолучение списка конференций аккаунта
GET…/Conferences/{Conference_Sid}Получение конференции
POST…/Conferences/{Conference_Sid}Завершение конференции (действие update)
DELETE…/Conferences/{Conference_Sid}Удаление завершённой конференции
GET…/Conferences/{Conference_Sid}/ParticipantsПолучение списка участников конференции
POST…/Conferences/{Conference_Sid}/ParticipantsДобавление участника в конференцию
GET…/Conferences/{Conference_Sid}/Participants/{Call_Sid}Получение участника конференции
POST…/Conferences/{Conference_Sid}/Participants/{Call_Sid}Обновление участника активной конференции
DELETE…/Conferences/{Conference_Sid}/Participants/{Call_Sid}Удаление участника из конференции

3.3.4Сообщения — SMS API (Messages)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/Messages.

МетодПутьОписание
GET…/MessagesПолучение списка сообщений
POST…/MessagesОтправка сообщения
GET…/Messages/{Message_Sid}Получение сообщения
DELETE…/Messages/{Message_Sid}Удаление сообщения

3.3.5Записи разговоров (Recordings)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/Recordings.

МетодПутьОписание
GET…/RecordingsПолучение списка записей аккаунта
GET…/Recordings/{Rec_Sid}.jsonПолучение метаданных записи
GET…/Recordings/{Rec_Sid}Получение медиафайла записи в формате WAV
GET…/Recordings/{Rec_Sid}.mp3Получение медиафайла записи в формате MP3
DELETE…/Recordings/{Rec_Sid}Удаление метаданных записи и связанных медиафайлов
GET…/Recordings/{Rec_Sid}/TranscriptionsПолучение транскрипций указанной записи

3.3.6Транскрипции (Transcriptions)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/Transcriptions.

МетодПутьОписание
GET…/TranscriptionsПолучение транскрипций аккаунта
GET…/Transcriptions/{Transcription_Sid}Получение транскрипции
DELETE…/Transcriptions/{Transcription_Sid}Удаление транскрипции

3.3.7Телефонные номера (Phone Numbers)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}.

МетодПутьОписание
GET…/AvailablePhoneNumbersПолучение списка стран, для которых доступны номера
GET…/AvailablePhoneNumbers/{Country_code}Получение информации по стране
GET…/AvailablePhoneNumbers/{Country_code}/MobileПоиск доступных для подключения мобильных номеров по стране
GET…/IncomingPhoneNumbersПолучение списка подключённых номеров
POST…/IncomingPhoneNumbersПодключение нового номера
GET…/IncomingPhoneNumbers/{Phone_Sid}Получение подключённого номера
POST…/IncomingPhoneNumbers/{Phone_Sid}Обновление настроек номера (в т.ч. Voice Callback)
DELETE…/IncomingPhoneNumbers/{Phone_Sid}Отключение номера

3.3.8SIP-транкинг (SIP)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/SIP.

МетодПутьОписание
GET…/SIP/DomainsПолучение списка SIP-доменов
POST…/SIP/DomainsСоздание SIP-домена
GET…/SIP/Domains/{Sip_Domain_Sid}Получение SIP-домена
POST…/SIP/Domains/{Sip_Domain_Sid}Обновление SIP-домена
GET…/SIP/CredentialListsПолучение списка списков учётных данных SIP
POST…/SIP/CredentialListsСоздание списка учётных данных SIP
GET…/SIP/CredentialLists/{Sip_Credential_List_Sid}Получение списка учётных данных SIP
POST…/SIP/CredentialLists/{Sip_Credential_List_Sid}Обновление списка учётных данных SIP
DELETE…/SIP/CredentialLists/{Sip_Credential_List_Sid}Удаление списка учётных данных SIP
GET…/CredentialLists/{…}/CredentialsПолучение учётных данных в списке
POST…/CredentialLists/{…}/CredentialsДобавление учётных данных в список
GET…/Credentials/{Sip_Credential_Sid}Получение учётных данных SIP
POST…/Credentials/{Sip_Credential_Sid}Обновление учётных данных SIP
DELETE…/Credentials/{Sip_Credential_Sid}Удаление учётных данных SIP
GET…/Domains/{…}/Auth/Calls/CredentialListMappingsПолучение привязок списков учётных данных к домену
POST…/Domains/{…}/Auth/Calls/CredentialListMappingsПривязка списка учётных данных к домену
GET…/CredentialListMappings/{Sip_Credential_List_Mapping_Sid}Получение привязки списка учётных данных
DELETE…/CredentialListMappings/{Sip_Credential_List_Mapping_Sid}Удаление привязки списка учётных данных
GET…/SIP/IpAccessControlListsПолучение списка контроля доступа по IP (ACL)
POST…/SIP/IpAccessControlListsСоздание списка контроля доступа по IP
GET…/IpAccessControlLists/{Sip_Ip_Control_List_Sid}Получение списка контроля доступа по IP
POST…/IpAccessControlLists/{Sip_Ip_Control_List_Sid}Обновление списка контроля доступа по IP
DELETE…/IpAccessControlLists/{Sip_Ip_Control_List_Sid}Удаление списка контроля доступа по IP
GET…/IpAccessControlLists/{…}/IpAddressesПолучение IP-адресов в списке ACL
POST…/IpAccessControlLists/{…}/IpAddressesДобавление IP-адреса в список ACL
GET…/IpAddresses/{Sip_Ip_Address_Sid}Получение IP-адреса из списка ACL
POST…/IpAddresses/{Sip_Ip_Address_Sid}Обновление IP-адреса в списке ACL
DELETE…/IpAddresses/{Sip_Ip_Address_Sid}Удаление IP-адреса из списка ACL
GET…/Domains/{…}/Auth/Calls/IpAccessControlListMappingsПолучение привязок ACL по IP к домену
POST…/Domains/{…}/Auth/Calls/IpAccessControlListMappingsПривязка списка ACL по IP к домену
GET…/IpAccessControlListMappings/{Sip_Ip_Control_List_Mapping_Sid}Получение привязки ACL по IP
DELETE…/IpAccessControlListMappings/{Sip_Ip_Control_List_Mapping_Sid}Удаление привязки ACL по IP

3.3.9Ключи API (Keys)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/Keys.

МетодПутьОписание
GET…/KeysПолучение списка API-ключей
POST…/KeysСоздание нового именованного API-ключа
GET…/Keys/{Key_Sid}Получение API-ключа
POST…/Keys/{Key_Sid}Обновление API-ключа
DELETE…/Keys/{Key_Sid}Удаление API-ключа

3.3.10Учёт использования (Usage)

Базовый путь: /2010-04-01/Accounts/{Acc_Sid}/Usage.

МетодПутьОписание
GET…/Usage/RecordsПолучение записей об использовании услуг
GET…/Usage/TriggersПолучение списка триггеров по использованию
POST…/Usage/TriggersСоздание триггера по использованию
GET…/Usage/Triggers/{Usage_Trigger_Sid}Получение триггера по использованию
POST…/Usage/Triggers/{Usage_Trigger_Sid}Обновление триггера по использованию
DELETE…/Usage/Triggers/{Usage_Trigger_Sid}Удаление триггера по использованию

3.3.11BYOC-транки и политики подключения (v1)

Ресурсы для подключения собственного оператора связи (Bring Your Own Carrier). Базовый путь: /v1.

МетодПутьОписание
GET/v1/ByocTrunksПолучение списка BYOC-транков
POST/v1/ByocTrunksСоздание BYOC-транка
GET/v1/ByocTrunks/{ByocTrunk_Sid}Получение BYOC-транка
POST/v1/ByocTrunks/{ByocTrunk_Sid}Обновление BYOC-транка
DELETE/v1/ByocTrunks/{ByocTrunk_Sid}Удаление BYOC-транка
GET/v1/ConnectionPoliciesПолучение списка политик подключения
POST/v1/ConnectionPoliciesСоздание политики подключения
GET…/ConnectionPolicies/{Connection_Policy_Sid}Получение политики подключения
POST…/ConnectionPolicies/{Connection_Policy_Sid}Обновление политики подключения
DELETE…/ConnectionPolicies/{Connection_Policy_Sid}Удаление политики подключения
GET…/ConnectionPolicies/{…}/TargetsПолучение целевых узлов политики подключения
POST…/ConnectionPolicies/{…}/TargetsДобавление целевого узла в политику подключения
GET…/Targets/{Connection_Policy_Target_Sid}Получение целевого узла политики подключения
POST…/Targets/{Connection_Policy_Target_Sid}Обновление целевого узла политики подключения
DELETE…/Targets/{Connection_Policy_Target_Sid}Удаление целевого узла политики подключения

3.3.12Сервисы и файлы сценариев (Services/Assets, v1)

Ресурсы для хранения и версионирования файлов, используемых сценариями (аналог статического хостинга для IVR-сценариев). Базовый путь: /v1/Services.

МетодПутьОписание
GET/v1/ServicesПолучение списка сервисов
POST/v1/ServicesСоздание сервиса
GET/v1/Services/{service_sid}Получение сервиса
POST/v1/Services/{service_sid}Обновление сервиса
DELETE/v1/Services/{service_sid}Удаление сервиса
GET…/Services/{service_sid}/AssetsПолучение списка файлов (Assets) сервиса
POST…/Services/{service_sid}/AssetsСоздание файла (Asset)
GET…/Assets/{asset_sid}Получение файла (Asset)
POST…/Assets/{asset_sid}Обновление файла (Asset)
DELETE…/Assets/{asset_sid}Удаление файла (Asset)
GET…/Services/{service_sid}/AssetGroupsПолучение списка групп файлов (AssetGroups)
POST…/Services/{service_sid}/AssetGroupsСоздание группы файлов
GET…/AssetGroups/{asset_group_sid}Получение группы файлов
POST…/AssetGroups/{asset_group_sid}Обновление группы файлов
DELETE…/AssetGroups/{asset_group_sid}Удаление группы файлов
GET…/AssetGroups/{…}/AssetGroupAssetsПолучение файлов, входящих в группу
POST…/AssetGroups/{…}/AssetGroupAssetsДобавление файла в группу
PATCH…/AssetGroups/{…}/AssetGroupAssetsПолная замена набора файлов в группе
GET…/AssetGroupAssets/{asset_group_asset_sid}Получение файла из группы
POST…/AssetGroupAssets/{asset_group_asset_sid}Обновление файла в группе

3.3.13Визуальные сценарии IVR (Flows, v2)

Ресурсы конструктора визуальных сценариев (Low/No-Code IVR, упомянутого в разделе назначения комплекса) и их выполнения. Базовый путь: /v2/Flows.

МетодПутьОписание
GET/v2/FlowsПолучение списка сценариев (Flow)
POST/v2/FlowsСоздание сценария
POST/v2/Flows/ValidateВалидация сценария
GET/v2/Flows/{Sid}Получение сценария
POST/v2/Flows/{Sid}Обновление сценария
DELETE/v2/Flows/{Sid}Удаление сценария
GET…/Flows/{Sid}/RevisionsПолучение списка версий (ревизий) сценария
GET…/Flows/{Sid}/Revisions/{Revision}Получение конкретной версии сценария
GET…/Flows/{Sid}/TestUsersПолучение тестовых пользователей сценария
POST…/Flows/{Sid}/TestUsersОбновление тестовых пользователей сценария
GET…/Flows/{Flow_Sid}/ExecutionsПолучение списка выполнений (Executions) сценария
POST…/Flows/{Flow_Sid}/ExecutionsЗапуск выполнения сценария
GET…/Executions/{Execution_Sid}Получение выполнения сценария
POST…/Executions/{Execution_Sid}Обновление выполнения сценария
DELETE…/Executions/{Execution_Sid}Удаление выполнения сценария
GET…/Executions/{Execution_Sid}/ContextПолучение контекста выполнения сценария
GET…/Executions/{Execution_Sid}/StepsПолучение шагов выполнения сценария
GET…/Steps/{Step_Sid}Получение шага выполнения сценария
GET…/Steps/{Step_Sid}/ContextПолучение контекста шага выполнения сценария

4Системные требования

Аппаратные требования ПО «CPaaS» складываются из требований к узлам кластера Kubernetes, на котором развертывается основная часть компонентов платформы, и требований к отдельному хосту для компонентов sfas_aas, Kamailio и RtpEngine, разворачиваемых вне кластера Kubernetes.

4.1Требования к кластеру Kubernetes

Минимальная отказоустойчивая конфигурация кластера Kubernetes включает 3 ноды со следующими характеристиками каждая:

Таблица 1. Минимальные требования к узлу кластера Kubernetes

ХарактеристикаЗначение
Количество узлов (нод)3
Количество ядер центрального процессора (на узел)Не менее 2
Тактовая частота центрального процессораНе менее 2.00GHz
Объём оперативной памяти (на узел)Не менее 4Gb
Операционная системаРЕД ОС и другие ОС семейства Linux
Примечание:

При развертывании кластера в однонодовой конфигурации (без отказоустойчивости) суммарные требования к единственному узлу составляют не менее 6 vCPU и не менее 12Gb оперативной памяти — то есть сумма ресурсов трех нод минимальной конфигурации.

4.2Требования к хосту компонентов sfas / Kamailio / RtpEngine

Компоненты sfas_aas, Kamailio и RtpEngine, отвечающие за прием и обработку SIP/RTP-трафика, разворачиваются на отдельном хосте вне кластера Kubernetes.

Таблица 2. Минимальные требования к хосту sfas / Kamailio / RtpEngine

ХарактеристикаЗначение
Количество ядер центрального процессораНе менее 2
Тактовая частота центрального процессораНе менее 2.00GHz
Объём оперативной памятиНе менее 4Gb
Операционная системаРЕД ОС и другие ОС семейства Linux

Указанные конфигурации являются минимальными и могут быть увеличены в зависимости от ожидаемой нагрузки (количества единовременных вызовов, объема обрабатываемого голосового трафика и подключаемых сервисов AI/ML).

Тип развертывания — кластер Kubernetes для основной части компонентов; отдельный выделенный хост — для sfas_aas/Kamailio/RtpEngine. Поддерживается развертывание как на виртуальных машинах (VM), так и на физических серверах (Bare Metal).

4.3Требования к квалификации обслуживающего персонала

К работе с ПО «CPaaS» должны допускаться только должностные лица, имеющие:

опыт работы с UNIX-подобными операционными системами;

практические навыки работы с Kubernetes и Helm;

знание основ администрирования PostgreSQL и RabbitMQ;

базовые знания протокола SIP и понимание принципов телефонии (сигнализация, установление и завершение вызова, передача медиатрафика по RTP/SRTP);

изучившие настоящее руководство по эксплуатации.

5Установка ПО «CPaaS»

5.1Описание установочного пакета

В состав установочного пакета входят:

Helm-чарты (или эквивалентные HelmChart-манифесты) для инфраструктурного уровня: Kyverno, cert-manager, MetalLB, Traefik, CNPG Operator (с плагином резервного копирования plugin-barman-cloud), CSI S3, операторы RabbitMQ (rabbitmq-cluster-operator, rabbitmq-messaging-topology-operator);

Helm-чарты прикладного уровня: cpaas-app (основное приложение), billing (биллинг), api-gw (API Gateway), sengine (сервисный движок сценариев), copula-webui (веб-консоль управления);

вспомогательные чарты инициализации базы данных: миграция схемы и наполнение справочных данных (тарифы и категории использования для биллинга);

образы контейнеров из корпоративного реестра образов;

Kubernetes-манифесты для конфигурации кластеров PostgreSQL, RabbitMQ (включая топологию — виртуальные хосты, пользователи, обменники, очереди, правила) и прочих вспомогательных ресурсов.

Примечание:

Компоненты sfas_aas, Kamailio и RtpEngine в состав установочного пакета Kubernetes не входят и устанавливаются отдельно, на выделенном хосте вне кластера (см. раздел «Требования к хосту компонентов sfas / Kamailio / RtpEngine»). Их сетевые адреса указываются в параметрах конфигурации чартов api-gw и sengine соответственно.

Для выполнения установки необходим доступ к корпоративному реестру образов и Helm-репозиторию (<REPO_AUTH>).

Для выполнения установки войдите в систему с правами, достаточными для работы с кластером Kubernetes. Все дальнейшие действия выполняются в командной строке терминала.

5.2Установка на Kubernetes

Развертывание ПО «CPaaS» выполняется в кластере Kubernetes с использованием MetalLB в качестве балансировщика нагрузки. Установка выполняется последовательно в шесть шагов.

5.2.1Шаг 1. Подготовка кластера Kubernetes

Создание namespace:

kubectl create namespace infrastructure
kubectl create namespace cpaas

Добавить в оба namespace секрет для доступа к реестру образов контейнеров (sifox-imagepull-secret). Также необходимо выбрать или установить дефолтный StorageClass.

Политики Kyverno (опционально):

helm install kyverno kyverno \
  --repo https://kyverno.github.io/kyverno/ \
  --version 3.8.1 -n infrastructure

После установки Kyverno применяется политика, автоматически добавляющая секрет доступа к registry во все поды, создаваемые Helm-чартами (файл kyverno-policy.yaml):

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: add-imagepullsecret-helm-jobs
spec:
  rules:
    - name: add-imagepullsecret-helm-jobs
      match:
        any:
          - resources:
              kinds:
                - Pod
              namespaces:
                - infrastructure
                - cpaas
              selector:
                matchExpressions:
                  - key: helmcharts.helm.cattle.io/chart
                    operator: Exists
      mutate:
        patchStrategicMerge:
          spec:
            imagePullSecrets:
              - name: sifox-imagepull-secret

kubectl apply -f kyverno-policy.yaml

Cert-manager (опционально):

helm install cert-manager cert-manager \
  --repo <REPO_AUTH>/helm/cert-manager-chart/ \
  --version v1.20.2 -n infrastructure \
  --set installCRDs=true \
  --set imagePullSecrets[0].name=sifox-imagepull-secret

5.2.1.1MetalLB

Файл metallb-values.yaml:

imagePullSecrets:
  - name: sifox-imagepull-secret
controller:
  image:
    repository: registry
    tag: v0.15.3
speaker:
  image:
    repository: registry
    tag: v0.15.3
  frr:
    enabled: false

Установка MetalLB:

helm install metallb metallb \
  --repo <REPO_AUTH>/helm/metallb-chart/ \
  --version v0.15.3 -n infrastructure \
  -f metallb-values.yaml

Настройка пула IP-адресов выполняется на следующем шаге (см. «Шаг 2. Настройка сетевой инфраструктуры»).

5.2.1.2Traefik

Установка CRD и контроллера Traefik:

helm install traefik <REPO_AUTH>/helm/traefik/traefik-39.0.9.tgz -n infrastructure

5.2.1.3CNPG Operator

Оператор CloudNativePG управляет жизненным циклом кластеров PostgreSQL в Kubernetes.

Файл cnpg-operator-values.yaml:

imagePullSecrets:
  - name: sifox-imagepull-secret
image:
  repository: <REGISTRY>/cpaas/demo/repo-docker/cloudnative-pg
  tag: "1.29.0"
tolerations:
  - key: "node-role.kubernetes.io/control-plane"
    operator: "Exists"
    effect: "NoSchedule"

Установка:

helm install cnpg-operator cloudnative-pg \
  --repo <REPO_AUTH>/helm/cloudnative-pg-chart/ \
  --version 0.28.0 -n infrastructure \
  -f cnpg-operator-values.yaml

Дополнительно устанавливается плагин plugin-barman-cloud, используемый для резервного копирования кластеров PostgreSQL в объектное хранилище S3:

helm install plugin-barman-cloud plugin-barman-cloud \
  --repo <REPO_AUTH>/helm/plugin-barman-cloud-chart/ \
  --version 0.6.0 -n infrastructure

CSI S3 (опционально) — подключение объектного хранилища как тома:

helm install csi-s3 csi-s3 \
  --repo <REPO_AUTH>/helm/k8s-csi-s3-chart/ \
  --version 0.43.7 -n infrastructure \
  --set imagePullSecret=sifox-imagepull-secret

5.2.1.4Операторы RabbitMQ

Для работы кластера RabbitMQ в Kubernetes требуется установка двух операторов: rabbitmq-cluster-operator (управление кластерами RabbitMQ) и rabbitmq-messaging-topology-operator (управление топологией — виртуальными хостами, пользователями, обменниками, очередями и правилами через Kubernetes-манифесты).

helm install rabbitmq-cluster-operator rabbitmq-cluster-operator \
  --repo <REPO_AUTH>/helm/rabbitmq-cluster-operator-chart/ -n infrastructure

helm install rabbitmq-messaging-topology-operator rabbitmq-messaging-topology-operator \
  --repo <REPO_AUTH>/helm/rabbitmq-messaging-topology-operator-chart/ -n infrastructure

5.2.2Шаг 2. Настройка сетевой инфраструктуры

5.2.2.1Пул IP-адресов MetalLB

После установки MetalLB необходимо добавить пул внешних IP-адресов (свободные адреса из подсети инфраструктуры). Файл metallb-ippool.yaml:

apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: cpaas-pool
  namespace: infrastructure
spec:
  addresses:
    - <SUBNET_CIDR>
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: cpaas-l2
  namespace: infrastructure
spec:
  ipAddressPools:
    - cpaas-pool

Применение:

kubectl apply -f metallb-ippool.yaml

Выделенный из пула адрес в дальнейшем указывается в аннотациях MetalLB (metallb.universe.tf/allow-shared-ip, metallb.universe.tf/loadBalancerIPs) сервисов типа LoadBalancer — веб-консоли, RabbitMQ, внешнего доступа к PostgreSQL и т. д.

5.2.2.2Класс Ingress для namespace cpaas

Для маршрутизации трафика приложений CPaaS отдельно от инфраструктурных сервисов создаётся выделенный класс Ingress Traefik, ограниченный namespace cpaas. Файл traefik-cpaas-values.yaml:

service:
  annotations:
    <metallb annotations>
ingressClass:
  isDefaultClass: false
  name: "cpaas"
providers:
  kubernetesCRD:
    ingressClass: "cpaas"
    namespaces: ["cpaas"]
  kubernetesIngress:
    ingressClass: "cpaas"
    namespaces: ["cpaas"]
  publishedService:
    enabled: true

Установка:

helm install traefik-cpaas <REPO_AUTH>/helm/traefik/traefik-39.0.9.tgz -n cpaas \
  -f traefik-cpaas-values.yaml

5.2.3Шаг 3. PostgreSQL (namespace cpaas)

5.2.3.1Создание секретов

Файл pg-secrets.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: cpaas-rdbms-superuser
  namespace: cpaas
type: kubernetes.io/basic-auth
stringData:
  username: postgres
  password: <PG_SUPERUSER_PASSWORD>
---
apiVersion: v1
kind: Secret
metadata:
  name: cpaas-rdbms-app
  namespace: cpaas
type: kubernetes.io/basic-auth
stringData:
  username: cpaas
  password: <PG_APP_PASSWORD>

Применение:

kubectl apply -f pg-secrets.yaml

5.2.3.2Создание кластера PostgreSQL

Имя кластера — cpaas-rdbms, база данных и пользователь — cpaas, порт — 5432.

Файл pg-cluster.yaml:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cpaas-rdbms
  namespace: cpaas
spec:
  instances: 2
  imageName: <REGISTRY>/cpaas/demo/repo-docker/pg_cloudnative_containers:16.2.0.3
  imagePullSecrets:
    - name: sifox-imagepull-secret
  bootstrap:
    initdb:
      database: cpaas
      owner: cpaas
      dataChecksums: true
      encoding: UTF8
      secret:
        name: cpaas-rdbms-app
  enableSuperuserAccess: true
  superuserSecret:
    name: cpaas-rdbms-superuser
  managed:
    roles:
      - name: cpaas
        ensure: present
        login: true
        superuser: true
        createdb: true
        createrole: true
        replication: true
        passwordSecret:
          name: cpaas-rdbms-app
  postgresql:
    shared_preload_libraries:
      - periods
      - pg_partman_bgw
    parameters:
      max_connections: "100"
      shared_buffers: "1024MB"
      effective_cache_size: "4096MB"
      maintenance_work_mem: "128MB"
      timezone: "UTC"
      pg_partman_bgw.dbname: "cpaas"
      pg_partman_bgw.interval: "3600"
  storage:
    size: 20Gi
    storageClass: fast.ru-1c
  affinity:
    enablePodAntiAffinity: true
    nodeSelector:
      sifox.com/storage: "yes"

Применение и ожидание состояния healthy:

kubectl apply -f pg-cluster.yaml
kubectl -n cpaas get cluster cpaas-rdbms -w
Примечание:

Внутри кластера приложения подключаются к PostgreSQL по адресу cpaas-rdbms-rw.cpaas.svc.cluster.local:5432. Резервное копирование в S3 в поставке выключено; при необходимости в спецификацию кластера добавляется блок backup с доступами к S3 через плагин plugin-barman-cloud (бакет по умолчанию — cpaas-rdbms-backup).

5.2.3.3Внешний доступ к PostgreSQL (опционально)

При необходимости внешнего доступа к PostgreSQL создаются сервисы типа LoadBalancer с общим адресом из пула MetalLB, настроенного на «Шаге 2»: отдельно для записи (порт 5432), чтения (порт 5433) и подключения к любому инстансу (порт 5434). Файл cnpg-svc.yaml:

apiVersion: v1
kind: Service
metadata:
  name: cpaas-rdbms-lb-rw
  namespace: cpaas
  annotations:
    metallb.universe.tf/allow-shared-ip: "<LB_VIP>"
    metallb.universe.tf/loadBalancerIPs: "<LB_VIP>"
spec:
  type: LoadBalancer
  ports:
    - name: postgres
      port: 5432
      protocol: TCP
      targetPort: 5432
  selector:
    cnpg.io/cluster: cpaas-rdbms
    role: primary
---
apiVersion: v1
kind: Service
metadata:
  name: cpaas-rdbms-lb-ro
  namespace: cpaas
  annotations:
    metallb.universe.tf/allow-shared-ip: "<LB_VIP>"
    metallb.universe.tf/loadBalancerIPs: "<LB_VIP>"
spec:
  type: LoadBalancer
  ports:
    - name: postgres
      port: 5433
      protocol: TCP
      targetPort: 5432
  selector:
    cnpg.io/cluster: cpaas-rdbms
    role: replica
---
apiVersion: v1
kind: Service
metadata:
  name: cpaas-rdbms-lb-r
  namespace: cpaas
  annotations:
    metallb.universe.tf/allow-shared-ip: "<LB_VIP>"
    metallb.universe.tf/loadBalancerIPs: "<LB_VIP>"
spec:
  type: LoadBalancer
  ports:
    - name: postgres
      port: 5434
      protocol: TCP
      targetPort: 5432
  selector:
    cnpg.io/cluster: cpaas-rdbms
    cnpg.io/podRole: instance

Применение и проверка:

kubectl apply -f cnpg-svc.yaml
kubectl get svc -n cpaas

5.2.4Шаг 4. RabbitMQ (namespace cpaas)

5.2.4.1Создание кластера RabbitMQ

Имя — cpaas-rmq, порт AMQP — 5672, управление через ingress по пути /cpaas-rmq.

Файл rmq-cluster.yaml:

apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
  name: cpaas-rmq
  namespace: cpaas
spec:
  replicas: 1
  resources:
    requests:
      cpu: 100m
      memory: 300Mi
  rabbitmq:
    additionalPlugins:
      - rabbitmq_management
      - rabbitmq_consistent_hash_exchange
    additionalConfig: |
      management.path_prefix = /cpaas-rmq
  service:
    type: LoadBalancer
    annotations:
      <metallb annotations>
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
          - matchExpressions:
              - key: sifox.com/storage
                operator: In
                values: ["yes"]

Применение:

kubectl apply -f rmq-cluster.yaml
kubectl -n cpaas get rabbitmqcluster cpaas-rmq -w

Для управления кластером через веб-интерфейс RabbitMQ Management настраивается Ingress по пути /cpaas-rmq, а также PodDisruptionBudget, ограничивающий количество одновременно недоступных реплик при плановом обслуживании (файл rmq-ingress.yaml):

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: cpaas-rmq
  namespace: cpaas
spec:
  maxUnavailable: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: cpaas-rmq
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cpaas-rmq
  namespace: cpaas
spec:
  ingressClassName: cpaas
  rules:
    - http:
        paths:
          - path: /cpaas-rmq
            pathType: Prefix
            backend:
              service:
                name: cpaas-rmq
                port:
                  number: 15672

kubectl apply -f rmq-ingress.yaml

Применение топологии (виртуальные хосты, обменники, очереди):

kubectl apply -f rmq-topology.yaml
5.2.4.1.1Проверка результата настройки RabbitMQ

После успешного развертывания ожидаемый результат команд проверки:

$ rabbitmqctl list_vhosts
/
cpaas

$ rabbitmqctl list_users
default_user_IkVHNimNqhpYPffh_v1   [administrator]
cpaas                               [policymaker]

$ rabbitmqctl list_permissions -p cpaas
user                                configure  write  read
default_user_IkVHNimNqhpYPffh_v1   .*         .*     .*
cpaas                               .*         .*     .*

$ rabbitmqctl list_exchanges -p cpaas name type durable auto_delete
x-cpaas    topic  true  false
dlx-cpaas  topic  true  false
amq.topic  topic  true  false
amq.direct direct true  false

$ rabbitmqctl list_queues -p cpaas name type durable auto_delete messages
q_call                          quorum  true  false  0
q_billing_se_back_notifications quorum  true  false  0
q_cdr_ext                       quorum  true  false  0
q_normalizer                    quorum  true  false  0
q_transcriber                   quorum  true  false  0
q_billing_filer                 quorum  true  false  0
q_filer                         quorum  true  false  0
q_billing_usage                 quorum  true  false  0
q_combiner                      quorum  true  false  0
q_trimmer                       quorum  true  false  0
q_convertor                     quorum  true  false  0
q_sengine                       quorum  true  false  0
q_logs                          quorum  true  false  0
q_billing_trigger               quorum  true  false  0
Примечание:

Дополнительно применяется топология очередей интеграции с сервисом sfas_aas (q_sfas_filer_sfas-0 — передача записей разговоров, q_cdr_ext — передача данных о вызовах для биллинга), развёрнутым вне кластера Kubernetes.

5.2.5Шаг 5. Инициализация базы данных

5.2.5.1Миграция схемы БД

Файл db-migrate-values.yaml:

db:
  host: cpaas-rdbms-rw.cpaas.svc.cluster.local
  port: 5432
  name: cpaas
  user: cpaas
  passwordSecret:
    name: cpaas-rdbms-app
    key: password
migrate:
  image: <REGISTRY>/common/debug-tools-k8s/debug-k8s-s3:latest
  command: up
  version: ""
archive:
  url: "<REPO_AUTH>/cpaas/cpaasdb/db_migrate/ansible-role-db-cpaas.v0.3.14.tar.gz"
  authSecret: ""
imagePullSecret: sifox-imagepull-secret

Установка (запускает job миграции):

helm upgrade --install cpaas-db-migrate <HELM_OCI>/cpaas/helm/cpaas-db-migrate \
  --version 0.0.1 -n cpaas \
  -f db-migrate-values.yaml

После выполнения job необходимо убедиться, что миграции применены без ошибок:

kubectl exec -it -n cpaas cpaas-rdbms-1 -- psql -c "\c cpaas" -c "SELECT * FROM schema_migrations;"

5.2.5.2Наполнение справочных данных

Отдельным вспомогательным чартом выполняется наполнение служебных справочников биллинга: создаётся тариф по умолчанию и базовые расценки по категориям использования (исходящие/входящие вызовы, конференц-связь, запись и хранение разговоров, транскрибация, распознавание речи, подключенные номера, сообщения). Данные задаются в виде идемпотентных SQL-запросов (INSERT ... ON CONFLICT / условное UPDATE), выполняемых при каждой установке чарта, — повторное применение не создаёт дублей и не затирает уже изменённые вручную значения. Файл values-db-insert.yaml (пример для одной категории использования; конкретные тарифные значения задаются индивидуально и не входят в состав настоящего руководства):

db:
  host: cpaas-rdbms-rw.cpaas.svc.cluster.local
  port: 5432
  name: cpaas
  user: cpaas
  passwordSecret:
    name: cpaas-rdbms-app
    key: password
queries:
  - "INSERT INTO cpaas.tariffs AS t (id, friendly_name, price_unit)
     VALUES (1, 'default tariff', 'rub')
     ON CONFLICT (id) DO UPDATE SET friendly_name = EXCLUDED.friendly_name, price_unit = EXCLUDED.price_unit
     WHERE t.friendly_name != 'default tariff' OR t.price_unit != 'rub'"
  - "DO $$ BEGIN
       IF NOT EXISTS (SELECT 1 FROM cpaas.tariff_usage_prices
                       WHERE tariff_id = 1 AND usage_category = '<USAGE_CATEGORY>') THEN
         INSERT INTO cpaas.tariff_usage_prices
           (tariff_id, usage_category, price_unit, price_per_unit, usage_unit, num_of_units)
         VALUES (1, '<USAGE_CATEGORY>', 'rub', <PRICE>, '<UNIT>', 1);
       ELSE
         UPDATE cpaas.tariff_usage_prices SET price_unit = 'rub', price_per_unit = <PRICE>,
           usage_unit = '<UNIT>', num_of_units = 1
         WHERE tariff_id = 1 AND usage_category = '<USAGE_CATEGORY>';
       END IF;
     END $$"
imagePullSecret: sifox-imagepull-secret

Аналогичные запросы (с собственными значениями usage_category, price_per_unit и usage_unit) добавляются для каждой тарифицируемой категории: исходящие/входящие вызовы, конференц-связь, транскрибация, распознавание речи, хранение и запись разговоров, аренда номеров, отправка сообщений.

helm upgrade --install cpaas-db-insert <HELM_OCI>/cpaas/helm/cpaas-db-insert \
  --version 0.0.1 -n cpaas \
  -f values-db-insert.yaml

5.2.6Шаг 6. Развертывание прикладных компонентов CPaaS

Прикладные компоненты устанавливаются в namespace cpaas в следующем порядке: основное приложение, биллинг, API Gateway, сервисный движок сценариев и веб-консоль управления.

5.2.6.1Основное приложение (cpaas-app)

Файл cpaas-app-values.yaml (чарт версии 0.0.8, образ версии 0.5.4):

erlCookie: <ERL_COOKIE>
replicaCount: 1
image:
  repository: <REGISTRY>
  tag: "0.5.4"
imagePullSecrets:
  - name: sifox-imagepull-secret
debug:
  mq: 'false'
  rs: 'false'
  stt: 'false'
  s3: 'false'
  tppapi: 'false'
Vosk:
  sttCheck: 'false'
  channel1Host: "asr-stt"
  channel1Port: 5001
  channel1EndpointsNum: 2
  channel2Host: "asr-stt"
  channel2Port: 5001
  channel2EndpointsNum: 2
TppApi:
  check: 'false'
rmq:
  username: cpaas
  password: <RMQ_PASSWORD>
  vhost: cpaas
  exchange: x-cpaas
  haVip: cpaas-rmq
  haAmqpPort: 5672
s3:
  endpoint: "<S3 ENDPOINT>"
  access_key: <S3_ACCESS_KEY>
  secret_key: <S3_SECRET_KEY>
  tmp_bucket: cpaas-app-tmp
radioSilence:
  repository: <REGISTRY>
  tag: "1.6.2"

Установка:

helm install cpaas-app <HELM_OCI>/cpaas/helm/cpaas-app \
  --version 0.0.8 -n cpaas \
  -f cpaas-app-values.yaml

5.2.6.2Биллинг (billing)

Файл values-billing.yaml (чарт версии 0.0.1, образ версии v0.0.34):

replicaCount: 1
image:
  repository: <REGISTRY>
  tag: "v0.0.34"
imagePullSecrets:
  - name: sifox-imagepull-secret
resources:
  requests:
    memory: "28Mi"
    cpu: "50m"
  limits:
    memory: "256Mi"
    cpu: "1000m"
secrets:
  pgPassword: <PG_PASSWORD>
  rmqPassword: <RMQ_PASSWORD>
Billing:
  domainId: 1
  domainName: "PROD"
  clusterId: 1
  defaultTariffId: 1
  pg:
    hostname: cpaas-rdbms-rw
    port: 5432
    database: cpaas
    username: cpaas
  rmq:
    host: cpaas-rmq
    port: 5672
    user: cpaas
    vhost: cpaas
    exchange: x-cpaas
  grpc:
    apigwHost: api-gw
    apigwPort: 8001

Установка:

helm install billing <HELM_OCI>/cpaas/helm/billing \
  --version 0.0.1 -n cpaas \
  -f values-billing.yaml

5.2.6.3API Gateway (api-gw)

Файл values-api-gw.yaml (чарт версии 0.0.4, образ версии v0.14.2):

image:
  repository: <REGISTRY>
  tag: "v0.14.2"
imagePullSecrets:
  - name: sifox-imagepull-secret
CpaasApiGw:
  s3AccessKey: <S3_ACCESS_KEY>
  grpcClients:
    sipaas:
      enabled: true
      host: "<SIPAAS_HOST>"
secrets:
  pgPassword: <PG_PASSWORD>
  s3SecretKey: <S3_SECRET_KEY>
Примечание:

Параметр grpcClients.sipaas.host указывает на адрес компонента Kamailio/sipaas, развёрнутого на отдельном хосте вне кластера Kubernetes (см. раздел «Требования к хосту компонентов sfas / Kamailio / RtpEngine»).

Установка:

helm install api-gw <HELM_OCI>/cpaas/helm/api-gw \
  --version 0.0.4 -n cpaas \
  -f values-api-gw.yaml

5.2.6.4Сервисный движок сценариев (sengine)

Файл values-sengine.yaml (чарт версии 0.0.2, образ версии v0.9.14):

replicaCount: 2
image:
  repository: <REGISTRY>
  tag: "v0.9.14"
imagePullSecrets:
  - name: sifox-imagepull-secret
persistence:
  storageClass: fast.ru-1c
  size: "1Gi"
  mountPath: "/mnesia"
resources:
  requests:
    memory: "128Mi"
    cpu: "150m"
  limits:
    memory: "512Mi"
    cpu: "500m"
secrets:
  s3AccessKeyId: <S3_ACCESS_KEY>
  s3SecretAccessKey: <S3_SECRET_KEY>
  rmqPassword: <RMQ_PASSWORD>
Sengine:
  domainId: 1
  domainName: "PROD"
  clusterId: 1
  instanceId: 0
  sfas:
    channels:
      - name: "sfas_channel_1"
        ip: "<SFAS_HOST>"
        port: 8000
  s3:
    endpoints:
      - "<S3 ENDPOINT>"
    mediaBucket: cache
    recordBucket: records
  rmq:
    user: cpaas
    ip: cpaas-rmq
    port: 5672
    vhost: cpaas
    exchange: x-cpaas
  grpcClients:
    apigwChannel1:
      host: api-gw
      port: 8001
      endpointsNum: 4
    apigwChannel2:
      host: api-gw
      port: 8001
      endpointsNum: 4
Примечание:

Параметр Sengine.sfas.channels[].ip указывает на адрес компонента sfas_aas, развёрнутого на отдельном хосте вне кластера Kubernetes.

Установка:

helm install sengine <HELM_OCI>/cpaas/helm/sengine \
  --version 0.0.2 -n cpaas \
  -f values-sengine.yaml

5.2.6.5Веб-консоль управления (copula-webui)

Файл values-copula-webui.yaml (чарт версии 0.0.3, образ версии 0.4.1):

image:
  tag: "0.4.1"
imagePullSecrets:
  - name: sifox-imagepull-secret
service:
  loadBalancerIP: "<LB_VIP>"
  annotations:
    <metallb annotations>
secrets:
  appApiKey: <APP_API_KEY>
  dbUsername: cpaas
  dbPassword: <PG_PASSWORD>
appConfig:
  springDatasourceUrl: "jdbc:postgresql://cpaas-rdbms-rw:5432/cpaas"
  apiGwBasePath: "http://<LB_VIP>:80"
  grpcClientApiGwAddress: "static://billing:8014"
  loggingLevelRoot: "INFO"

При установке веб-консоли выполняется вспомогательный init-контейнер, загружающий актуальную сборку статического веб-интерфейса (консоль и административная панель) из корпоративного репозитория артефактов и распаковывающий её в общий с основным контейнером том. Загрузка пропускается, если версия уже загруженной сборки совпадает с ожидаемой (файл ver.txt в томе статики):

initContainers:
  - name: wget-models
    image: "<REGISTRY>/cpaas/demo/repo-docker/alpine:3.19.1"
    command: ["sh", "-c"]
    args:
      - |
        EXPECTED="<REPO_AUTH>/cpaas/web-ui/copula-console/copula-console-v0.3.16.tgz:/workspace/static/console/:3"
        if [ -f /workspace/static/ver.txt ] && [ "$(cat /workspace/static/ver.txt)" = "$EXPECTED" ]; then
          echo "Static already up to date, skip"; exit 0;
        fi
        mkdir -p /workspace/static/console /workspace/static/console2 /workspace/static/adm
        wget -O /tmp/console.tgz "<REPO_AUTH>/cpaas/web-ui/copula-console/copula-console-v0.3.16.tgz"
        tar -xzf /tmp/console.tgz -C /workspace/static/console --strip-components=3
        wget -O /tmp/console-admin.tgz "<REPO_AUTH>/cpaas/web-ui/copula-console-admin/copula-console-admin-v0.0.2.tgz"
        tar -xzf /tmp/console-admin.tgz -C /workspace/static/adm --strip-components=3
        echo "$EXPECTED" > /workspace/static/ver.txt
    volumeMounts:
      - name: static
        mountPath: /workspace/static/

Установка:

helm install copula-webui <HELM_OCI>/cpaas/helm/copula-webui \
  --version 0.0.3 -n cpaas \
  -f values-copula-webui.yaml

После установки веб-консоль доступна по адресу, указанному в service.loadBalancerIP (порт 80/443 в зависимости от конфигурации Ingress).

5.3Установка компонентов вне кластера Kubernetes

Компоненты sfas_aas, Kamailio и RtpEngine, отвечающие за прием и обработку сигнального (SIP) и медийного (RTP) трафика, в состав Kubernetes-инсталляции не входят и устанавливаются отдельно, на выделенном хосте вне кластера. Аппаратные требования к такому хосту приведены в разделе «Требования к хосту компонентов sfas / Kamailio / RtpEngine».

5.3.1Установка

Для установки должны быть выделены вычислительные мощности согласно аппаратным требованиям, указанным выше. Установка выполняется с использованием предоставляемого набора ansible-скриптов.

Примечание:

<имя пользователя> — учётная запись пользователя на целевых хостах, имеющая доступ к повышению привилегий с помощью команды sudo.

.vault.pass — файл с GPG-ключом, с помощью которого зашифрованы чувствительные данные с помощью механизма Ansible Vault.

Перед установкой необходимо выполнить корректировку переменных и шаблонов ansible в соответствии с целевым окружением.

Установка FreeSWITCH и sfas_aas:

ansible-playbook --vault-password-file=.vault.pass -u <имя пользователя> -v -i hosts cpaas-not-k8s.yml

Аналогичным образом выполняется установка Kamailio, RtpEngine и дополнительных компонентов:

ansible-playbook --vault-password-file=.vault.pass -u <имя пользователя> -v -i hosts kamailio.yml

Интеграция внешнего хоста с компонентами, развернутыми в кластере, задаётся исключительно параметрами конфигурации соответствующих Helm-чартов:

Таблица 3. Параметры интеграции с компонентами вне кластера Kubernetes

Внешний компонентЧарт / параметрНазначение
Kamailio / sipaasapi-gw: CpaasApiGw.grpcClients.sipaas.hostадрес узла, принимающего SIP/SIP(S)-трафик и передающего его через api-gw в остальную часть платформы
sfas_aassengine: Sengine.sfas.channels[].ip, portадрес и порт канала взаимодействия sengine с sfas_aas (обработка речи, аудио)
sfas_aasтопология RabbitMQ: очереди q_sfas_filer_sfas-0, q_cdr_extпередача записей разговоров (sfas_aas.sfas-0.record) и данных о вызовах для биллинга (sfas_aas.*.cdr) по AMQP

После изменения адреса внешнего хоста в файлах values-api-gw.yaml или values-sengine.yaml необходимо выполнить обновление соответствующего Helm-чарта (см. раздел «Обновление и удаление»), чтобы новое значение было применено.

6Настройка ПО «CPaaS»

Настоящий раздел описывает прикладную настройку ПО «CPaaS» после установки: создание аккаунта, подключение номеров и настройку SIP-транков для исходящих и входящих вызовов. Параметры развёртывания компонентов (Helm-чарты, Kubernetes-манифесты) описаны в разделе «Установка ПО «CPaaS»».

6.1Создание аккаунта через веб-консоль

1.Открыть в браузере административный раздел веб-консоли по адресу http://<WEBUI_HOST>:<PORT>/adm/.

2.В открывшейся форме ввести API-ключ — тот же, что указан в параметре secrets.appApiKey при установке чарта copula-webui (см. раздел «Веб-консоль управления (copula-webui)»).

3.В поле «Friendly Name» указать произвольное имя создаваемого аккаунта.

4.Нажать «Создать» — будет сгенерирована ссылка на форму регистрации.

5.Перейти по ссылке и завершить регистрацию, указав адрес электронной почты и пароль.

6.2Настройка посредством API

Настройка аккаунта выполняется напрямую через базу данных и API.

6.2.1Получение идентификатора и токена аккаунта

Идентификатор аккаунта (Account SID) отображается в веб-консоли в разделе «Профиль». Токен аутентификации (Auth Token) можно получить из базы данных:

SELECT * FROM cpaas.accounts;

-[ RECORD 1 ]------+-----------------------------------------------
sid                | <ACCOUNT_SID>
parent_account_sid | <ACCOUNT_SID>
auth_token         | <AUTH_TOKEN>
date_created       | <TIMESTAMP>
date_updated       | <TIMESTAMP>
friendly_name      | <ACCOUNT_NAME>
status             | active
type               | full
is_main            | t
Внимание:

Значение auth_token является конфиденциальным и используется для аутентификации запросов к API; оно не должно передаваться или храниться в открытом виде.

6.2.2Добавление страны и телефонного номера

Для работы с исходящими вызовами в справочники базы данных добавляется поддерживаемая страна и номер, с которым платформа регистрируется у оператора связи:

INSERT INTO cpaas.countries (code, country, available, description, system_start, system_end)
VALUES ('RU', 'Russian Federation', 't', ' ', '<TIMESTAMP>', 'infinity');

INSERT INTO cpaas.available_phone_numbers
  (friendly_name, phone_number, locality, sms_enabled, voice_enabled, available, type, country_code)
VALUES ('<FRIENDLY_NAME>', '<PHONE_NUMBER>', '<CITY>', true, true, true, 'sim_card', 'RU');

6.2.3Определение адреса API Gateway

Адрес обращения к API (APIGW_ENDPOINT) зависит от способа публикации сервиса api-gw — через Service типа LoadBalancer (порт, как правило, 4000) либо через Ingress (порт 80). Пример манифеста Ingress, маршрутизирующего запросы к путям /2010-04-01/Accounts и /v1 на порт 4000 сервиса api-gw:

kubectl get ingress -n cpaas api-gw -o yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gw
  namespace: cpaas
spec:
  ingressClassName: cpaas
  rules:
    - http:
        paths:
          - path: /2010-04-01/Accounts
            pathType: Prefix
            backend:
              service:
                name: api-gw
                port:
                  number: 4000
          - path: /v1
            pathType: Prefix
            backend:
              service:
                name: api-gw
                port:
                  number: 4000
status:
  loadBalancer:
    ingress:
      - ip: <LB_VIP>

Подготовка окружения для работы с API:

export APIGW_ENDPOINT="http://<LB_VIP>"
export APIGW_AUTH="<ACCOUNT_SID>:<AUTH_TOKEN>"

Проверка доступа (получение списка подключённых номеров):

curl -X GET "$APIGW_ENDPOINT/2010-04-01/Accounts/<ACCOUNT_SID>/IncomingPhoneNumbers" \
  -H 'accept: application/json' \
  -u $APIGW_AUTH | jq '.'

6.3Настройка SIP-транка для исходящих вызовов

1.Создать ресурс ConnectionPolicy — параметры регистрации на SIP-домене оператора связи:

curl -X POST "$APIGW_ENDPOINT/v1/ConnectionPolicies" \
  -H 'accept: application/json' -H 'Content-Type: application/json' \
  -d '{
    "AuthUsername": "<PHONE_NUMBER>@<CARRIER_SIP_DOMAIN>",
    "Domain": "<CARRIER_SIP_DOMAIN>",
    "FriendlyName": "<NAME>",
    "Password": "<CARRIER_SIP_PASSWORD>",
    "Realm": "<CARRIER_SIP_REALM>",
    "Register": true,
    "Username": "<PHONE_NUMBER>"
  }' \
  -u $APIGW_AUTH | jq '.'

В ответе возвращается идентификатор политики подключения (sid), используемый на следующих шагах.

2.Создать ресурс ConnectionPolicyTarget — SIP-адрес узла оператора связи, на который отправляются вызовы:

curl -X POST "$APIGW_ENDPOINT/v1/ConnectionPolicies/<CONNECTION_POLICY_SID>/Targets" \
  -u "$APIGW_AUTH" -H "Accept: application/json" -H "Content-Type: application/json" \
  -d '{"Target":"sip:<CARRIER_SIP_DOMAIN>:5060;transport=udp","FriendlyName":"<NAME>","Enabled":true}'

3.Создать ресурс BYOC Trunk, связанный с созданной политикой подключения:

curl -X POST "$APIGW_ENDPOINT/v1/ByocTrunks?FriendlyName=<NAME>&ConnectionPolicySid=<CONNECTION_POLICY_SID>" \
  -H 'accept: application/json' -u $APIGW_AUTH | jq '.'

4.Добавить SIP-домен, используемый для исходящих вызовов через созданный транк:

curl -X POST "$APIGW_ENDPOINT/2010-04-01/Accounts/<ACCOUNT_SID>/SIP/Domains?DomainName=<CARRIER_SIP_DOMAIN>&FriendlyName=<NAME>" \
  -H 'accept: application/json' -u $APIGW_AUTH | jq '.'

5.Убедиться, что созданный транк связан с доменом (поле from_domain_sid должно соответствовать идентификатору созданного домена):

SELECT * FROM cpaas.trunks;

6.4Настройка для входящих вызовов

1.Добавить SIP-домен для входящих вызовов — в качестве имени домена указывается внешний адрес интерфейса SBC-узла, принимающего SIP-трафик от оператора связи:

curl -X POST "$APIGW_ENDPOINT/2010-04-01/Accounts/<ACCOUNT_SID>/SIP/Domains?DomainName=<SBC_EXTERNAL_IP>&FriendlyName=<NAME>" \
  -H 'accept: application/json' -u $APIGW_AUTH | jq '.'

2.Создать ресурс SipIpAccessControlList (список контроля доступа по IP-адресам):

curl -X POST "$APIGW_ENDPOINT/2010-04-01/Accounts/<ACCOUNT_SID>/SIP/IpAccessControlLists?FriendlyName=<NAME>" \
  -H 'accept: application/json' -u $APIGW_AUTH | jq '.'

3.Привязать список контроля доступа к SIP-домену (SipIpAccessControlListMapping):

curl -X POST "$APIGW_ENDPOINT/2010-04-01/Accounts/<ACCOUNT_SID>/SIP/Domains/<DOMAIN_SID>/Auth/Calls/IpAccessControlListMappings?IpAccessControlListSid=<ACL_SID>" \
  -H 'accept: application/json' -u $APIGW_AUTH | jq '.'

4.Добавить в список контроля доступа IP-адрес, с которого оператор связи отправляет SIP-сообщения:

curl -X POST "$APIGW_ENDPOINT/2010-04-01/Accounts/<ACCOUNT_SID>/SIP/IpAccessControlLists/<ACL_SID>/IpAddresses?FriendlyName=<CARRIER_NAME>&IpAddress=<CARRIER_SIP_IP>&CidrPrefixLength=32" \
  -H 'accept: application/json' -u $APIGW_AUTH | jq '.'

7Запуск, перезапуск и завершение работы

Запуск, перезапуск и остановка ПО «CPaaS» осуществляются стандартными средствами Kubernetes.

7.1Запуск

# 1. Снять PostgreSQL с гибернации
kubectl annotate cluster cpaas-rdbms -n cpaas cnpg.io/hibernate-

# 2. Дождаться готовности БД
kubectl -n cpaas wait --for=condition=Ready cluster/cpaas-rdbms --timeout=300s

# 3. Запустить RabbitMQ
kubectl scale rabbitmqcluster cpaas-rmq -n cpaas --replicas=1

# 4. Дождаться готовности RabbitMQ
kubectl -n cpaas wait --for=condition=Ready rabbitmqcluster/cpaas-rmq --timeout=300s

# 5. Запустить приложение
kubectl scale deployment cpaas-app -n cpaas --replicas=1

7.2Перезапуск

# Перезапустить приложение
kubectl rollout restart deployment cpaas-app -n cpaas

# Перезапустить RabbitMQ
kubectl delete pod -l app.kubernetes.io/name=cpaas-rmq -n cpaas

# Перезапустить PostgreSQL (с сохранением данных)
kubectl -n cpaas cnpg restart cpaas-rdbms

7.3Останов

# 1. Остановить приложение
kubectl scale deployment cpaas-app -n cpaas --replicas=0

# 2. Остановить RabbitMQ
kubectl scale rabbitmqcluster cpaas-rmq -n cpaas --replicas=0

# 3. Перевести PostgreSQL в гибернацию
kubectl annotate cluster cpaas-rdbms -n cpaas --overwrite cnpg.io/hibernate=true

8Обновление и удаление

Обновление и удаление ПО «CPaaS» выполняются с помощью штатных механизмов Kubernetes и Helm.

8.1Обновление

Примечание:

Перед обновлением рекомендуется создать резервную копию базы данных и сохранить актуальные файлы конфигурации (values.yaml) всех установленных чартов.

Обновление конфигурации без смены версии:

helm upgrade cpaas-app <HELM_OCI>/cpaas/helm/cpaas-app \
  --version 0.0.8 -n cpaas \
  -f cpaas-app-values.yaml

Обновление до новой версии:

helm upgrade cpaas-app <HELM_OCI>/cpaas/helm/cpaas-app \
  --version <NEW_VERSION> -n cpaas \
  -f cpaas-app-values.yaml

Откат к предыдущей версии:

helm rollback cpaas-app -n cpaas

8.2Удаление

Удаление приложения:

helm uninstall cpaas-app -n cpaas
Внимание:

Удаление namespace cpaas приведёт к безвозвратному удалению всех данных, включая базу данных PostgreSQL. Перед удалением необходимо убедиться в наличии актуальной резервной копии.

Удаление всего namespace CPaaS вместе с данными:

kubectl delete namespace cpaas

Удаление инфраструктурных компонентов:

helm uninstall metallb -n infrastructure
helm uninstall traefik -n infrastructure
helm uninstall cnpg-operator -n infrastructure
kubectl delete namespace infrastructure

9Проверка работоспособности

Проверка работоспособности ПО «CPaaS» осуществляется путём проверки текущего состояния всех компонентов.

Для выполнения проверки необходимо обладать правами на чтение ресурсов в namespace cpaas и infrastructure.

Просмотр статуса всех подов и кластеров:

# Состояние подов платформы
kubectl get pods -n cpaas

# Состояние подов инфраструктуры
kubectl get pods -n infrastructure

# Статус кластеров PostgreSQL и RabbitMQ
kubectl -n cpaas get cluster,rabbitmqcluster

Все поды должны находиться в состоянии Running, кластер PostgreSQL — в состоянии healthy, кластер RabbitMQ — в состоянии allReplicasReady.

Проверка состояния PostgreSQL:

kubectl -n cpaas get cluster cpaas-rdbms -w

Проверка состояния RabbitMQ:

kubectl -n cpaas get rabbitmqcluster cpaas-rmq -w

Проверка доступности PostgreSQL изнутри пода:

kubectl -n cpaas exec -it <pod-name> -- \
  psql postgresql://cpaas:<PASSWORD>@cpaas-rdbms-rw.cpaas.svc.cluster.local:5432/cpaas \
  -c "SELECT 1"

Проверка очередей RabbitMQ:

kubectl -n cpaas exec -it cpaas-rmq-server-0 -- \
  rabbitmqctl list_queues -p cpaas name messages

10Log guide. Анализ диагностической информации

Журналы ПО «CPaaS» собираются стандартными средствами Kubernetes и доступны через kubectl logs.

Уровни протоколирования основного приложения задаются в конфигурации. Доступны следующие уровни:

Таблица 4. Уровни логирования

УровеньОписание
errorКритические ошибки, влияющие на работоспособность
warningПредупреждения, не блокирующие работу платформы
noticeВажные события штатной работы (подключения, старт)
infoИнформационные сообщения (уровень по умолчанию)
debugПодробная отладочная информация

По умолчанию ПО «CPaaS» протоколирует события с уровнем info. Каждый следующий уровень включает в себя сообщения предыдущего.

ПО «CPaaS» использует JSON-формат для структурированного логирования:

{
  "level": "notice",
  "msg": "RabbitMQ connection established",
  "time": "2024-01-15T10:23:45.123456789Z",
  "component": "cpaas-app"
}

Команды для работы с журналами:

Просмотр журнала основного приложения (последние 100 строк):

kubectl -n cpaas logs -l app=cpaas-app --tail=100

Просмотр журнала в режиме реального времени:

kubectl -n cpaas logs -l app=cpaas-app -f

Просмотр только ошибок:

kubectl -n cpaas logs -l app=cpaas-app --tail=500 | grep '"level":"error"'

Просмотр журнала PostgreSQL:

kubectl -n cpaas logs cpaas-rdbms-1 -c postgres --tail=100

Просмотр журнала RabbitMQ:

kubectl -n cpaas logs cpaas-rmq-server-0 --tail=100

Если в журнале появляются записи об ошибках подключения к RabbitMQ или к сервису ASR, необходимо проверить доступность соответствующего сервиса и корректность его настроек в cpaas-app-values.yaml.

11Мониторинг работы

ПО «CPaaS» предоставляет метрики для внешних систем мониторинга по протоколу HTTP в формате Prometheus. Адрес и порт экспортера задаются в конфигурации (по умолчанию 0.0.0.0:9103).

Основные метрики cpaas-app:

Таблица 5. Прикладные метрики CPaaS

МетрикаТипОписание
cpaas_calls_totalcounterОбщее количество обработанных вызовов
cpaas_calls_activegaugeКоличество активных (текущих) вызовов
cpaas_rmq_messages_sentcounterКоличество сообщений, успешно отправленных в RabbitMQ
cpaas_rmq_messages_failedcounterКоличество необработанных (сброшенных) сообщений
cpaas_stt_requests_totalcounterКоличество запросов к сервису распознавания речи
cpaas_stt_errors_totalcounterКоличество ошибок сервиса распознавания речи

Рекомендуемые метрики для дашборда:

1.Нагрузка:

cpaas_calls_active — текущее количество активных вызовов;

rate(cpaas_calls_total[1m]) — динамика вызовов за период;

rate(cpaas_rmq_messages_sent[1m]) — интенсивность обработки сообщений.

2.Ошибки (алерты при значениях > 0):

rate(cpaas_rmq_messages_failed[1m]) — сброшенные сообщения RabbitMQ;

rate(cpaas_stt_errors_total[1m]) — ошибки сервиса STT.

Мониторинг инфраструктуры Kubernetes:

Помимо прикладных метрик рекомендуется настроить мониторинг через kube-state-metrics и node-exporter:

kube_pod_status_phase{namespace="cpaas"} — статус подов платформы;

kube_deployment_status_replicas_available{namespace="cpaas"} — доступные реплики;

rabbitmq_queue_messages{vhost="cpaas"} — количество сообщений в очередях RabbitMQ;

node_memory_MemAvailable_bytes — доступная оперативная память на узлах.

Примечание:

При организации мониторинга следует учитывать тип метрик (counter, gauge) и использовать соответствующие функции Prometheus для подсчёта нагрузки за период: irate, rate.

12Troubleshooting. Устранение неисправностей

Для своевременного обнаружения проблем рекомендуется настроить оповещение на перечисленные ниже условия.

12.1Поды находятся в состоянии Pending

Симптом: команда kubectl get pods -n cpaas показывает статус Pending.

Диагностика:

kubectl describe pod <pod-name> -n cpaas
kubectl get events -n cpaas --sort-by='.lastTimestamp'

Возможные причины и решения:

Нет узлов с нужными метками — проверить nodeSelector в манифесте и метки на узлах:

kubectl get nodes --show-labels | grep sifox.com/storage

Нехватка ресурсов — проверить доступные ресурсы на узлах:

kubectl describe nodes | grep -A 5 "Allocated resources"

PersistentVolumeClaim не создан — проверить статус PVC:

kubectl get pvc -n cpaas

12.2Кластер PostgreSQL не переходит в состояние healthy

Симптом: kubectl -n cpaas get cluster cpaas-rdbms показывает статус, отличный от healthy.

Диагностика:

kubectl -n cpaas describe cluster cpaas-rdbms
kubectl -n cpaas logs cpaas-rdbms-1 -c postgres --tail=100

Возможные причины и решения:

Секреты не созданы — убедиться в наличии необходимых секретов:

kubectl get secrets -n cpaas | grep cpaas-rdbms

StorageClass недоступен — проверить наличие и доступность StorageClass:

kubectl get storageclass

12.3Ошибки подключения к RabbitMQ

Симптом: в журналах cpaas-app появляются ошибки подключения к брокеру сообщений.

Диагностика:

kubectl -n cpaas logs -l app=cpaas-app --tail=100 | grep -i rmq
kubectl -n cpaas get rabbitmqcluster cpaas-rmq

Возможные причины и решения:

RabbitMQ не запущен — проверить статус пода:

kubectl get pods -n cpaas | grep rmq

Неверные учётные данные — проверить параметры rmq.username, rmq.password, rmq.vhost в cpaas-app-values.yaml;

Топология не применена — убедиться, что rmq-topology.yaml был применён:

kubectl get -n cpaas rabbitmqvhost,rabbitmquser,rabbitmqpermission

12.4Ошибки сервиса STT/ASR

Симптом: метрика cpaas_stt_errors_total растёт; в журналах ошибки подключения к ASR-серверу.

Диагностика:

kubectl -n cpaas logs -l app=cpaas-app --tail=200 | grep -i stt

Возможные причины и решения:

Сервис ASR недоступен — проверить доступность хоста и порта, указанных в Vosk.channel1Host / Vosk.channel1Port;

STT не используется — если функционал распознавания речи не требуется, убедиться, что в конфигурации задано Vosk.sttCheck: 'false'.

12.5Необходимость обращения в техподдержку

При возникновении неисправностей, не описанных в данном руководстве, или при обнаружении внутренних ошибок приложения необходимо инициировать обращение в проектную команду ООО «Интерконнект» в соответствии с согласованными процедурами технической поддержки, предоставив:

версию установленного ПО:

helm list -n cpaas

описание наблюдаемого поведения и условий воспроизведения;

журналы затронутых компонентов:

kubectl -n cpaas logs -l app=cpaas-app --tail=500 > cpaas-app.log
kubectl -n cpaas logs cpaas-rmq-server-0 --tail=200 > rmq.log
kubectl -n cpaas logs cpaas-rdbms-1 -c postgres --tail=200 > pg.log

вывод событий кластера:

kubectl get events -n cpaas --sort-by='.lastTimestamp'
Руководство по эксплуатации ПО "CPaaS"