Kairos: развёртывание открытой платформы антифрода
Разбираем Kairos — открытую платформу для принятия решений по рискам и мошенничеству. Развёртывание через Docker Compose, настройка правил и интеграция.
Что такое Kairos и зачем оно инженеру
Что такое Kairos и зачем оно инженеру
Kairos — открытая платформа для принятия решений по рискам и мошенничеству. Если в вашем приложении нужно оценивать действия пользователя в реальном времени — вход, оплату, создание аккаунта или вызов API — вам приходится либо писать собственную систему scoring с нуля, либо подключаться к коммерческому сервису. Kairos занимает промежуточную нишу: вы разворачиваете платформу у себя, управляете правилами через отдельный слой и не отдаёте данные третьим сторонам. Подробнее про концепцию можно прочитать в материале Kairos — открытая платформа для оценки рисков.
Инженеру платформа нужна тогда, когда логика принятия решений начинает разрастаться. Сначала достаточно одного if в коде, потом появляется десяток условий, затем — необходимость менять правила без пересборки приложения. Kairos выносит эту логику за пределы основного кода, чтобы разработчики не лезли в репозиторий каждый раз, когда бизнес просит ужесточить проверку платежей из новых регионов.
Основные компоненты платформы
Pлатформа собирается через Docker Compose и состоит из нескольких сервисов. Я предпочитаю писать конфиги вручную, даже когда есть графический интерфейс — так проще понимать, что именно запущено и почему. Пример файла docker-compose.yml для тестового развёртывания:
yamlversion: "3.8"
services:
kairos-api:
image: kairos/api:latest
ports:
- "8080:8080"
environment:
- DATABASE_URL=postgres://kairos:kairos@db:5432/kairos
- REDIS_URL=redis://cache:6379
depends_on:
- db
- cache
kairos-worker:
image: kairos/worker:latest
environment:
- QUEUE_NAME=default
depends_on:
- kairos-api
db:
image: postgres:15-alpine
volumes:
- kairos-db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=kairos
- POSTGRES_USER=kairos
- POSTGRES_PASSWORD=kairos
cache:
image: redis:7-alpine
volumes:
kairos-db:
После запуска доступны три основных компонента:
- API-сервис — принимает события от приложения и возвращает решение: разрешить, заблокировать или запросить дополнительную проверку.
- Worker — обрабатывает события в фоне, пересчитывает рисковые счета и обновляет модели.
- База данных и кэш — PostgreSQL для хранения правил и историй событий, Redis для быстрого доступа к сессиям и временным данным.
С практической точки зрения, самое важное здесь — разделение на API и worker. Если приложение присылает десять тысяч событий в секунду, API не должен ждать окончания расчёта риска. Он принимает событие, кладёт в очередь и сразу отвечает клиенту. Worker забирает задачу и работает в своём темпе. Такой подход напоминает работу с очередями сообщений, о которых я писал в материале Инструменты инженера: от Docker до Kubernetes.
Отличие от коммерческих аналогов
Коммерческие платформы антифрода обычно продаются как «чёрный ящик»: вы отправляете данные, получаете оценку риска, но не видите, как она сформирована. С Kairos ситуация иная. Код открыт, правила настраиваются в конфигах, а логика принятия решений видна в репозитории.
Во-первых, вы контролируете данные. События не уходят на сторонние серверы, что важно для проектов с жёсткими требованиями к конфиденциальности.
Во-вторых, вы можете адаптировать правила под свою бизнес-логику. Коммерческие решения часто предлагают готовые наборы правил, которые работают для интернет-магазинов, но не для банковской API или игровой платформы. Kairos позволяет описать собственные условия в YAML или через API.
В-третьих, предсказуемость конфигурации. Когда всё описано в коде и развёрнуто через Docker Compose, вы знаете, какая версия сервиса работает, какие переменные окружения заданы и как повторить развёртывание на другой среде.
Пример правила в формате YAML:
yamlname: "Подозрительный вход"
description: "Блокируем вход с нового устройства и необычной геолокации"
conditions:
- field: "device_id"
operator: "not_in"
value: "{{user.trusted_devices}}"
- field: "ip_country"
operator: "not_in"
value: "{{user.countries}}"
actions:
- type: "challenge"
method: "email"
- type: "alert"
channel: "slack"
Это не призыв бросать коммерческие решения. Kairos подходит, когда команда готова сама поддерживать платформу: обновлять образы, следить за базой данных и настраивать бэкапы. Если ресурсов нет, коммерческий аналог может быть дешевле в долгосрочной перспективе.
В следующем разделе разберём развёртывание через Docker Compose и интеграцию с приложением.
Развёртывание Kairos на собственном оборудовании
Требования к серверу и Docker Compose
Kairos состоит из нескольких сервисов: API, обработчик событий, база данных и брокер сообщений. С практической точки зрения, это классический стек, который удобно описывать одним файлом docker-compose.yml.
Во-первых, определитесь с железом. Для тестового инстанса хватит двух ядер, четырёх гигабайт оперативной памяти и двадцати гигабайт на диске. Если планируете обрабатывать поток событий в реальном времени, закладывайте не менее восьми гигабайт памяти и SSD — PostgreSQL с интенсивной записью не любит медленные диски.
Убедитесь, что на сервере установлен Docker и Docker Compose. Проверка занимает минуту:
bashdocker --version docker compose version
Если команда docker compose не найдена, а есть только старый docker-compose, замените в дальнейшем вызовах соответствующим образом.
Ниже пример минимального docker-compose.yml. Я обычно пишу конфиги вручную — GUI для тех, кто не знает, где лежит конфиг.
yamlversion: "3.8"
services:
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: kairos
POSTGRES_USER: kairos
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- kairos_db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U kairos -d kairos"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
volumes:
- kairos_redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
kairos-api:
image: kairos/api:latest
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
DATABASE_URL: postgresql://kairos:${DB_PASSWORD}@postgres:5432/kairos
REDIS_URL: redis://redis:6379/0
API_PORT: 8000
ports:
- "8000:8000"
restart: unless-stopped
kairos-worker:
image: kairos/worker:latest
depends_on:
kairos-api:
condition: service_started
environment:
DATABASE_URL: postgresql://kairos:${DB_PASSWORD}@postgres:5432/kairos
REDIS_URL: redis://redis:6379/0
restart: unless-stopped
volumes:
kairos_db:
kairos_redis:
Перед запуском создайте файл .env в той же директории и укажите надёжный пароль для базы:
bashDB_PASSWORD=сложный_пароль_не менее_16_символов
С паролями не экспериментируйте. Если база будет доступна извне, слабый пароль — это вопрос времени, а не вероятности.
Первый запуск и проверка работоспособности
Сначала поднимите инфраструктуру — базу и Redis:
bashdocker compose up -d postgres redis
Подождите, пока контейнеры перейдут в состояние healthy. Посмотреть статус можно так:
bashdocker compose ps
Если статус healthy, запустите остальные сервисы:
bashdocker compose up -d
Теперь проверьте, что API отвечает. Сначала убедитесь, что порт 8000 не занят другим процессом:
bashss -tlnp | grep 8000
Если порт свободен и контейнер запущен, выполните запрос к эндпоинту проверки работоспособности:
bashcurl -s http://localhost:8000/health | jq .
Ожидаемый ответ — JSON со статусом ok или healthy. Если curl возвращает ошибку соединения, загляните в логи:
bashdocker compose logs --tail=50 kairos-api
Чаще всего проблема кроется в неверных переменных окружения или в том, что база ещё не успела инициализироваться. Система healthcheck в compose-файле выше должна это отловить, но при первом запуске сетевые задержки между контейнерами иногда играют свою роль.
Когда API отвечает, попробуйте отправить тестовое событие на оценку риска. Структура запроса зависит от версии API, поэтому смотрите актуальную спецификацию в репозитории проекта. В общем виде это POST-запрос с телом события и заголовком авторизации, если он настроен.
Если всё работает, следующим шагом будет вынос конфига из .env в отдельный файл секретов и настройка обратного прокси — например, Nginx или Caddy — чтобы не открывать порт 8000 напрямую в интернет. Об этом и о настройке правил антифрода читайте в следующих разделах.
Для повторения основ Docker перед работой с compose-файлами полезно заглянуть в Инструменты инженера: от Docker до Kubernetes, а общая концепция платформы описана в Kairos — открытая платформа для оценки рисков.
Настройка правил принятия решений
Настройка правил принятия решений
Правила принятия решений — это то, где платформа перестаёт быть просто набором контейнеров и становится полезным инструментом. Без них Kairos — пустая оболочка, которая собирает данные, но ничего с ними не делает. Подробнее о самой платформе и её архитектуре можно прочитать в обзорной статье о Kairos.
Я настраивал подобные системы раньше, и главная ошибка — пытаться описать все возможные сценарии сразу. Начинайте с двух-трёх источников данных и одной политики, отработайте её на реальном трафике, а потом масштабируйте.
Подключение источников данных
Источник данных — это точка, откуда Kairos забирает информацию о клиенте, транзакции или устройстве. На практике это чаще всего реляционная база, ключ-значение для кэша, внешнее API или логи веб-сервера.
Настройка правил без понимания источников данных — это как сборка мебели без инструкции: вроде всё есть, но ничего не hält. Во-первых, определите, какие данные нужны для принятия решения. Для антифрода обычно достаточно трёх категорий: профиль пользователя, история транзакций и метаданные устройства (IP, User-Agent, отпечаток браузера).
С практической точки зрения, подключение источника в Kairos выглядит как описание в docker-compose.yml. Ниже пример, где платформа тянет данные из PostgreSQL и Redis, которые уже развёрнуты в том же стеке.
yamlservices:
kairos:
image: kairos/platform:latest
environment:
- DATA_SOURCE__PG__HOST=db
- DATA_SOURCE__PG__PORT=5432
- DATA_SOURCE__PG__USER=kairos
- DATA_SOURCE__PG__PASSWORD=${PG_PASSWORD}
- DATA_SOURCE__PG__DATABASE=fraud_events
- CACHE__REDIS__HOST=cache
- CACHE__REDIS__PORT=6379
volumes:
- ./rules:/etc/kairos/rules
depends_on:
- db
- cache
Сначала убедитесь, что переменная PG_PASSWORD определена в .env, иначе контейнер не стартует. Я предпочитаю хранить пароли отдельно, а не в репозитории — это базовая гигиена, которой часто пренебрегают.
Если источник — внешнее API, добавьте его как отдельный сервис или через переменную окружения с URL. Главное, чтобы ответ приходил в формате, который понимает Kairos, обычно JSON.
Создание политик рисков
Политика — это набор правил, каждое из которых состоит из условия и действия. Условие проверяет данные из источников, действие определяет, что делать с транзакцией: одобрить, отклонить или отправить на ручную проверку.
Если мы посмотрим на типичный сценарий, политика выглядит так: сумма транзакции превышает порог, и страна IP не совпадает со страной выпуска карты. В этом случае риск высокий, и решение принимает оператор, а не алгоритм.
Пример описания политики в YAML:
yamlpolicies:
- name: high_value_foreign_transaction
priority: 10
conditions:
- field: transaction.amount
operator: gt
value: 50000
- field: transaction.country
operator: ne
value: "{{ user.card_country }}"
action: manual_review
reason: "Сумма выше порога и страна транзакции не совпадает со страной выпуска карты"
Здесь priority определяет порядок проверки: чем выше число, тем раньше срабатывает правило. Если несколько правил подходят, применяется то, у которого приоритет выше.
С predictable конфигурацией — это ключевое для меня качество — вы знаете, какое решение будет принято при любых входных данных. Без предсказуемости отладка превращается в гадание на кофейной гуще.
После создания политики проверьте её на тестовых данных. Kairos предоставляет эндпоинт для симуляции решения без влияния на реальный трафик:
bashcurl -X POST http://localhost:8080/v1/simulate \
-H "Content-Type: application/json" \
-d '{"transaction_id": "test-001", "amount": 75000, "country": "US", "user_id": "user-42"}'
Ответ содержит применённую политику и итоговое действие. Если что-то пошло не так, смотрите логи контейнера kairos — обычно проблема в несоответствии имён полей в условии и реальных данных.
Настройка правил — не разовая задача. Мошенники меняют тактику, и политики приходится пересматривать раз в квартал. Ведите журнал изменений к файлам правил, как к любому другому коду, и тогда платформа останется полезным инструментом, а не источником ложных срабатываний.
Мониторинг и логирование событий
Мониторинг и логирование событий
Когда платформа принимает решения о рисках, молчание — это не признак того, что всё в порядке. Это признак того, что вы не видите, что происходит. Kairos, как и любая другая система, генерирует логи: запросы к API, решения движка, ошибки подключения к базам, сетевые таймауты. Без сбора и алертов вы узнаете о проблеме от пользователя, а не из дашборда.
С практической точки зрения, мониторинг делится на две части: то, что произошло (логи), и то, что требует реакции прямо сейчас (алерты). Для Kairos я использую стек, который уже описан в материале про инструменты инженера от Docker до Kubernetes — Loki для логов и Alertmanager для уведомлений. Если вы только начинаете знакомство с платформой, рекомендую сначала прочитать обзор Kairos — открытая платформа для оценки рисков.
Сбор логов в Loki
Loki выбираю потому, что он лёгкий, не требует тяжёлой индексации и хорошо дружит с Docker. Для сбора логов из контейнеров Kairos использую Promtail — агент, который читает логи из /var/lib/docker/containers и отправляет их в Loki.
Фрагмент docker-compose.yml:
yamlservices:
loki:
image: grafana/loki:2.9.0
ports:
- "3100:3100"
volumes:
- ./loki-config.yaml:/etc/loki/local-config.yaml
command: -config.file=/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:2.9.0
volumes:
- ./promtail-config.yaml:/etc/promtail/config.yaml
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/log:/var/log:ro
command: -config.file=/etc/promtail/config.yaml
depends_on:
- loki
Конфиг Promtail для сбора логов Kairos:
yamlscrape_configs:
- job_name: kairos
static_configs:
- targets:
- localhost
labels:
job: kairos
__path__: /var/lib/docker/containers/*/*-json.log
pipeline_stages:
- docker: {}
- regex:
expression: '(?P<level>\w+)\s+(?P<message>.*)'
- labels:
level:
Как проверить, что логи идут:
bashcurl -s 'http://localhost:3100/loki/api/v1/query?query={job="kairos"}' | jq .
Если видите JSON с потоками логов — сбор работает. Если нет — проверьте права на /var/lib/docker/containers и имя контейнера Kairos.
С практической точки зрения, не стоит пытаться индексировать всё подряд. Loki не Elasticsearch, и попытка сделать из него полнотекстовый поиск по всем полям приведёт к раздуванию хранилища. Собирайте логи приложения, ошибки и системные события контейнеров. Достаточно.
Алерты в Alertmanager
Логи показывают, что случилось. Алерты говорят, что нужно сделать прямо сейчас. Для Kairos я настраиваю алерты на основе метрик, которые платформа уже отдаёт, и на основе состояния контейнеров.
Alertmanager — стандарт в экосистеме Prometheus. Он получает сигналы от Prometheus, группирует их, убирает дубли и рассылает уведомления. Ниже пример минимального конфига.
alertmanager.yml:
yamlglobal:
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alerts@your-domain.ru'
route:
group_by: ['alertname']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
receiver: 'team-email'
receivers:
- name: 'team-email'
email_configs:
- to: 'infra-team@your-domain.ru'
Правила алертинга для Prometheus (prometheus.rules.yml):
yamlgroups:
- name: kairos.rules
rules:
- alert: KairosDown
expr: up{job="kairos"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Kairos не отвечает"
description: "Контейнер kairos уже более минуты не отвечает на проверку здоровья."
- alert: KairosHighErrorRate
expr: rate(kairos_requests_total{status=~"5.."}[5m]) > 0.1
for: 2m
labels:
severity: warning
annotations:
summary: "Высокий уровень ошибок в Kairos"
description: "За последние 5 минут более 10 % запросов завершились ошибкой 5xx."
Подключение в docker-compose.yml:
yamlservices:
prometheus:
image: prom/prometheus:2.47.0
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- ./prometheus.rules.yml:/etc/prometheus/rules/kairos.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
ports:
- "9090:9090"
alertmanager:
image: prom/alertmanager:0.25.0
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
ports:
- "9093:9093"
Важный момент: метрики в примере выше — это иллюстрация. В реальности смотрите, какие метрики отдаёт ваш экземпляр Kairos, и пишите правила под них. Не копируйте правила слепо, иначе получите тревогу о том, чего не существует.
Проверка алертов без инцидента:
bashcurl -s 'http://localhost:9093/api/v2/alerts'
Должен вернуться пустой массив или список текущих активных алертов.
Мониторинг Kairos не должен быть сложным. Начните с сбора логов в Loki и пары критических алертов в Alertmanager — достаточно, чтобы видеть падения и ошибки. По мере роста нагрузки добавляйте метрики и дашборды, но не гонитесь за сложностью ради сложности. Предсказуемость конфигурации важнее количества датчиков.
Часто задаваемые вопросы
Нужно ли использовать Docker Compose, или можно развернуть вручную?
Docker Compose — рекомендуемый способ старта, но не обязательный. Все компоненты — обычные контейнеры, их можно поднять через systemd или Kubernetes, если инфраструктура требует. С практической точки зрения Compose проще для теста, а в продакшене я обычно выношу каждый сервис в отдельный манифест, чтобы управлять ресурсами точнее.
Можно ли менять правила антифрода без перезапуска сервиса?
Да, правила хранятся отдельно от кода приложения и подгружаются через API платформы. Изменения вступают в силу сразу после сохранения, перезапуск контейнера не требуется. Это удобно, когда бизнес просит ужесточить проверку платежей из нового региона в середине рабочего дня.
Какая база данных нужна для Kairos и можно ли использовать свою PostgreSQL?
Kairos работает с PostgreSQL и Redis, оба сервиса уже входят в docker-compose.yml. Если у вас есть своя база, достаточно изменить переменные DATABASE_URL и REDIS_URL в конфиге API и воркера. Я не рекомендую совмещать production-базу с тестовой средой Kairos — лучше выделить отдельную схему или инстанс.
Как интегрировать Kairos с собственным приложением?
Платформа предоставляет HTTP API, куда приложение отправляет событие — вход, оплату или создание аккаунта — и получает оценку риска. В ответе приходит решение: разрешить, заблокировать или запросить дополнительную проверку. Интеграция сводится к одному вызову из бэкенда, логику принятия решения выносите в правила Kairos, а не в код приложения.
На какую нагрузку рассчитана платформа?
Зависит от конфигурации железа и сложности правил. На трёх нодах Proxmox с 8 ядрами и 32 ГБ оперативной памяти я держу несколько тысяч событий в минуту без задержек. Если правил становится больше пятидесяти, стоит добавить отдельный инстанс воркера и мониторить очередь через Prometheus.