Хранение метрик Zabbix

10 декабря 2018

  • Главным нововведением Zabbix 4.0, вышедшего в уходящем году, является поддержка ElasticSearch в качестве хранилища для значений собираемых метрик.
  • Предыдущие версии умели сохранять их только в SQL-таблицах, и это создавало огромные неудобства при удалении старых значений.
  • Ответственный за удаление процесс HouseKeeper служил постоянным источником проблем — либо удаление происходило слишком медленно и долго, либо ядро и Веб-интерфейс оказывались парализованными, либо то и другое сразу.
  • Запуск HouseKeeper'а почти всегда приводил к ложным срабатываниям триггеров — в лучшем случае про сам HouseKeeper, в худшем случае мы получали поток «Zabbix agent is unreachable for 5 minutes» для всех отслеживаемых через Zabbix узлов.
  • В качестве обходного решения предлагается и используется партиционирование таблиц, но его объём и «костыльность» заставляют откладывать внедрение до того момента, когда база слишком разрастается и почти все попытки решить исходную проблему не столько решают, сколько усугубляют её.

Рекомендуемая документация:

ElasticSearch:

  • Подключаем репозиторий — создаём файл /etc/yum/repos.d/elasticsearch.repo
  • [elasticsearch-6.x]
    name=Elasticsearch repository for 6.x packages
    baseurl=https://artifacts.elastic.co/packages/6.x/yum
    gpgcheck=1
    gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
    enabled=1
    autorefresh=1
    type=rpm-md
  • Устанавливаем (Java Runtime надо указывать явно, потому что в зависимостях пакета elasticsearch он почему-то отсутствует):
  • yum install -y jre-headless elasticsearch curl
    systemctl daemon-reload
    systemctl enable elasticsearch
    systemctl start  elasticsearch
  • Дальше необходимо создать в ElasticSearch т.н. maps, т.е. описание структуры будущих индексов, в которые будет писать Zabbix.
    Этот момент во всех описаниях указан нечётко. Мы поместили все необходимые команды в один сценарий, который можно скачать и запустить одной командой:
  • curl https://gist.githubusercontent.com/ilyaevseev/a9bebe1ac19c91d597379db7de45ea78/raw//zabbix-elasticsearch-datebased-maps-init.sh | sh
  • Проверяем индексы и maps:
  • curl "localhost:9200/_cat/indices?v"
    curl "localhost:9200/_all/_mapping?pretty=true"
  • Перед запуском необходимо освободить на диске минимум 5% места, иначе ES откажется принимать данные на запись.

Zabbix:

  • Установка новой версии:
  • systemctl stop zabbix-server
    systemctl stop php-fpm
    rpm -Uvh https://repo.zabbix.com/zabbix/4.0/rhel/7/x86_64/zabbix-release-4.0-1.el7.noarch.rpm
    yum upgrade
    
  • Отключение SQL-таблиц, хранящих значения метрик:
  • mysql -e 'rename table history_uint to history_uint_until_2018' zabbix
    mysql -e 'rename table history      to history_until_2018'      zabbix
    
  • При первом запуске новая версия Zabbix'а произведёт автоматическое обновление базы. Этому могут помешать старые проблемы, например, русские символы в таблицах с кодировкой latin1. Чтобы обновление не закончилось с ошибкой, предварительно исправьте их вручную:
  • mysql -e 'ALTER TABLE problem CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci' zabbix
  • Чтобы ядро Zabbix'a начало использовать ElasticSearch и создавало посуточные индексы вместо монолитных, достаточно добавить две строки в /etc/zabbix/zabbix_server.conf:
  • HistoryStorageURL=http://127.0.0.1:9200
    HistoryStorageDateIndex=1
  • Чтобы Веб-интерфейс начал читать значения из ElasticSearch, потребуется добавить в /etc/zabbix/web/zabbix.conf.php:
  • global $HISTORY;
    $HISTORY['url'] = 'http://127.0.0.1:9200';
    $HISTORY['types'] = ['uint', 'text', 'str', 'log', 'dbl'];
    
  • Настройка закончена, запускаем ядро и Веб-интерфейс Zabbix:
  • systemctl start zabbix-server
    systemctl start php-fpm
    
  • Проверяем, что индексы начали заполняться значениями:
  • curl "localhost:9200/_cat/indices?v"

