惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News and Events Feed by Topic
N
News | PayPal Newsroom
SecWiki News
SecWiki News
P
Privacy International News Feed
T
Troy Hunt's Blog
Attack and Defense Labs
Attack and Defense Labs
N
News and Events Feed by Topic
L
LINUX DO - 热门话题
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Security Latest
Security Latest
AWS News Blog
AWS News Blog
S
Secure Thoughts
W
WeLiveSecurity
H
Heimdal Security Blog
T
Threat Research - Cisco Blogs
I
Intezer
Application and Cybersecurity Blog
Application and Cybersecurity Blog
S
Security @ Cisco Blogs
G
GRAHAM CLULEY
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Spread Privacy
Spread Privacy
L
Lohrmann on Cybersecurity
C
CERT Recently Published Vulnerability Notes
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
Google Online Security Blog
Google Online Security Blog
Cisco Talos Blog
Cisco Talos Blog
雷峰网
雷峰网
Cloudbric
Cloudbric
Y
Y Combinator Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园_首页
Hacker News: Ask HN
Hacker News: Ask HN
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google DeepMind News
Google DeepMind News
Vercel News
Vercel News
云风的 BLOG
云风的 BLOG
Latest news
Latest news
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
D
Docker
Recent Announcements
Recent Announcements
博客园 - 【当耐特】
H
Help Net Security
博客园 - 司徒正美
TaoSecurity Blog
TaoSecurity Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
Check Point Blog
博客园 - 叶小钗

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Сервис аудитных логов в облаке: архитектура и ценность для пользователей
Владимир Атасунц · 2026-05-07 · via Все публикации подряд на Хабре

Сервис аудитных логов в облаке: архитектура и ценность для пользователей

Простой

14 мин

10K

На первый взгляд задача кажется простой: нужно зафиксировать событие и предоставить интерфейс для его просмотра. Но на практике за этим стоит множество интересных инженерных решений: как отбирать события, хранить их, масштабировать систему, не потерять данные в случае аварии. И как сделать сервис полезным и для ИБ-специалистов, и для простых пользователей.

Привет! Я Владимир Атасунц, руководитель направления Security Services в MWS Cloud Platform. В этой статье расскажу о сервисе аудитных логов — базовом инструменте облака для контроля действий с ресурсами и анализа изменений в инфраструктуре.

Разберу:

  • зачем конкретно нужен такой сервис и какие сценарии использования предусматривает;

  • как он выглядит с точки зрения продуктовой модели;

  • какие требования легли в основу системного дизайна;

  • как жизненный цикл события нашел отражение в архитектуре и из каких компонентов она в итоге состоит.

Пойдём последовательно — от бизнес-сценариев к технической реализации.

Что такое сервис аудитных логов

Начнём с простого примера. Представьте, что вы — администратор облачного пространства. Утром вы создали виртуальную машину. Вечером возвращаетесь — а с ней что-то произошло: кто-то добавил ядра, кто-то её выключил. В команде есть коллеги, доступов много, действий — ещё больше.

Возникают базовые вопросы: что именно произошло и кто это сделал? Ответ на это и дают аудитные логи.

Аудитные логи — это запись о том:

  • какое действие было выполнено;

  • кто выполнил действие;

  • когда это произошло;

  • и чем всё закончилось (успехом или ошибкой).

Эта информация позволяет восстановить цепочку событий и понять, что происходило в инфраструктуре.

Теперь поговорим про основных потребителей сервиса — по нашему мнению, это специалисты по информационной безопасности: ИБ-инженеры, аналитики, архитекторы, SOC-команды. Для них это рабочий инструмент для выполнения регуляторных требований, мониторинга событий безопасности, разбора инцидентов постфактум. 

При этом аудитные логи важны не только для ИБ. Ими пользуются и инженеры, которым нужно быстро понять причину изменений в инфраструктуре — например, кто и каким действием остановил кластер или изменил конфигурацию ресурса.

