Wiki

Clone wiki

comp-house.repo / TheJournal

Журнал

  • Автор: Lennart Poettering

Оглавление

От переводчика

Можно по разному относиться к Леннарту Поттерингу. Но невозможно отрицать то, что он оказывает огромное влияние на развитие ОС Linux и уже поэтому достоин нашего внимания.

На мой взгляд, Леннарт является шуткой всевышнего, реинкарнацией РМС. Не верите?

Вот факты:

РМС: вместо того, чтобы заставить производителя принтера исправить ошибку в драйвере, не задумываясь, принялся писать текстовой редактор, затем компилятор языка С и в итоге не удержался даже в рамках одной ОС. Теперь он везде, а его последователи проникли даже в космос.

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

Итак, сходство очевидно? Нет. Объединяет их вовсе не глобальность запросов (людей, которые хотят сразу всего и много на земле хватает), но что действительно отличает Леннарта и РМС от прочих - это невероятное воплощение их идей и явное несоответствие между масштабом их личности и последствиями их дел. Возьмите РМС - это же просто один американец, без армии танков, чиновников или коммерсантов. Просто попал в ситуацию с ошибкой в драйвере. Кто из нас не бывал в такой ситуации? Но необходим РМС, чтобы раздуть из этой мелочи столь масштабные последствия для всего мира.

Поттеринг со своей стороны тоже продемонстрировал недюжинный талант формирователя альтернативной реальности. В его активе как минимум два "эпик вина" - pulseaudio и systemd и все идет к тому, что syslog тоже не выдержит его напора. Заметьте, что подобно РМС, Леннарт ни ранее, ни теперь не держал руку на ядерной кнопке. Сидя в своем Берлине он так сумел предложить всему миру свой звуковой велосипед, что мир почему-то не только не смог отказаться, но с песнями в заглохших колонках внедрил явно сырое поделие во все современные дистры. Будучи сотрудником одного вендора - red hat, Поттеринг каким-то невероятным образом так представил свой systemd, что он теперь вошел и в другие дистрибутивы, например в opensuse. И при этом, заметьте, на страничке википедии об этом человеке написано ровно две с половиной строчки! Разве это не мистика?

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

Условия использования перевода

Вы можете безо всяких ограничений на свое усмотрение читать и ссылаться на этот текст.

Перевод завершен. Поэтому теперь вы МОЖЕТЕ копировать этот текст целиком или по частям. При цитировании ссылка на этот перевод или оригинал статьи крайне желательна, да вы и сами все знаете...

Предисловие

Последние несколько недель мы работали над новой возможностью systemd и теперь рады ввести вас в курс дела.

Введение: syslog

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

Назначение демона syslog, как следует из названия, вести системный журнал (SYStem LOGging). Он принимает сообщения в относительно свободной форме от приложений и сервисов и затем сохраняет их на диск. Обычно, вся сопутствующая информация, которая присоединяется к этим сообщениям, ограничивается значениями facility, приоритета, меткой времени, а также тегом и идентификатором процесса. Все эти свойства передаются от клиента, не проверяются и обычно сохраняются как есть. Большинство этих полей не обязательны и их точный ситнтаксис сильно меняется в зависимости от конкретной реализации. Какой-то интернет-RFC в конце концов попытался формализовать и немного улучшить формат сообщений, однако большинство основных реализаций (таких, как вызов glibc’s syslog()) практически не используют эти улучшения.

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

