ElasticSearch для ведення журналу

Ми використовуємо ElasticSearch у мене на роботі для фронтальних веб-запитів. Продуктивність критична, і для наших цілей, дані в основному статичні. Ми оновлюємо пошукові індекси щодня, але не маємо проблем запуску на старих індексах протягом декількох тижнів. Більшість трафіку на цьому кластері забирає пошук; це "важкий для читання" ( "read heavy") кластер. У нас були деякі збої продуктивності на початку, але ми працювали в тісному співробітництві з Шейем Беннон з ElasticSearch для ліквідації цих проблем. Тепер наші фронт-енд кластери є дуже надійними, стійкими і швидкими.

Зараз я працюю над реалізацією централізованої інфраструктури реєстрації, яка відповідає за технічні вимоги, але також корисна. Мета інфраструктури реєстрації наслідувати якомога більшої частини функціональності Splunk, наскільки це можливо. Моя попередня запис по журнал пояснює, чому ми проголосували проти Splunk .

Після оцінки ряду варіантів, я вирішив використовувати ElasticSearch як храненіліще на сервері для цієї системи. Цей тип кластера дуже відрізняється від кластера, який ми реалізували для пошуку важких завантажень.

макети покажчиків

Дві популярні системи маршрутизації журналу з відкритим вихідним кодом це Graylog2 і LogStash . На момент написання статті, стабільна версія Graylog2 підтримувала тільки написання / читання з одного індексу. Як я вже зазначав у попередній статті, це представляє великі проблеми масштабування для Graylog2. Реліз Graylog2 0.10.0 включатиме в себе здатність до індексування до кількох індексам. Однак, мій досвід був з індексами LogStash, оскільки це були єдині масштабовані опції в минулому.

Для того, щоб отримати максимальну віддачу від ElasticSearch під час журналирования, ви повинні використовувати кілька індексів. Є кілька способів впоратися з цим при пролонгації індексу, але автоматичне добове обертання LogStash за замовчуванням, виходить, має більше сенсу. Таким чином, у вас вийде щось на кшталт:

  • logstash-2012.12.19
  • logstash-2012.12.20
  • logstash-2012.12.21
  • logstash-THE_WORLD_HAS_ENDED

Ви можете слідкувати за кількістю документів в кожному індексі. Потім згорнути це після мільйонів або мільярдів, або іншого довільного числа, якого вам заманеться, але ви просто створите більше роботи для себе пізніше. Є деякі випадки, коли є деякі крайні схеми, де інші схеми індексації можуть бути більш ефективним, але для більшості користувачів ідея "в день за індексом" є найпростішою, найефективнішою у використанні ваших ресурсів.

Давай серйозно або йди додому.

Обидва LogStash і Graylog2 поставляються з вбудованим ElasticSearch патчем. Це дуже зручно для демонстраційних цілей або розробок. НЕ використовуйте ЦЕЙ ВБУДОВАНИЙ СЕРВЕР ДЛЯ РЕАЛЬНИХ ЦІЛЕЙ! Я здивований кількістю користувачів LogStash і Graylog2, які закінчують на #elasticsearch або irc.freenode.org, які використовують вбудований движок сховища ElasticSearch і дивуються, що все обвалилося!

Запустіть автономний кластер ElasticSearch!

Вам знадобиться окреме обладнання для цього. Java додатки, такі як LogStash і ElasticSearch є інтенсивними для пам'яті і дискового кеша. Зафіксуйте обладнання на коробках переробки індексації журналу і окремі коробки до кластеру ElasticSearch. Java має деякі дивні проблеми з пам'яттю. Ми виявили, що Ви не хочете переглядати 32 ГБ оперативної пам'яті, присвяченій ElasticSearch, і резерв щонайменше, 8 Гб, присвячений індексування файлової системи ОС кешування.