Для нас как для облака, помимо внешних пользователей есть еще и внутренние потребители — команда, которая это облако развивает. Нам важно понимать, что происходит внутри инфраструктуры: для аналитики, выполнения внутренних требований, расследования инцидентов и оперативной диагностики. По сути, мы используем тот же инструмент для тех же задач, что и наши пользователи: чтобы видеть изменения, отслеживать подозрительные действия и быстрее разбираться в проблемах.

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

Сегодня сервис аудитных логов — это must-have для любого облака. Такие решения есть у западных, азиатских и российских провайдеров. Мы не стали изобретать велосипед: посмотрели на существующие подходы, выбрали наиболее зрелую модель и адаптировали её под российские реалии, нашу архитектуру и продуктовые сценарии. 

В самом простом виде задача сервиса выглядит так: в облаке есть множество источников событий и их нужно куда-то собирать и где-то хранить. Внутри мы называем это common storage — общее хранилище, куда стекаются события со всего облака. Нюансы начинаются дальше — когда нужно дать пользователям управляемый доступ к этим событиям. Для этого мы ввели две отдельные сущности — коллектор и хранилище.   

Коллектор (Collector). Нужен, чтобы пользователь мог управлять тем, какие события собирать. Позволяет выбрать из всего объёма доступных событий только те, которые действительно интересны пользователю. В Google Cloud аналогичный ресурс называется Sink.

Пример сценария — события создания виртуальных машин пользователю не важны, а вот удаление ВМ или Kubernetes-кластера — критично.

Хранилище (Storage). Ресурс, в который попадают события после фильтрации. Именно он отвечает за то, где данные будут храниться или куда будут выгружаться дальше.

Мы сознательно выделили хранилище в отдельную сущность и не стали объединять его с коллектором. Коллектор отвечает за отбор событий, а хранилище за их дальнейшее хранение или отгрузку. Такое разделение даёт гибкость: можно независимо развивать логику маршрутизации событий и способы их хранения. Через конфигурацию коллектора пользователь может сначала выбрать хранение данных в хранилище аудитных логов, а при желании через некоторое время переключить хранение на внешнюю систему.

В Google Cloud аналог называется log bucket, но нам не понравилось пересечение с сущностью S3 bucket сервиса Object Storage — S3-совместимое хранилище облака MWS Cloud Platform, поэтому мы упростили нейминг.

Требования к системному дизайну сервиса аудитных логов

Приступив к проработке системного дизайна, мы опирались на технические требования, бизнес-сценарии, продуктовую модель. В архитектуре облака мы разделяем Control Plane и Data Plane.

  • Control Plane отвечает за хранение конфигурации объектов, реализацию API и ресурсной модели.

  • Data Plane отвечает за выполнение действий. Например, Control Plane сохраняет конфигурацию виртуальной машины и передаёт её в Data Plane, который уже создаёт ВМ.

Аудитные события могут генерироваться на обоих уровнях. Ниже рассмотрим требования к дизайну сервиса — от технических до потребности в централизованном хранилище. 

Технические требования

Чтобы понимать, что происходит в инфраструктуре, события нужно надёжно генерировать, доставлять и хранить. У нас были следующие требования:

Высокая производительность на запись. Поток событий большой и постоянно растёт. На старте мы заложили целевой показатель в 100k RPS. Для молодого облака это серьёзная цифра, но архитектуру хотелось строить с запасом.

Адекватная производительность на чтение. Пользователь не должен ждать по пять минут, пока загрузятся события. Особенно в сценарии расследования инцидентов , где приходится постоянно фильтровать и уточнять выборку. Мы не фиксировали жёсткий SLA, но ориентировались на единицы секунд в типовом запросе — в идеале около пяти. В сложных случаях с большой глубиной хранения запросы могут занимать десятки секунд, но это нетипичный сценарий.

Масштаб и низкая стоимость хранения. Источников событий много: сервисов много, пользовательских ресурсов ещё больше, пользователей — ещё больше. Все что-то делают. При этом хранить эти данные нужно долго, например для целей compliance. Значит, решение должно обеспечивать низкую стоимость хранения.