Syslog примерно за 30 лет своего развития стал простым, повсеместным и неоценимым инструментом администратора. Тем не менее он обременен рядом существенных ограничений и с течением времени эти ограничения породили серьезные проблемы:

  • Данные сообщений в основном НЕ аутентифицируются, любой локальный процесс может заявить, что он Apache с PID 4711, и syslog поверит ему на слово и сохранит эту информацию на диск.
  • Данные журналируются в очень свободной форме. Автоматизированные анализаторы журнала должны разбирать строки на человеческом языке, чтобы a) определить тип сообщения и b) вычленить параметры из него. В результате мы получаем ужас регэкспов и необходимость постоянно следить за разработчиками апстрима, которые могут подправить строки журнала на человеческом языке в новых версиях своих программ. В дальнейшем, для того чтобы не менять созданные пользователями регулярные выражения, все сообщения журналов стали частью бинарного интерфейса (ABI), что изначально не предполагалось разработчиками.
  • Штампы времени в сновном не содержат информации о часовом поясе, тем не менее в некоторых новых спецификациях определена их поддержка.
  • Syslog это только одна из многих систем журналирования в локальных машинах. Отдельные логи содержатся для utmp/wtmp, lastlog, audit, kernel logs, firmware logs, а также есть большое количество специфичных для приложений журналов со своими форматами, что не только излишне сложно, но и скрывает связи между записями журналов в разных подсистемах.
  • Чтение файлов журнала просто, но крайне неэффективно. Множество ключевых операций журнала имеют сложность O(n). Индексирование в основном недоступно.
  • Сетевой протокол syslog-а очень прост, но также очень ограничен, поскольку в основном поддерживает только push-модель передачи и не использует хранение-и-передачу, а такие проблемы, как Thundering herd или потеря пакетов мешают нормально его использовать.
  • Файлы журнала легко подвержены манипуляциям атакующих, позволяют легко скрыть от администратора информацию об атаках.
  • Управление доступом отсутствует. Если только администратор вручную его не запрограммировал, пользователь имеет полный доступ к файлам журнала, или не имеет доступа вовсе.
  • Метаданные, хранимые в записях журнала ограничены и не содержат ключевые части информации, такие как имя сервиса, аудит сессии или непрерывные штампы времени.
  • Автоматическое ротация файлов журнала доступна, но далеко от идеала в большинстве реализаций: вместо того, чтобы непрерывно следить за использованием диска, чтобы пресечь выход за установленые пределы, делаются попытки ротации через фиксированные промежутки времени, что открывает двери для многих DoS атак.
  • Ограничение скорости хотя и доступно в некоторых реализациях, тем не менее, в основном не позволяет привязать использование диска или сервис к аккаунту, что было бы крайне желательно.
  • Сжатие структуры журнала на диске в основном доступно, но в большинстве случаев как побочный эффект от ротации и имеет отрицательное действие на и без того запутанное поведение многих важнейших операций с журналом.
  • Традиционный Syslog не пригоден для поддержки журналирования ранней стадии загрузки или поздней стадии выключения, несмотря на то, что последние улучшения (к примеру в systemd) позволяют ему работать.
  • Двоичные данные не могут попасть в журнал, хотя в некоторых случаях это необходимо (Примеры: ATA SMART блоки или важные данные SCSI, дампы прошивок)

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

Журналирование является критически важной частью управления сервисами. В Unix, большинство выполняемых сервисов подключается к syslog, чтобы писать сообщения в журнал. В systemd, мы внедрили журналирование в самое ядро управления сервисами: начиная с Fedora 16 все сервисы стартуют с автоматически поключеными к syslog стандартными потоками stdout и stderr.

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

По мере разработки systemd ограничения syslog становились для нас все более явными. К примеру: для облегчения работы администратора мы хотели в качестве одной и важнейших возможностей добавить отображение последних 10 (или около того) строчек журнала сервиса к следующей основной информации, которая показывается командой “systemctl status foo.service”. Корректная реализация этой функции для классического сислога получается неэффективной, ненадежной и небезопасной: потребуется линейный поиск по всем файлам журналов (который может подразумевать разархивирование на лету), хранимые данные журнала могут потребовать обработки и не факт, что эта обработка будет простой (и без гонок), чтобы сопоставить их с именем сервиса и средой исполнения.

Короче говоря, традиционый сислог после долгой истории длиной в 30 лет достиг состояния очень мощного инструмента, страдающего от множества серьезных ограничений.

Так что же мы можем сделать теперь для улучшения ситуации?

Журнал

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