Мій кластер обробляє ~ 60 Гб даних журналу в день в моїй середовищі розробки з 3 пошуковими вузлами на 24 Гб оперативної пам'яті кожен і це захоплення. Це викликає наступне питання, скільки серверів для мого кластера? Почніть з 3 серверів в кластері ElasticSearch. Це дає вам гнучкість для відключення сервера і підтримку в повній мірі для використання кластера. Ви завжди можете додати більше обладнання!

установка ElasticSearch

Я не стану повністю описувати установку ElasticSearch, ви можете прочитати про це більше на сайті документації. Ви можете навіть вирішити видалити .deb або, можливо, запустити rpm і створити «рецепт» управління ElasticSearch за допомогою Puppet або Chef . Єдина річ, яку я скажу про встановлення, це те, що не дивлячись на всі труднощі, найкраще запускати ElasticSearch за допомогою Sun JVM . Так розробники ElasticSearch користуються ElasticSearch і ви теж можете!

Конфігурація ElasticSearch: OS і Java

Є деякі речі, які вам дійсно потрібно налаштувати на хост-системі. Я припускаю, що ви використовуєте Linux в якості хост-системи. Ви повинні запустити ElasticSearch як непривілейований користувач. Мій кластер працює як користувач "elasticsearch", тому ми налаштовуємо межі ядра на процеси і пам'ять в '/etc/security/limits.conf':

 # Ensure ElasticSearch can open files and lock memory! elasticsearch soft nofile 65536 elasticsearch hard nofile 65536 elasticsearch - memlock unlimited 

Тому ви повинні налаштувати мінімальний і максимальний пул пам'яті ElasticSearch і встановити в тому ж значенні. Це бере на себе всі розподілу пам'яті при запуску, так що вам не доведеться чекати, щоб отримати більше пам'яті з ядра. Я побудував ElasticSearch в системі RedHat і він є в моєму '/ etc / sysconfig / elasticsearch' яка встановлює змінні середовища для демона при запуску:

 # Allocate 14 Gigs of RAM ES_MIN_MEM=14g ES_MAX_MEM="$ES_MIN_MEM" 

Цей файл знаходиться у веденні Puppet і встановлює пам'ять, рівну індексування 50% від RAM + 2 гігабайти. Це не ракетобудування, і це розглядається в кожному керівництві настройки ElasticSearch.

Конфігурація ElasticSearch: elasticsearch.yml

Є деякі речі, які ми можемо налаштувати у файлі '' elasticsearch.yml ", які значно поліпшать продуктивність важких для запису вузлів. По-перше, встановити bootstrap.mlockall на" так ". Це змушує JVM виділити все ES_MIN_MEM негайно. Це означає, що у Java є вся пам'ять, необхідна при запуску! Ще одна проблема важкого на запис кластера - це дисбаланс виділення пам'яті індексування / об'ємному двигуну.

ElasticSearch передбачає, що ви збираєтеся використовувати його в основному для пошуку, так що більшість вашого розподілу пам'яті охороняється для пошуків. Питання не в цьому кластері, так, по налаштуванню indices.memory.index_buffer_size до 50% ми можемо відновити баланс, необхідний для цього використання. У моїй установці, я також піднімав інтервал оновлення і угоду розраховував на очистку журналу. В іншому випадку, ElasticSearch буде чистити транслогаріфм майже кожну секунду.

Друга річ, яку ми повинні налаштувати, щоб уникнути катастрофічних невдач, це налаштування пулу потоків. ElasticSearch буде робити те, що на його думку найкраще для досягнення найвищої продуктивності. Ми з'ясували, на виробництві, що це може означати виловлювання тисяч і тисяч потоків для обробки вхідних запитів. Це виведе весь кластер з ладу досить швидко під таким навантаженням. Щоб уникнути цього, ми встановлюємо максимальну кількість потоків в пул; пошук, індекс, і основний. Більшість наших операцій будуть громади, тому ми залишаємо загрозам 60, і іншими операціями 20. Ми також встановлюємо максимальну кількість запитів, яке може "стояти" в черзі на обробку 200 для громади і 100 для всього іншого. Таким чином, якщо кластер стає перевантаженим, він хоче відмовитися від нових запитів, але він залишить вам досить файлових дескрипторів і ідентифікаторів PID, щоб заглянути в коробки і з'ясувати, що пішло не так.