Высокая надёжность. С учетом вышеописанных требований сервис должен обеспечить непрерывный поток записи событий, быть готовым к инфраструктурным проблемам и неожиданному росту нагрузки, легко масштабироваться.

Ресурсная модель

Следующий шаг — спроектировать ресурсную модель сервиса и понять, как объекты будут взаимодействовать между собой.

Событие, главный объект. Их может быть очень много. В событии хранится вся необходимая информация: кто, что, когда и над каким ресурсом сделал.

Хранилище. Я уже о нём писал, но здесь важно зафиксировать характеристики. Storage может иметь ограничение по объёму — а может не иметь. Это зависит от потребностей клиента. Также можно ограничить срок хранения. Например: максимум 10 ГБ в течение 10 дней.

Коллектор — определяет, какие события нужно собрать и в какое хранилище их отправить.

С ресурсной моделью самого сервиса разобрались — теперь надо понять, как она ложится на модель облака.

Первый контейнер ресурсов, с которым сталкивается пользователь, — это организация. Важно понимать, что события могут происходить и на этом уровне. Например, добавление пользователя — это тоже событие, которое мы хотим фиксировать.

Ниже находится проект — основной рабочий контейнер для пользователей. Именно внутри проекта разворачиваются виртуальные машины, Kubernetes-кластеры, а также создаются наши хранилища и коллекторы.

Есть и сценарий выгрузки во внешнее хранилище. Например, в Object Storage нашего облака. Это достаточно простой вариант, и мы его поддерживаем.

Ресурсная модель. Базовый сценарий

Ресурсная модель. Базовый сценарий

Потребность в централизованном хранилище

Теперь рассмотрим более сложный вариант. Представим крупного клиента с десятком проектов. Создавать в каждом проекте отдельное хранилище и разбираться в них неудобно. Гораздо логичнее иметь единое централизованное хранилище, куда будут стекаться события со всех проектов и, при необходимости, с уровня организации.

Например, можно создать отдельный проект безопасности — условный Project Sec — и разместить в нём общее хранилище. Туда будут отправляться события из других проектов. Доступ к этому проекту можно выдать только команде безопасности, которая занимается мониторингом и аналитикой. С точки зрения ресурсной модели это всё то же хранилище , просто в него попадает больше событий.

При этом возникает вопрос кросс-проектного доступа. Не любой коллектор может читать события в соседнем проекте или писать в чужое хранилище. Поэтому у коллектора появляется дополнительная характеристика — сервисный аккаунт, от имени которого выполняются операции чтения и записи. Это позволяет корректно разграничить доступ. Логика аналогична Object Storage: писать может только тот, у кого есть права.

Ресурсная модель. Кросс-проектный сценарий

Ресурсная модель. Кросс-проектный сценарий

Отображение жизненного цикла события в архитектуре сервиса аудитных логов

Прорабатывая архитектуру, мы разделили жизненный цикл события на четыре этапа:

  1. Генерация.

  2. Сбор и доставка.

  3. Хранение.

  4. Доступ.

Генерация событий

С генерации всё начинается. Кто-то должен сообщить сервису, что произошло событие. Причём делать это нужно в едином формате и с полным набором данных — это не два-три поля, а довольно большой объём информации.

Поскольку инфраструктура не монолитная и состоит из множества сервисов, каждый из них должен уметь генерировать и передавать события.

На этапе системного дизайна мы решили реализовать собственную библиотеку — по сути SDK, которую подключают сервисы облака. Можно было, например, пойти по классическому пути с REST API и отправкой событий напрямую. Но на решение повлияли особенности нашей инфраструктуры.

Мы работаем в Kubernetes, сервисы развёрнуты в нескольких кластерах. Возможны аварии, сетевые проблемы, перезапуски нод. Нам нужно минимизировать влияние таких ситуаций на качество сервиса. 

Синхронная отправка событий — плохой вариант. Если в момент создания пользователем виртуальной машины возникнет проблема с сетью на уровне инфраструктуры облака и сервис начнёт с периодичностью повторять запись аудита, пользователю придется ждать. Фоновая отправка без буферизации — тоже риск. При перезапуске ноды событие может потеряться.