Конечно, когда проектируешь такой новый базовый копонент, как сислог, некоторые цели проектирования должны быть очевидны:

  • Простота: минимум кода с небольшим количеством зависимостей и минимальными потерями на абстракциях.
  • Без обслуживания: журналирование является слишком важной функцией для отладки и мониторинга систем и не должна сама быть источником проблем, но должна работать, как есть, даже в самых тяжелых случаях. К примеру, это означает, что система должна элегантно обходить такие проблемы, как ограниченое дисковое пространство или когда /var не доступен, избегать возникновения проблем с дисковым пространством по своей вине (например путем реализации ротации файла журнала в демоне в тот момент когда файл журнала растет).
  • Жизнестойкость: файлы данных, которые генерирует журнал должны быть напрямую доступны администратору и могут полноценно использованы после копирования на другие хосты утилитами типа "scp" или "rsync". Неполные копии должны быть гибко обработаны. Просмотр файла журнала клиентом должен работать без работающего рядом демона журнала.
  • Переносимость: файлы журнала должны быть используемы на всем спектре линукс-систем, вне зависимости от того, какой процессор или порядок байт в них используется. Файлы журнала, созданные во встраиваемых ARM-системах должны быть просматриваемы на любом x86 десктопе, как если бы они были созданы локально.
  • Производительность: Очень важно, чтобы операции журнала по добавлению и навигации были быстрыми, в терминах сложности - O(log n) или лучше. Это нужно для того, чтобы предоставить возможность мониторинга с хорошей производительностью в пределах организации.
  • Интеграция: журнал должен быть тесно интегрирован с остальными компонентами системы. Поскольку журналирование является основой службы, оно должено быть опционально отключаемым в тех случаях, когда его надо обойти. Журналирование отвечает за отзывчивость менеджера служб и поэтому журнал должен быть интегрирован с ним чтобы соответствовать данному требованию.
  • Минимум следов: файлы данных журнала должны занимать минимум места на диске, особенно в свете того, что объем генерируемых данных теперь значительно больше, чем в классическом сислоге.
  • Хранилище событий общего назначения: журнал должен быть применим для хранения журнальной записи любого рода без оглядки на его формат, метаданные или размер.
  • Унификация: ряд различных технологий журналирования должны быть приведены к общему знаменателю так, чтобы все журналируемые события оканчивались в едином хранилище. Таким образом сохраняется и в дальнейшем остается доступен глобальный контекст журнала, к примеру, запись прошивки часто следует за записью ядра и оканчивается записью из пространства пользователя. Эта ключевая связь между элементами данной тройки не должна теряться при сохранении на диск.
  • Основа для высокоуровневых инструментов: журнал должен предоставлять универсальное полнофункциональное API, которое может быть использовано средствами мониторинга состояния, инструментами восстановления, генераторами отчетов об ошибках и других высокоуровневых инструментов для доступа к данным журнала.
  • Масштабируемость: как Linux масштабируется от встраиваемых устройств до суперкомпьютеров и кластеров, так и журнал должен масштабироваться вместе с ним. Журналирование критически важно, когда разрабатывают встраиваемые устройства, и существенно на другом краю спектра, для обслуживания кластеров. Журнал необходимо сфокусировать на обобщении обычных, основных вариантов (шаблонов) использования, как общепит для различной специфики, при этом он должен оставаться минимальным в оставлении следов (minimal in footprint).
  • Универсальность: как базовый кирпичик операционной системы, журнал должен быть достаточно универсальным и расширяемым, чтобы удовлетворять специфичным для приложений нуждам. Формат должен быть расширяемым и доступны соответствующие API.
  • Кластеризация и сеть: сегодня компьютеры редко работают изолированно. Это критически важно, чтобы журналирование удовлетворяло данному условию, а файлы и утилиты журнала должны с самого начала разработки поддерживать большие многохостовые инсталляции.
  • Безопасность: файлы журнала должны быть аутентифицированы, чтобы исключить незаметные (необнаружимые) манипуляции с ними.

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

По аналогии (навеяные) с udev событиями, записи журнала схожи с блоками окружения (environment blocks). Ряд ключ/значение полей, разделеных переводом строки, с именами переменных в верхнем регистре. По сравнению с событиями устройств udev и настоящими блоками окружения они имеют одно большое отличие: хотя основное внимание сфокусировано на форматированных ASCII строках, в качестве значений также поддерживаются и двоичные блоки (binary blobs) -- которые могут использоваться для присоединения двоичных данных, типа ATA SMART данных о здоровье, важных данных SCSI, дампов (coredumps) или дампов прошивок (firmware dumps). Код, который генерирует запись, может присоединять столько полей к записи журнала, сколько сочтет нужным и эти поля могут быть общеизвестны или специфичны для службы/подсистемы/драйвера.

Приложения и службы могут генерировать записи в журнале, передавая поля записи службе journald, которая принадлежит systemd. Эта служба дополнит запись рядом мета-полей. Значения этих доверенных полей будут определены службой журнала самостоятельно и не могут быть подделаны со стороны клиента. В случае с аппаратным обеспечением и устройствами ядра, служба журнала будет дополнять запись журнала доступной на данный момент информацией из базы udev, которая содержит все известные имена устройств, симлинки и прочую связанную с устройством информацию.