Мониторинг работоспособности:

  • Работоспособность ElasticSearch теперь является для Zabbix'a ключевой, поэтому о проблемах в работе ES надо узнавать максимально быстро.
  • Zabbix является системой мониторинга, поэтому логично следить за состоянием ES прямо из него.
  • В сети есть достаточное количество готовых полнофункциональных шаблонов, но если они представляются для вас слишком громоздкими, то можете воспользоваться предложенным ниже простым вариантом.
  • Итак, создайте новый шаблон в Zabbix'e:
    • имя: elasticsearch;
    • создайте внутри него Application «ElasticSearch»;
    • назначьте этот шаблон Zabbix-серверу.
  • Создайте в шаблоне метрику, которая будет следить за сетевым портом, на котором ES принимает подключения:
    • Name: ElasticSearch listening on port 9200;
    • Key: net.tcp.listen[9200];
    • Application: ElasticSearch.
  • Триггер для неё:
    • Name: ElasticSearch is not listening on port 9200 on {HOSTNAME}
    • Severity: Disaster
    • Expression: {elasticsearch:net.tcp.listen[9200].last()}=0
  • Метрика, показывающая состояние ES (green/yellow/red, для одиночного сервера без кластеризации нормальным будет yellow):
    • Name: ElasticSearch cluster health;
    • Type: Zabbix agent
    • * Key: elasticsearch.cluster_health_status
    • Type: Character;
    • Application: ElasticSearch;
  • Описание метрики в настройках агента:
    • создайте файл /etc/zabbix/zabbix_agentd.d/elasticsearch.conf;
    • UserParameter=elasticsearch.cluster_health_status,curl -sS 'http://127.0.0.1:9200/_cluster/health?pretty=true' | awk -F'"' '$2 == "status" { print $4; exit }'
    • скомандуйте агенту перечитать настройки:
    • systemctl restart zabbix-agent
  • Триггер на «жёлтый» уровень здоровья:
    • Name = ElasticSearch cluster status is "yellow" on {HOSTNAME};
    • Severity = Warning;
    • Expression = {elasticsearch:elasticsearch.cluster_health_status.str(yellow)}=1.
  • Триггер на «красный» уровень здоровья:
    • Name = ElasticSearch cluster status is "red" on {HOSTNAME}
    • Severity = High
    • Expression = {elasticsearch:elasticsearch.cluster_health_status.str(red)}=1
  • Убедитесь, что первый триггер срабатывает:
    • остановите ES командой systemctl stop elasticsearch;
    • в течение минуты Zabbix должен отреагировать на это на странице Monitoring => Problems;
    • снова запустите ES и убедитесь, что проблема в Zabbix'e ушла.
  • Если для ElasticSearch не настроен отказоустойчивый кластер из нескольких узлов, уровень здоровья всегда будет понижен с зелёного до жёлтого. Поэтому для одиночных узлов триггер на жёлтый уровень имеет смысл отключать.

Удаление устаревших метрик:

  • Создайте файл /etc/cron.daily/Remove-old-Zabbix-metrics-from-ElasticSearch (и сделайте его исполняемым с помощью chmod +x):
  • #!/bin/sh -e
    
    MAX_DAYS="93"
    LOG_DAYS="93"
    LOG_DIR="/var/log/zbx-es-metrics-cleanup"
    LOGFILE="$LOG_DIR/$(date +%Y-%m-%d-%H%M).log"
    
    mkdir -p "$LOG_DIR"
    
    D0="$(date -d "$MAX_DAYS days ago" +%s)"
    
    curl -sS "http://127.0.0.1:9200/_cat/indices" | awk '{ print $3 }' |
    while read idx; do
        D="$(date -d "${idx#*-}" +%s 2>/dev/null || :)"
        test "$D" = ""      && continue
        test "$D" -ge "$D0" && continue
        curl -X DELETE "http://127.0.0.1:9200/$idx"
    done >> "$LOGFILE" 2>&1
    
    find "$LOG_DIR/" -type f -name '*.log' -mtime "+$LOG_DAYS" -delete
  • Срок хранения в MAX_DAYS установите, исходя из собственных потребностей и возможностей.
  • Обратите внимание, что индивидуальные настройки «History storage period» в свойствах метрик теперь игнорируются.
    Их использовал HouseKeeper. Новый сценарий использует только свой собственный, общий для всех метрик параметр — MAX_DAYS.
  • В качестве альтернативы в Сети рекомендуют использовать приложение Curator, но мы не видим смысла в отдельном приложении там, где достаточно пары HTTP-запросов.

Импорт старых метрик из MySQL в ES:

  • Выполняется при помощи Logstash с JDBC-плагином, детально описан в статье на SoHabr'e, ссылку на которую мы привели выше, и в копипасте которой не видим смысла.

← Назад в Блог