В итоге мы выбрали подход с локальной записью событий на диск. Сервис через библиотеку записывает событие в файл, а отдельный компонент считывает эти файлы и отправляет данные дальше. Так мы отделяем пользовательскую операцию от сетевой доставки. Библиотека инкапсулирует всю эту логику — сервисам не нужно реализовывать её самостоятельно.

Сбор и доставка событий

После генерации событий возникает следующая задача — собрать данные из разных кластеров и доставить их в единое хранилище.

У нас не один кластер и не один сервис. Сервисы распределены, кластеры изолированы друг от друга, а события генерируются повсюду. Важно аккуратно собрать весь этот поток в одной точке и при этом не перегрузить систему.

Мы рассматривали разные варианты организации очереди. В том числе думали о собственной реализации, смотрели и на классические решения, и на нетипичные, но в итоге остановились на Kafka. Она позволила нам:

  • аккумулировать поток событий со всех кластеров;

  • выстроить контролируемую модель потребления;

  • обеспечить высокую производительность записи.

Хранение событий

Теперь нужно было решить, где и как хранить данные. Мы помнили про два ключевых требования: низкая стоимость хранения и высокая производительность на запись. Сразу стало понятно, что хранить всё на локальных дисках — дорого. Поэтому уже на этапе системного дизайна мы приняли решение строить хранилище поверх Object Storage нашего облака. Дальше начался выбор инструмента.

Первым кандидатом был ClickHouse — привычный и понятный инструмент с поддержкой S3-совместимых хранилищ и зрелой экосистемой. Он позволяет строить таблицы с использованием Object Storage, однако в классическом self-managed сценарии ClickHouse копирует данные на диск, что не соответствовало нашей цели отказа от дисков.

Мы также рассматривали zero-copy replication, где между репликами синхронизируются в основном метаданные, а не сами данные, но на момент нашего системного дизайна этот режим в документации был помечен как «not production ready». Рисковать мы не стали.

Дальше мы посмотрели в сторону Apache Iceberg. Важно понимать, что Iceberg — это не полноценная база данных, а слой управления табличными данными поверх Object Storage. Он определяет, как хранить файлы, как вести метаданные и как обеспечивать консистентность.

Архитектуру Iceberg можно условно разделить на четыре компонента.

  • Первый — собственно Object Storage, где лежат файлы данных. Мы выбрали формат Parquet — колоночный, удобный и хорошо поддерживаемый.

  • Второй — каталог метаданных. Он хранит информацию о таблицах, версиях и связях между файлами. Мы рассматривали несколько вариантов и в итоге выбрали Nessie — по нашему мнению, на момент проработки архитектуры это был наиболее зрелый и удобный для production-сценариев каталог.

  • Третий — сервисы обслуживания таблиц. Это процессы, которые удаляют устаревшие файлы, объединяют мелкие файлы в более крупные и обновляют метаданные. Это важно как для экономии места, так и для производительности. Для этих задач мы используем Spark — проверенный инструмент, который хорошо подходит для фонового обслуживания таблиц и обработки данных в Iceberg.

  • Четвёртый — движок для выполнения запросов, который работает с данными и метаданными Iceberg-таблиц. Здесь мы рассматривали три варианта: Trino, StarRocks и ClickHouse. Мы выбрали StarRocks, о причинах расскажу дальше. 

Trino — мощный и зрелый query engine с поддержкой Iceberg и инструментами обслуживания таблиц. Но у него есть архитектурная особенность: координатор не масштабируется из коробки. Решения существуют, но они достаточно сложные.

StarRocks — полноценная аналитическая база данных, которая умеет работать поверх Iceberg и хорошо масштабируется. В её архитектуре есть frontend-ноды, которые планируют выполнение запроса, и compute-ноды, которые выполняют его. При нехватке ресурсов архитектура позволяет горизонтально добавлять необходимые ноды.

ClickHouse, несмотря на симпатию к инструменту, на момент проработки архитектуры не предоставлял нужного нам набора операций поверх Iceberg для реализации полного пайплайна. 