Поля, которые добавляет демон журнала, начинаются с символа подчеркивания (“_”) который указывает на то, что это поле доверенное и не предложено потенциально мошенническим клиентом. Приложения не могут самостоятельно передать поля, начинающиеся с символа подчеркивания.

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

_SERVICE=systemd-logind.service
MESSAGE=User harald logged in
MESSAGE_ID=422bc3d271414bc8bc9570f222f24a9
_EXE=/lib/systemd/systemd-logind
_COMM=systemd-logind
_CMDLINE=/lib/systemd/systemd-logind
_PID=4711
_UID=0
_GID=0
_SYSTEMD_CGROUP=/system/systemd-logind.service
_CGROUPS=cpu:/system/systemd-logind.service
PRIORITY=6
_BOOT_ID=422bc3d271414bc8bc95870f222f24a9
_MACHINE_ID=c686f3b205dd48e0b43ceb6eda479721
_HOSTNAME=waldi
LOGIN_USER=500

Этот пример записи создан демоном systemd logind в тот момент, когда в систему вошел пользователь “harald”. Как видно, автоматически добавленая информация вполне исчерпывающа и включает ряд важных параметров процесса исполнения.

Полное объяснение определенных полей см. здесь

Родной формат файла журнала навеян классическим лог-файлом git репозитария. Он спроектирован в том ключе, что данные лога только добавляются в конец (чтобы быть уверенным в его целостности и атомарности при доступе, основанном на вызовах mmap()), с некоторыми изменениями в метаданных заголовка, чтобы отразить дополнения. Поля, из которых состоит запись, хранятся, как индивидуальные объекты в файле журнала, на которые ссылаются все записи, которым в них нуждаются. Это позволяет сохранить пространство на диске, поскольку обычно записи журнала часто повторяются (полагаю, каждое локальное сообщение будет содержать один и тот же _HOSTNAME= и _MACHINE_ID= поле). Поля данных сжимаются с целью сохранить дисковое пространство. Чистый эффект от этого состоит в том, что несмотря на то, что журнал сохраняет значительно больше метаданных, чем классический сислог, это не окзывает непосредственного влияния на занимаемое дисковое пространство.

Формат на диске использует исключительно 64bit LE (little endian) смещения, с целью упрощения и уверенности в том, что мы можем хранить бинарные блоки значительных размеров. Синхронизации между инструментами просмотра лога и демоном journald не требуется. Клиенты, которые хотят читать журнал, могут просто использовать вызов mmap() на файлы журнала и использовать уведомления об изменении файла, чтобы получить информацию об обновлениях.

Доступна клиентская библиотека для получения доступа файлам журнала. Эта библиотека позволяет индексированный доступ к записям журнала по любому полю и с произвольным доступом по непрерывным или в форме настенных часов временным меткам. Клиентская библиотека автоматически объединяет множество файлов журнала так, что они представляют собой единый унифицированный поток записей журнала. Так сделано с целью скрыть, является ли файл журнала архивом (то есть "свернутым") или принадлежащим можеству пользователей. Прозрачное объединение файлов журнала в интерфейсе браузера полностью динамично: в момент создания новых файлов журнала или удаления старых вид браузера автоматически обновляется. Фактически, подразумевается, что чтение журнала будет живым (live), чтобы позволить вести мониторинг источников журнала в реальном времени.

http://cgit.freedesktop.org/systemd/tree/src/journal/sd-journal.h?h=journal

Сообщения от непривелигерованных пользователей разделяются в индивидуальные журналы, по одному на пользователя. Используя POSIX ACL для контроля доступа на чтение, мы можем быть уверены, что пользователи смогут получить доступ к собственным файлам журнала. Записи журнала, которые генерируются системными службами по умолчанию недоступны для обычных пользователей, если только они не входят в специальные Unix-группы. Следует заметить, что разделение файлов позволяет настроить правильные права доступа, но глобальный контекст записей лога не теряется, поскольку стороне клиента файлы журналов объединяются, чтобы можно было одним глазом просмотреть все сообщения в верном порядке, как они прошли через глобальный журнал, который обеспечивается автоматически присваиваемыми порядковыми номерами. Все это обеспечивает эффективное разделение прав доступа без копромиссов в обеспечении контекста пользовательских журнальных записей.

