Использование Athena для запроса журналов Cloudwatch с несколькими учетными записями

Сценарий. У нас есть несколько рабочих нагрузок и сред, развернутых на нескольких аккаунтах в AWS Organization. Cloudwatch Logs используется для хранения журналов различных служб в рамках одной учетной записи AWS. EC2 ведут системные журналы, функции Lambda ведут журналы выполнения и так далее.

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

В этой статье демонстрируется, как реализовать централизованное хранение журналов в организации с несколькими учетными записями в AWS Organizations. Основной целью является создание облачной инфраструктуры для:

  • Хранить журналы приложений из нескольких учетных записей AWS в одном ведре S3.
  • Выполнять специальные запросы к данным в S3 с помощью Amazon Athena.

Давайте начнем!

Обзор

Предлагаемое решение использует Cloudwatch Logs для сбора журналов с исходных учетных записей. Amazon Kinesis используется для доставки журналов в централизованное хранилище и S3 для долгосрочного хранения данных журналов. Наконец, мы будем использовать Amazon Athena для выполнения SQL-запросов к этим журналам.

Развертывание

Шаблоны Cloudformation для решения по ведению журналов можно найти здесь: https://github.com/markymarkus/cloudformation/tree/master/centralised-cloudwatch-logs.

logging-account-template.yml обеспечивает инфраструктуру для Log Storage Account. Параметр шаблона OrganizationId используется в политике доступа Cloudwatch Logs Destination для разрешения доставки журналов из учетных записей членов AWS Organizations.

member-account-template.yml демонстрирует, как создать фильтр подписки на журналы Cloudwatch. Вы можете создать его на той же учетной записи, на которой развернут logging-account-template.yml.

Учетные записи источников журналов

Учетные записи-источники содержат рабочие нагрузки, производящие и принимающие журналы в Cloudwatch Logs. Каждая группа журналов хранит события журналов из определенного источника. В нашем примере:

Наличие последовательных соглашений об именовании групп журналов пригодится нам при выполнении запросов Athena к данным. Запросы типа ‘/var/log/messages каждого экземпляра EC2 в каждой учетной записи AWS организации’ зависят от согласованного именования.

Журналы отправляются из учетной записи-члена в централизованное место назначения в Log Storage Account через фильтр подписки.

Учетная запись хранения журналов

Log Storage Account получает и подготавливает данные журналов для Athena и сохраняет журналы в ведро S3. Журналы хранятся в формате JSON по одной записи в строке. Поддерживается Athena и легко экспортируется другими сервисами и инструментами.

Преобразование событий журнала

По умолчанию Firehose записывает записи JSON в потоке в ведро S3 без разделителей и новых строк. Это работало бы, если бы мы не использовали Athena для выполнения запросов. Athena требует, чтобы каждая запись JSON была представлена в отдельной строке.
Для разделения записей JSON мы используем лямбда преобразование Firehose. Функция Lambda считывает пакет записей и добавляет символ новой строки + "n" после каждой записи. Обработанные записи записываются обратно в поток Firehose, который в конечном итоге доставляет журналы в ведро S3.

output = []
for record in event['records']:
    payload = base64.b64decode(record['data'])
    striodata = BytesIO(payload)
    with gzip.GzipFile(fileobj=striodata, mode='r') as f:
        payload = f.read().decode("utf-8")

    # Add newline to each record
    output_record = {
        'recordId': record['recordId'],
        'result': 'Ok',
        'data': base64.b64encode((payload + "n").encode("utf-8"))
    }
    output.append(output_record)
Вход в полноэкранный режим Выход из полноэкранного режима

Выполнение запросов Athena

На данный момент у нас есть журналы приложений в ведре S3 в учетной записи Log Storage. Kinesis — это поток, основанный на времени, поэтому каждый файл содержит журналы из нескольких учетных записей и групп журналов Source AWS:

Чтобы запустить запросы Athena, сначала создайте внешнюю таблицу, указывающую на данные:

CREATE EXTERNAL TABLE logs (
    messageType string,
    owner string,
    logGroup string,
    subscriptionFilters string,
    logEvents array<struct<id:string,
              timestamp:string,
              message:string
              >>
  )           
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://BUCKET_NAME/logs/year=2022/month=05/day=05/' 
Войдите в полноэкранный режим Выход из полноэкранного режима

logEvents хранятся в структуре массива. Чтобы запросить поля журналов Cloudwatch внутри массива, необходимо UNNEST logEvents. Вот несколько запросов для начала работы:

Первый запрос возвращает последние потоковые журналы из учетных записей источников:

SELECT owner,loggroup,n.message FROM logs
CROSS JOIN UNNEST(logs.logevents) AS t (n)
LIMIT 20
######
1   111111111111    /var/log/messages   May 5 03:07:48 ip-10-0-24-56 dhclient[2085]: XMT: Solicit on eth0, interval 119340ms.
2   222222222222    /aws/lambda/hello-world-lambda  START RequestId: fcc9e873-d4c1-4ca3-a7de-fd5490300740 Version: $LATEST
3   222222222222    /aws/lambda/hello-world-lambda  [DEBUG] 2022-05-05T03:07:50.972Z fcc9e873-d4c1-4ca3-a7de-fd5490300740 {'version': '0', 'id': ....
4   222222222222    /aws/lambda/hello-world-lambda  [DEBUG] 2022-05-05T03:07:50.973Z fcc9e873-d4c1-4ca3-a7de-fd5490300740 Hello World!
5   111111111111    /aws/lambda/lambda-writer-LambdaFunction    START RequestId: 38fb9b6b-dbea-4875-91cc-cf1dd5b36ab9 Version: $LATEST
6   111111111111    /aws/lambda/lambda-writer-LambdaFunction    [DEBUG] 2022-05-05T03:08:16.81Z 38fb9b6b-dbea-4875-91cc-cf1dd5b36ab9
7   111111111111    /var/log/messages   May 5 11:40:01 ip-10-0-24-56 systemd: Created slice User Slice of root.
8   111111111111    /var/log/messages   May 5 11:40:01 ip-10-0-24-56 systemd: Started Session 169 of user root. 

Войти в полноэкранный режим Выход из полноэкранного режима

Следующий SQL-запрос возвращает количество событий журнала для каждого источника регистрации (группы журналов):


SELECT owner,loggroup,count(*) FROM logs
CROSS JOIN UNNEST(logs.logevents) AS t (n)
GROUP BY owner,loggroup
###
1   111111111111    /var/log/secure 429
2   111111111111    /var/log/messages   1670
3   222222222222    /aws/lambda/hello-world-lambda  5764
4   111111111111    /aws/lambda/lambda-writer-LambdaFunction    7198
...
Войти в полноэкранный режим Выйти из полноэкранного режима

Заключение

Если вы находитесь в процессе построения и планирования стратегии ведения журналов, это решение может стать хорошей отправной точкой. Вы можете собирать журналы Cloudwatch из нескольких учетных записей и регионов в одно ведро S3. Запросы Athena могут быть выполнены на основе консолидированных данных журналов. Я рекомендую вам поэкспериментировать с SQL-запросами к данным журналов. Анализ моделей ведения журналов по конкретным источникам и количества событий может помочь вам улучшить общий процесс управления журналами.

Спасибо за прочтение.

Оцените статью
Procodings.ru
Добавить комментарий