В результате мы остановились на StarRocks.

Пользовательский доступ к данным

Финальный этап жизненного цикла события — предоставить пользователю удобный доступ к данным. Для этого у нас есть Control Plane, написанный на Kotlin. Он реализует API, поддерживает ресурсную модель и позволяет выполнять запросы с заданными фильтрами.

Пользователь взаимодействует именно с этим уровнем. Внутри Control Plane обращается к query engine и возвращает результат. Возможно, в будущем добавим собственный язык запросов — по аналогии с тем, как это реализовано в Google. Пока же мы ограничились фильтрами и преднастроенными возможностями поиска.

Архитектура сервиса аудитных логов: реализация на практике

Как я уже писал, архитектура сервиса отражает жизненный цикл события. Ниже расскажу, как она выглядит на практике и из каких компонентов состоит. 

Генерация аудитных событий

Как я уже упоминал выше, у нас есть библиотека, с помощью которой сервисы записывают аудитные события. Backend, живущий в Kubernetes, подключает эту библиотеку, генерирует события и записывает их на диск. Библиотеку мы реализовали под основные языки нашего облака — в первую очередь под Kotlin и Go.

Помимо базовой функциональности «записать событие», мы предусмотрели middleware, которую можно подключить в Control Plane на уровне обработчиков запросов. Middleware автоматически собирает большую часть данных, необходимых для аудита. Сервису остаётся передать только специфическую часть: какой ресурс, какая операция и чем она завершилась.

События записываются в файл в каталоге на диске, подключённом через HostPath. Дальше возникает задача корректно прочитать эти данные и отправить их дальше.

Для корректной обработки файлов, в которые идет активная запись, мы реализовали отдельный сервис, условно названный logrotate (это наш собственный компонент, просто одноимённый с известной утилитой). Этот компонент вместе с библиотекой выводит файлы из режима записи и помечает их как готовые к дальнейшей обработке. После этого файлы можно забирать на сбор. Logrotate развёрнут как DaemonSet во всех кластерах, поэтому обслуживает все сервисы.

Архитектура сервиса аудитных логов. Генерация событий

Архитектура сервиса аудитных логов. Генерация событий

Локальный сбор и архив данных

Следующий компонент — сервис, который читает подготовленные файлы и отправляет их дальше. Этот сервис мы называем коллектором. Он выполняет две задачи:

  1. Отправляет данные дальше в пайплайн.

  2. Сохраняет сжатые данные во временный локальный архив.

Зачем нужен локальный архив? Ответ — надёжность. Теоретически сеть может упасть на час или два. В такой ситуации события не должны теряться. Поэтому локальный архив хранит данные до тех пор, пока они не будут успешно доставлены в целевое хранилище. Очевидная проблема — архив не бесконечный. Поэтому со старта разработки сервиса мы настроили метрики и алертинг и следим за потреблением архива, чтобы не допустить его переполнения.

Коллекторы также запущены как DaemonSet во всех кластерах. В итоге все коллекторы отправляют данные в Kafka для дальнейшей обработки.

Архитектура сервиса аудитных логов. Локальный сбор данных

Архитектура сервиса аудитных логов. Локальный сбор данных

Очередь событий

Kafka в пайплайне сбора событий — это центральная точка агрегации. После этого начинается этап обработки, который делится на две части:

  • внешняя выгрузка;

  • внутренняя запись в наше хранилище.

Мы сознательно разделили эти потоки. Нам не хотелось сначала писать события во внутреннее хранилище, а затем читать их оттуда для внешней отправки. Это создавало бы лишнюю нагрузку и увеличивало задержку. Проще и эффективнее отправлять данные напрямую из Kafka.

Внешняя выгрузка данных

Внешний экспортер читает данные из Kafka. Дальше происходит следующее:

  1. События группируются по проектам и организациям.

  2. Экспортер обращается к Control Plane по внутреннему API.

  3. Получает информацию о коллекторах, работающих с этими проектами и организациями.

  4. Определяет:

    • какие события нужно оставить;

    • куда их выгружать;

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