Одна из основных идей журнала состоит в том, чтобы унифицировать различные технологии журналирования, которые мы сейчас имеем. Как таковой, журнал должен быть полноценной заменой для wtmp, логгеров ранней стадии загрузки и подобных им бэкэндов журналирования. Данные могут генерироваться из разных источников: сообщения ядра, создаваемые с использованием printk(), сообщения пространства пользователя, которые создаются посредством syslog(3), сообщения пространства пользователя, которые создаются через родной для журнала API, coredumps через /proc/proc/sys/kernel/core_pattern и прочее. В дальнейшем, мы надеемся улавливать сообщения прошивок (UEFI логи) a расширить журналирование ядра до поддержки журналирования в ядерных структурах. Поскольку все поля неявно индексируются в структуре данных журнала, извлечение из журнала пользовательских данных, наподобие wtmp является относительно недорогой операцией. Ранняя загрузка и журналирование во время исполнения унифицированы. До тех пор,пока /var не доступен, все записи журнала сохраняются в /run, и затем сбрасываются в /var как только он будет доступен. Это безкомпромисно означает, что все сообщения, генерируемые системой, не важно, из прошивок во время фазы POST, во время инициализации ядра, во время ранней загрузки или во время работы, закончат свой путь в индексированных файлах единого журнала.

С целью сделать записи узнаваемыми для клиентских утилит, записи журнала могут опционально нести 128bit иденитификатор в MESSAGE_ID=, установленый службой генерации сообщений. Этот ID должен быть случайно сгенерирован разработчиком во время разработки. К примеру, один ID для “Пользователь вошел в систему” и другой для “Пользователь вышел”. Все записи для этих событий будут обязаны нести 128bit ID что сделает их простыми для распознавания, и автоматически индексированными по этому полю. Это хорошая идея, использовать идентификаторы, совместимые с RFC4122 UUID тип 4, тем не менее это требование не является таким уж обязательным. Данное условие указано с целью обеспечить совместимость с другими системами журналирования, которые используют UUID-ы для идентификации типов сообщений, таких как логи прошивок UEFI. Если посмотреть на эти глобальные 128bit ID коды ошибок, то можно заметить, что в силу их случайности, не требуется центрального стандартизирующего органа, который присваивает цифровые ID конкретным типам сообщений. Присваивание идентификатора сообщения в целом необязательно, и мы ожидаем, что только малая часть журнала будет нести их, например, только те из них, которые необходимо распознавать из пользовательского окружения. Если разработчику нужен новый 128bit ID для присваивания новому типу сообщений, который он вводит, то все, что ему надо, это выполнить “cat /proc/sys/kernel/random/uuid” который вернет новый UUID при каждом вызове. 128bit ID также могут быть использованы для реализации локализованных сообщений пользовательских интерфейсов, которые смотрят в каталог сообщений на нужном языке и представляют пользователю переведеное сообщение в всем интерфейсе программы.

Все записи дополняются меткой времени с реальным временем (настенные часы) и непрерывное время. Чтобы сделать непрерывные штампы времени полнофункциональными, все сообщения также несут ID загрузки исполняемого ядра Linux (т.е. /proc/sys/kernel/random/boot_id). Точность составляет 1мкс, а настенные часы сохраняются в микросекундах с момента epoch UTC с целью избежать проблем с часовыми поясами, которые могут перемешать записи в сислоге.

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

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

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

В начальной версии journald поддержка сети очень проста: чтобы разделить файлы журнала, просто скопируйте их на один центральный хост утилитами типа scp, rsync или через NFS. Клиентский браузер журнала прозрачно объединит эти файлы, чередуя их по необходимости. В более поздних версиях мы планируем расширить журнал, как минимум, до поддержки живого (live) удаленного журналирования. В обоих PUSH и PULL режимах всегда используется локальный журнал, как буфер для логики сохранения и переправки. Вне зависимости от того, какой режим используется, подлежащий формат журнала спроектирован так, чтобы масштабироваться на большое количество хостов и все записи в журнале идентифицируются по идентификатору машины и имени хоста. Поставлена цель реализовать эффективный инструмент мониторинга, который может прозрачно и в прямом эфире (live) просматривать журналы с множества хостов, оставляя администратору выбор того транспорта, который удовлетворит его нуждам, например, является ли функциональность живого обновления важнее, чем возможность наступления thundering herd, ну и другие соображения.