Зібравши все це разом, ось мій конфігураційний файл:

################################################## ################
# /etc/elasticsearch/elasticsearch.yml
#
# Base configuration for a write heavy cluster
#
# Cluster / Node Basics
cluster.name: logng
# Node can have abritrary attributes we can use for routing
node.name: logsearch-01
node.datacenter: amsterdam
# Force all memory to be locked, forcing the JVM to never swap
bootstrap.mlockall: true
## Threadpool Settings ##
# Search pool
threadpool.search.type: fixed
threadpool.search.size: 20
threadpool.search.queue_size: 100
# Bulk pool
threadpool.bulk.type: fixed
threadpool.bulk.size: 60
threadpool.bulk.queue_size: 300
# Index pool
threadpool.index.type: fixed
threadpool.index.size: 20
threadpool.index.queue_size: 100
# Indices settings
indices.memory.index_buffer_size: 30%
indices.memory.min_shard_index_buffer_size: 12mb
indices.memory.min_index_buffer_size: 96mb
# Cache Sizes
indices.fielddata.cache.size: 15%
indices.fielddata.cache.expire: 6h
indices.cache.filter.size: 15%
indices.cache.filter.expire: 6h
# Indexing Settings for Writes
index.refresh_interval: 30s
index.translog.flush_threshold_ops: 50000
# Minimum nodes alive to constitute an operational cluster
discovery.zen.minimum_master_nodes: 2
# Unicast Discovery (disable multicast)
discovery.zen.ping.multicast.enabled: false
discovery.zen.ping.unicast.hosts: [ "logsearch-01", "logsearch-02", "logsearch-03"]
view raw elasticsearch.yml hosted with ❤ by GitHub

Конфігурація ElasticSearch: Шаблони індексів

Як я вже говорив, я розробив цей кластер на основі LogStash через недоліки в реалізації Graylog2 в той час. Даний розділ буде містити поняття "журнальна ничку", але ви можете легко адаптувати це до Graylog2 або домашньому відображенню індексу.

Так як ми вирішили створювати за індексом в день, є два шляхи для налаштування відображення функції кожного індексу. Ми можемо створити індекси або явно з настройками, які ми хочемо, або ми можемо використовувати шаблон, щоб це був будь-який індекс, створений неявно по запису даних від індексування, і мав свої особливості і конфігурації, які ми хочемо! Шаблони мають найбільший сенс в цьому випадку, ви будете створювати їх на вже працюючий кластер!

Налаштування мого шаблону:

{
"Template": "logstash- *",
"Settings": {
"Index.number_of_shards": 3,
"Index.number_of_replicas": 1,
"Index.query.default_field": "@message",
"Index.routing.allocation.total_shards_per_node": 2,
"Index.auto_expand_replicas": false
},
"Mappings": {
"_default_": {
"_all": { "Enabled": false},
"_source": { "Compress": false},
"Dynamic_templates": [
{
"Fields_template": {
"Mapping": { "type": "string", "index": "not_analyzed"},
"Path_match": "@ fields. *"
}
},
{
"Tags_template": {
"Mapping": { "type": "string", "index": "not_analyzed"},
"Path_match": "@ tags. *"
}
}
],
"Properties": {
"@fields": { "Type": "object", "dynamic": true, "path": "full"},
"@source": { "Type": "string", "index": "not_analyzed"},
"@source_host": { "Type": "string", "index": "not_analyzed"},
"@source_path": { "Type": "string", "index": "not_analyzed"},
"@timestamp": { "Type": "date", "index": "not_analyzed"},
"@type": { "Type": "string", "index": "not_analyzed"},
"@message": { "Type": "string", "analyzer": "whitespace"}
}
}
}
}

Щоб застосувати настройки до кластеру, ми створюємо або оновлюємо шаблон за допомогою PUT:

 curl -XPUT 'http://localhost:9200/_template/template_logstash/' -d @logstash-template.json 