После этого экспортер выгружает данные в сконфигурированные пользователем внешнее хранилище. Здесь мы подумали про надёжность и предусмотрели плохие сценарии, например:

  • проблемы с сетью;

  • некорректно настроенный сервисный аккаунт;

  • удалённый пользователем бакет.

Поэтому мы сохраняем данные во временном хранилище и реализуем механизм повторной отправки в течение заданного времени.

Архитектура сервиса аудитных логов. Внешняя выгрузка данных

Архитектура сервиса аудитных логов. Внешняя выгрузка данных

Внутреннее хранилище данных

Внутренний экспортер (Iceberg Exporter) также читает данные из Kafka.

Он реализует два сценария:

  1. Запись полного набора событий для внутренних нужд в Common Storage.

  2. Запись в пользовательские хранилища.

В качестве Common Storage мы используем то же хранилище, который предоставляем пользователям. Разница лишь в конфигурации: для внутреннего хранения используется другой коллектор и другие параметры хранения.

Архитектура сервиса аудитных логов. Внутреннее хранилище

Архитектура сервиса аудитных логов. Внутреннее хранилище

Архитектура сервиса аудитных логов. Полная схема

Архитектура сервиса аудитных логов. Полная схема

Ниже расскажу про некоторые особенности нашего внутреннего хранилища данных:

Прослойка для работы с Iceberg. При записи в Iceberg есть важная особенность: в одну таблицу можно выполнить только один commit за раз. Если два процесса попытаются сделать commit параллельно, один из них завершится неудачей, и придётся перечитывать файлы и пересобирать манифесты.

Чтобы избежать этой проблемы, мы добавили прослойку-агрегатор, которую назвали Coordinator. Она накапливает данные в течение заданного интервала (например, двух минут) и выполняет единый commit. Это своего рода координатор записи.

Хранилище внутри Iceberg. Внутри нашего Iceberg-хранилища пользовательское хранилище — это, по сути, отдельная таблица.

Мы рассматривали другие варианты:

  • использование view;

  • комбинированную модель (общая таблица + view для каждого хранилища).

Но оба варианта не подошли. И вот почему: 

  • view дают худшую производительность;

  • комбинированный вариант сложнее в реализации и затрудняет контроль объёма данных.

Таблица оказалась самым простым и предсказуемым решением.

Кроме того, поскольку на этапе экспорта мы уже знаем, к каким коллекторам относятся события и в какие хранилища они должны попасть, запись в таблицы часто может выполняться параллельно — если это разные таблицы. Прослойка агрегации нужна только в случаях, когда несколько коллекторов пишут в одно хранилище.

Ограничения и производительность чтения. Напомню, одно из требований — адекватная производительность на чтение.

Событий может быть много, глубина хранения — большой. Технически обеспечить высокую производительность на больших объёмах сложно. Поэтому здесь вступает продуктовый подход.

У хранилища есть две характеристики:

  • максимальный объём;

  • максимальное время хранения.

В инфраструктуре large enterprise десятки ГБ могут заполниться очень быстро — это неудобно. Поэтому объём решили не ограничивать. А вот срок хранения мы ограничили — 30 дней.

По нашим исследованиям, этого достаточно для реализации основных сценариев: расследований, диагностики, мониторинга.

Если требуется более длительное хранение, пользователь может настроить выгрузку в Object Storage и строить аналитику самостоятельно.

Для внутренних хранилищ мы предоставляем интерфейс просмотра. Для внешних выгрузок (Object Storage и другие будущие направления) интерфейса просмотра не предусмотрено — в том числе из-за требований к производительности.

Что в итоге

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

Сервис продолжит развиваться. Сейчас аудитные логи доступны в Preview — сервис предоставляется бесплатно и предназначен для тестирования и знакомства с его возможностями. 

В ближайших планах — кросс-проектная выгрузка событий, подключение новых сервисов как источников аудитных логов, интеграция с SIEM через отдельный Collector, а также развитие интерфейса и более гибких фильтров в UI. 

Попробуйте сервис и поделитесь с нами обратной связью в сообществе MWS Cloud Platform.