Интернет - опасное место. Взломы высоконагруженных веб-сайтов становятся обычным делом, включая широко освещеный взлом kernel.org. После успешного взлома атакующий обычно пытается скрыть свои тропы редактируя файлы логов. С классическим syslog такие манипуляции очень трудно выловить: поскольку файлы в формате простого текста, не сделана криптографическая аутентификация и изменения не отслеживаются. Вполне в духе git, все записи в журнале криптографически хешированы предыдущей записью в файле. Это приводит к цепочкам записей , в которых каждая запись аутентифицирует все предыдущие . Если самый верхний хеш сохранять в безопасное, доступное только на запись место, то вся цепочка записей аутентифицируется этим хешем. Манипуляции атакующего могут быть легко обнаружены.

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

Демон журнала journald заменяет два мини-демона systemd, которые уже поставляются для целей журналирования (systemd-kmsg-syslogd и systemd-stdout-syslog-bridge). В отдаленной перспективе мы надеемся заменить традиционный демон syslog в большинстве инсталляций, но не конфликтовать с ним. Нагрузка на сеть (footprint) линукс-системы должна сократиться как в силу уменьшения количества работающих служб (1 вместо 3), так и потому что journald в текущем виде заметно меньше по объему кода, нежели жирный демон syslog.

Текущий статус

На текущее время, основная функциональность и все нетривиальные алгоритмы реализованы и доступны в git systemd, в ветке “journal”. Тем не менее код не завершен и ряд возможностей остался за его рамками.

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

Мы стремимся внести начальную реализацию в Fedora 17, но на первую попытку специально выбрали только несколько компонент. rsyslog будет работать с этими компонентами бок о бок, а пользователь практически не заметит journald, за исключением того, что “systemctl status” будет показывать последний вывод логов для всех служб. И конечно, он сможет поиграть с новыми клиентскими инструментами, такими, как “journalctl”, которые могут быть использованы для поиска по индексам журнала.

Frequently Asked Questions

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

  • Журнал, это хорошо, но systemd отвратителен, могу я использовать journald без systemd?

Нет, не можете. Журналирование является основной частью управления службами. Журнал тесно интегрирован с остальными частями systemd, чтобы быть уверенным в том, что все, что происходит в системе, может быть отслежено, рассмотрено и отлажено. Генерируемые записи журнала запрашиваются в разных компонентах, systemd и journald тесно связаны, так что разделение их не имеет смысла. Нелишне отметить, что это свободное ПО, так что вы можете делать с этим кодом то, что сочтете нужным. И в конце концов, вы совершенно неправы, полагая, что systemd отвратителен.

  • Запуск журнала сломает rsyslog/syslog-ng?

Нет, ни в коем случае. Вы можете запускать rsyslog или syslog-ng бок о бок с журналом и сообщения сислога будут сохраняться и в rsyslog/syslog-ng и в журнале. Тем не менее, журнал будет хранить множество мета-данных вместе с сообщениями сислога, а обычный syslog нет.

  • Моему приложению необходимы традиционные текстовые логи на диске. Могу я сконфигурировать journald так, чтобы он генерировал их?

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

  • Почему журнал не генерирует традиционные файлы логов?

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

  • Могу я подключить совместимый с RFC syslog протоколом удаленный генератор сообщений к журналу?

На текущий момент, нет. И наврядли journald будет поддерживать это из коробки. Тем не менее, это должно быть не слишком сложно написать конвертер или шлюз, который будет выполнять эту работу.

  • Я использую systemd во встраиваемой системе и не заинтересован в постоянном журналировании, могу я опционально выключить журнал?

Нет, никогда. Тем не менее, все, что вы хотите сделать, это сообщить systemd , что вам не требуются постоянные логи, и сделать это можно удалив (или не создав) директорию /var/log/journal. В этом случае journald будет вести лог только в директории /run/log/journal (что он делает всегда на раннней стадии загрузки). Директория /run непостоянна и теряется во время перезагрузки в отличие от /var. Ну и в идеале, можно сконфигурировать пределы занимаего дискового пространства в минимальное значение.

  • Все знают, что UUID сломаны. Зачем вы используете UUID для идентификации сообщений?