Установка шаблона logstash- * означає все нові індекси, створені і починаються з "logstash-" будуть володіти цими параметрами. Я перевизначив поведінку пошуку за замовчуванням, відключивши пошук полях _all і встановивши атрибут @message за замовчуванням. Це поле буде сирим syslog-повідомленням. Це, отже, єдине поле, в якому аналізатор відключений. Не хвилюйтеся. Це економія простору і часу індексування. Пошук інших полів в документі буде відповідати допомоги в пошуку точних збігів, а не нечітких запитів, але це нормально. Ми можемо спокійно отримати цей нестабільний тепле почуття, шукаючи поле @message! Це дозволить різко зменшити розмір сховища.

У попередніх рецензіях, до ElasticSearch 0.19, ви, можливо, бачили 6набор атрибутів "_source": { "compress": true}. Не рекомендується для реєстрації даних. Цей атрибут детермінує кожен документ (читай: вхідне повідомлення) зберігається з використанням стискання. Так як ці документи, як правило, дуже маленькі, стиск не заощадить реально багато місця. Це варто додаткової обробки під час індексації та пошуку. Краще дійсно відключити стиск для реєстрації кластера. Установка, яка дозволяє зберігання стиснення в нашій elasticsearch.yml використовує стиснення на рівні блоків і є набагато ефективнішою.

установки індексу

Налаштування індексу налаштовані на 3 вузла кластера. Ми можемо все змінити, але index.number_of_shards схаменеться на льоту, якщо нам потрібно збільшити або зменшити кластер. Дана установка неточно ідеальна, як ми іноді маємо справу з "осиротілими" (нерозподіленими) Шарден. Це досить легко виправити шляхом переміщення Шардена до ElasticSearch API .

Замість реплікації всього індексу на повний кластер, ми додаємо ємність, оскільки ми додаємо вузли. Таким чином у нас є схожа з "RAID" установка для локалізації Шардена. У мене є 3-вузловий кластер і я створюю 3 Шарда на індекс. Це означає, що майстер або "ми" шард можуть бути збалансовані в один на кожному вузлі. Для резервування, я поставив ряд реплік на один. Це означає, що є 6 Шарден для кожного індексу. Кожен вузол може мати тільки 2 Шарда на індекс.

Ви повинні будете поекспериментувати з цими настройками для ваших потреб. Візьміть до уваги, скільки вузлів ви можете дозволити собі втратити, перш ніж втратити функціональність. Ви повинні будете регулювати кількість реплік на основі цього. Я пішов по простому шляху і просто створив 1 репліку Шарда. Дане означає, я можу тільки зберегти тільки єдиний вузол від кластера. Поки, я зрозумів, що, number_of_replicas рівні (2/3 * Кількість вузлів) - 1 це хороший номер.

Автоматично розгортаються репліки

Також, отже, краще відключити поведінка за умовчанням ElasticSearch до автоматичного розширення кількості копій, заснованого на тому, скільки вузлів в кластері. Ми приймаємо відповідальність за управління цим вручну і продуктивність посилюється, особливо, коли ми повинні зупинити або перезапустити вузол в кластері. Авто-розширення відмінна можливість для пошуку важких індексів з малими і середніми даними. Без реконфігурації, додавши ще один вузол можна підвищити продуктивність. Однак, якщо у вас є багато даних в індексі, і ця функція включена, ось що відбувається, коли вузол перезапускается:

  • Все добре, число реплік = 1.
  • Вузол A закривається
  • Кластер це помічає і стає жовтим
    • реплік = 0, очікується 1
    • кількість вузлів зараз = 1
    • кол-во реплік, що очікуються = 0 зараз
  • Стан кластера покращено до зеленого, все оновлено
  • Вузол повертається в онлайн
  • Кластер посилає кількість очікуваних реплік, актуальних для всіх індексів
  • Вузол розуміє, що це Шарден не потрібні, і видаляє дані
  • Кластер збільшує кількість вузлів, репліки очікуються = 1, поточна = 0
  • Вузол обізнаний, що кількість реплік ще не відповідає
  • Вузол повторює кожен шард назад в його індекс, по мережі