Ну, это правда, что спецификация UUID причудлива и излишне сложна. Из за этого мы рекомендуем остановиться на UUID Тип 4 и проигнорировать остальной RFC 4122. UUID на самом деле имеют долгую успешную историю в линукс. К примеру, все дистрибутивы по умолчанию монтируют файловые системы исключительно по UUID-ам файловых систем.

  • Да ладно вам, UUID никогда не работали! к примеру, MAC адреса повторяются и все мои USB устройства имеют один из них! Почему вы настаиваете на их использовании?

Ну, мы все время использовали их, к примеру, в файловых системах, как уже упоминалось чуть выше и они всегда выполняли свою работу очень хорошо. Аппаратное обеспечение несет серийные номера, которые многие производители устанавливают в 1-2-3-4-5 или нечто похожее, но все это имеет мало общего с основной идеей UUID-ов. Серийные номера устройств не являются UUID-ами. Не смешивайте их!

Вдобавок, мы не настаиваем на их использовании. Как отмечалось выше, UUID-ы полностью опциональны и должны назначаться только тем сообщениям, которые в дальнейшем требуется распознавать.

  • Но если я введу UUID для типа сообщения в мой код и кто-то использует этот код, как шаблон для новой работы, то журнал сломается.

Нет, это неверно. Почему? Просто потому, что одинаковый 128bit ID должен быть присвоен одному и тому же типу условия/записи ошибки, вне зависимости от того, из какого источника она пришла. То есть 128bit ID который используется для идентификации “Sector bad on block device” должен быть одинаковым вне зависимости от того, какое устройство генрирует это сообщение, или какой драйвер. Если программе в окружении пользователя необходимо отличать записи журнала от разных служб, драйверов или устройств, оно должно использовать дополнительные условия совпадения в полях служба/устройство/драйвер.

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

  • Но постойте, printf()/printk() форматированные строки сообщений будут куда лучше для идентификации типов сообщений!

Это реально не тот случай. В конце концов, форматированные строки, это шаблоны человеческого языка, а человеческий язык хрупок для идентификации типов сообщений: каждая исправленая орфографическая ошибка изменит тип сообщения и приведет в появлению в клиентах неопознанных сообщений. Каждый раз, когда сообщение журнала расширяется, перефразируется, переписывается, это становится местом для поломки ABI. Или если обернуться: используя форматированые строки сообщений как идентификаторы, каждое сообщение ядра становится ABI, а перевод человеческого языка в ABI фатален. По сути, мы мало что приобрели по сравнению со стандартным журналом с его дорогим сравнением по регэкспам и внесением сообшений в ABI. С другой стороны, идентификаторы сообщений остаются неизменными, в то время как соответствующие строки на человеческом языке меняются, таким образом мы аккуратно разделяем ABI и человеческий язык.

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

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

  • Кто будет организовывать и управлять пространствами имен UUID и генерировать UUID-ы? Серьезно, мы не хотим больше бюрократов, которые будут только игнорировать!

Хорошая новость относительно 128bit случайных идентификаторов состоит в том, что их пространства имен не требует управления. Каждый может просто взять случайный UUID из /proc/sys/kernel/random/uuid и он будет его. Разработчики могут сгенерировать столько UUID-ов, сколько им нужно не спрашивая централизованые органы. UUIDы позволяют иметь общее пространство имен безо всякой бюрократии.

  • Да вернитесь на землю, в самом деле! UUID-ы? Вы с какой планеты!? Все знают, что агенство наподобие LANANA должно быть идеалом присвоения глобального уникального идентификатора типа сообщения для приложений!

Linux не изолирован. Крайне желательно, чтобы эти идентификаторы сообщений, которые используются другой инфраструктурой без швов интегрировались с тем, что мы делаем в журнале. Поэтому мы и выбираем то, что имеет смысл и уже где-то используется. Также, UUID в своей основе представляют собой несколько больше, чем глобальное пространство имен для уникальных идентификаторов, Которому не требуется центральная организация . Зачем нужна бюрократия в подконтрольном регистраторе, если можно обойтись без нее?

  • Нет, вы должны использовать обратную нотацию доменных имен как в яве, чтобы идентифицировать типы сообщений!

Сравнение строк значительно сложнее, чем сравнение идентификаторов фикированых размеров. А еще, посмотрите правде в лицо, данное решение в любом случае не решит проблемы с пространствами имен, поскольку 90% всех сообщений будут скорее всего в одном пространстве имен: org.freedesktop resp. org.kernel.

  • Но ASN.1 OID-ы сделали отличные идентификаторы типов!