Як ви можете бачити, це менше, ніж бажано, особливо з напруженим кластером. Будь ласка, будьте в курсі цієї поведінки у виробництві і спостерігайте за вашими мережевими графіками, коли ви додаєте / видаляєте вузли з кластера. Якщо ви бачите скачки, ви можете керувати вручну. Ви втрачаєте частину чарівництва, але ви можете взяти це за чаклунство в будь-якому випадку. При відключенні автоматичного розширення реплік, відбувається наступне:

  • Все добре.
  • вузол вимикається
  • Кластер це помічає, статус кластера жовтий
  • Стан кластера не покращується, очікувані репліки! = Фактичним реплік
  • Вузол А повертається
  • Кластер посилає кількість очікуваних реплік і актуальних для всіх індексів
  • Вузол А повідомляє кластер, що у нього є копії Шардена
  • Очікуваний кластер і фактичні репліки в даний час рівні, стан "зелене"
  • Кластер обчислює контрольні Шарден і повторює будь-які застарілі Шардена до вузла А

Це те, що більшість людей чекають від кластера за замовчуванням, але логіка, необхідна для виявлення стану кластера, робить це скрутним. Знову ж таки, магія поведінки auto_expand_replicas має сенс в більшості випадків використання, але не в нашому випадку.

Технічне обслуговування та моніторинг

Я написав кілька сценаріїв для роботи з ElasticSearch в середовищі розробки. Вони включають експорт метрик в Graphite і Cacti. Існує, отже, перевірка моніторингу Nagios, яка дуже конфігурується. Ми використовуємо ці утиліти для відстеження продуктивності і стану наших різних кластерів, включаючи журналоведческій кластер. Я буду оновлювати це в найближчі кілька днів, щоб включити мій сценарій керування індексом logstash.

В процесі того, як ви пишете ваші дані в журнал кластера, ElasticSearch створює індекс Lucene податкових повідомлень у фоновому режимі. Існує буфер вхідних документів і на основі ваших налаштувань, ці дані записуються на індекс Lucene. Індекси Lucene дорогі для створення / оновлення, але швидкі для пошуку. Це означає, що один шард може містити сотні індексів Lucene, які часто називають сегментами. Ці сегменти можуть бути швидко знайдені, але тільки один на потік може бути оброблений. Це може почати чинити негативний вплив на продуктивність. Ми бачили, погіршення швидкості пошуку на 10% з індексами з 20+ сегментів.

На щастя, ElasticSearch надає API для оптимізації сегментів Lucene . Ви не повинні оптимізувати індекс, в даний час індексує дані. Нові дані будуть просто створювати більше сегментів на тих Шардена. Так як ми можемо знати, що ми закінчили записи на індекс? Ну, якщо ви пам'ятаєте, я рекомендував використовувати щоденний індекс. Це означає, що ви можете запустити завдання щодня (або щогодини), щоб перевірити наявність індексів з вчорашнього дня і старше і переконатися, що вони 'повторно оптимізовані (або max_num_segments = 1). Якщо ви вибрали якусь іншу схему для створення імен індексів, ви тільки що створили більше роботи для себе.

майбутні дослідження

Цей пост виявився більше, ніж я очікував. Я показую тільки поверхневий погляд на розробку і реалізацію кластера ElasticSearch для логгіруемих даних. Мій кластер буде рухатися від розробки до виробництва найближчим часом (хоча він і в даний час забезпечує виробничі функції). Коли я щось роблю, я готовий зіткнутися з деякими додатковими труднощами і у мене є ноутбук, повний ідей про те, як структурувати індекси і кластери і впоратися з навантаженням і деякими з приватних проблем, які виникають, коли ви раптом надаєте простий, швидкий доступ до величезних обсягів даних.