Чувак, ты это серьезно?

  • Ладно, у меня есть даже лучше идея, как насчет того, чтобы использовать URL как идентификатор типов сообщений?

Ну, они имеют минимальные преимущества перед обратной доменной нотацией. Этого хватит?

  • Но ребята, если вы каждый раз генерируете UUID на каждую запись это привдет к тому, что мой пул энтропии (entropy pool) будет всегда пуст!

Прочитайте эту статью еще раз, так как вы невнимательно ее прочитали. 128bit идентификаторы типа сообщения присваиваются разработчиком тогда, когда необходимо идентифицировать определенный тип сообщения во время разработки , не во время исполнения. Большинство проектов скорее всего никогда не сгенерируют более 30 идентификаторов за все время разработки, и энтропия для этого должна быть простецки доступна на машинах разработчиков 10-летней давности.

  • Вы сумасшедшие фанатики юзерспеса, сначала вы принудили меня использовать в моей системе 20 cpu cgroups, а теперь вы заставляете меня иметь вонючие UUID-ы в моей системе?

Ну, не говоря о том, что мы не принуждали вас использовать 20 cpu cgroups, и то, что вы уже используете UUIDы все это время, потому что ваша файловая система ищет файловые системы через UUIDы во время загрузкиe -- принимая во внимание детали реализации и то, что вы не любите их, так не присоединяйте их к своим сообщениям. Это принесет свою цену, поскольку сообщения не смогут быть идентифицированны иначе как через ужасы регэкспов. Но, может быть, это то, что вы хотели? И в любом случае, мы никого не принуждаем делать что-либо.

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

К счастью, ядро Linux поддерживает SCM_CREDENTIALS, который предоставляет нам информацию об отправителе сообщения, которая не может быть подделана.

  • Будет ли формат журнала стандартизирован? Где я могу найти описание структур данных на диске?

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

  • Почему вы опять переизобретаете колесо? Почему просто не добавить все, что вам необходимо в сислог? Если вы просто почистите форматирование лога, сислог будет хорош!

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

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

Журнал делает syslog полностью устаревшим?

Нет, прежде всего, syslog API syslog(3) поддерживается как интерфейс первого класса для записи сообщений в лог, и продолжает оставаться главным API для всех простых текстовых логов. Тем не менее, как только потребуется присовокупить к тексту метаданные (возможно, двоичные метаданные), потребуется использовать вместо него нативный journal API.

Во вторых, журнал полностью новая вещь. Syslog является широко признаным индустриальным стандартом (хотя и довольно слабо определенным, поскольку о формате журнала еле договорились.), который реализован во множестве систем, программ и устройств. Таким образом, syslog и далее останется важным и будет востребован во многих и многих инсталляциях. Демон журнала не говорит по протоколу RFC, и вряд ли когда нибудь будет. Во всех местах, где требуется совместимость с протоколом syslog, будет востребован классический сислог. Чтобы быть уверенным, что это работает, мы реализовали журнал так, что он может бе помех работать совместно с локальным демоном syslog и сообщения будут переправляться по мере необходимости таким образом, чтобы сислог продолжал работать полностью так, как он работал бы без journald.

И это как раз та причина, по которой вы приглашены!

Прежде чем поместить их рядом, мы говорили с рядом пользователей, которые используют высоконагруженые логи, включая пользователей с сотнями тысяч активных хостов. Мы также разговаривали с рядом инженеров которые работают в этой области или могут стать серьезными пользователями журнала. Мы особенно интересовались шаблонами использования и проблемами масштабирования. Тем не менее, конечно, каждая инсталляция имеет свои собственные требования и потребности. Мы хотели бы попросить вас связаться с нами в том случае, когда какая-то важная функциональность, которая вам нужна, не покрывается нашим проектом. Наше внимание сосредоточено на нижних слоях стека журналирования. Специфичные интерфейсы пользователя нас пока не интересуют, тем не менее мы будем рады просить вас оставлять комментарии об этом позднее. Еще стоит отметить, что это не рождество, так что мы скорее всего не выполним все ваши пожелания (пожалуйста, не разочаровывайтесь!), но нам до них есть дело, поэтому ознакомьте нас с ними и мы обещаем, что хотя бы рассмотрим их!

Заранее большое спасибо!

Updated