Elasticsearch bootstrap error

I'm trying to use the Flink 5.x Elasticsearch sink connector to insert data to ES 5.2.1 instance hosted on a tiny VM. As this is a tiny VM in development mode, I cant get it to start up to accept

Issue is «max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]»

vm.max_map_count is very low, increasing its count will solve the issue

1. Linux

check with the vm.max_map_count setting in /etc/sysctl.conf:

grep vm.max_map_count /etc/sysctl.conf

OUTPUT : vm.max_map_count=262144

If the output is less than 262144, Apply the new count as elasticsearch expects, we have two options to add permanently or temporary fix.

add the varibale to /etc/sysctl.conf

vm.max_map_count=262144

OR

sysctl -w vm.max_map_count=262144

2. OSX with Docker for Mac

The vm.max_map_count setting must be set within the xhyve virtual machine:

screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty

Log in with the root and no password. Then configure the sysctl setting as you would for Linux:

sysctl -w vm.max_map_count=262144

3. OSX with Docker Toolbox

The vm.max_map_count setting must be set via docker-machine:

docker-machine ssh

sudo sysctl -w vm.max_map_count=262144

4. Docker Desktop with WSL on Windows

The vm.max_map_count setting must be set via wsl:

wsl

sudo sysctl -w vm.max_map_count=262144

Bootstrap Checksedit

Collectively, we have a lot of experience with users suffering
unexpected issues because they have not configured
important settings. In previous versions of
Elasticsearch, misconfiguration of some of these settings were logged
as warnings. Understandably, users sometimes miss these log messages.
To ensure that these settings receive the attention that they deserve,
Elasticsearch has bootstrap checks upon startup.

These bootstrap checks inspect a variety of Elasticsearch and system
settings and compare them to values that are safe for the operation of
Elasticsearch. If Elasticsearch is in development mode, any bootstrap
checks that fail appear as warnings in the Elasticsearch log. If
Elasticsearch is in production mode, any bootstrap checks that fail will
cause Elasticsearch to refuse to start.

There are some bootstrap checks that are always enforced to prevent
Elasticsearch from running with incompatible settings. These checks are
documented individually.

Development vs. production modeedit

By default, Elasticsearch binds to loopback addresses for
HTTP and transport (internal) communication. This is fine
for downloading and playing with Elasticsearch as well as everyday development,
but it’s useless for production systems. To join a cluster, an Elasticsearch
node must be reachable via transport communication. To join a cluster via a
non-loopback address, a node must bind transport to a non-loopback address and
not be using single-node discovery. Thus, we consider
an Elasticsearch node to be in development mode if it can not form a cluster
with another machine via a non-loopback address, and is otherwise in production
mode if it can join a cluster via non-loopback addresses.

Note that HTTP and transport can be configured independently via
http.host and transport.host; this
can be useful for configuring a single node to be reachable via HTTP for testing
purposes without triggering production mode.

Single-node discoveryedit

We recognize that some users need to bind the transport to an external
interface for testing a remote-cluster configuration. For this situation, we
provide the discovery type single-node (configure it by setting
discovery.type to single-node); in this situation, a node will elect itself
master and will not join a cluster with any other node.

Forcing the bootstrap checksedit

If you are running a single node in production, it is possible to evade the
bootstrap checks (either by not binding transport to an external interface, or
by binding transport to an external interface and setting the discovery type to
single-node). For this situation, you can force execution of the bootstrap
checks by setting the system property es.enforce.bootstrap.checks to true
in the JVM options. We strongly encourage you to do
this if you are in this specific situation. This system property can be used to
force execution of the bootstrap checks independent of the node configuration.

Overview

Elasticsearch has many settings that can cause significant performance problems if not set correctly. To prevent this happening, Elasticsearch carries out “bootstrap checks” to ensure that these important settings have been covered. If any of the checks fail, Elasticsearch will write an error to the logs and will not start. In this guide we cover common bootstrap checks you should know and how to configure your settings correctly to pass the checks successfully.

Bootstrap checks are carried out when the network.host setting in:

network.host: 0.0.0.0

If network host is not set and you use the default localhost, then Elasticsearch will consider the node to be in development mode, and bootstrap checks will not be enforced.

Common issues with bootstrap checks

If you install elasticsearch using RPM or Debian packages (strongly recommended) then most of the important configuration is already done for you, and the only bootstrap checks you are likely to run up against are the following.

Heap size check

The minimum and maximum heap sizes specified in jvm.options (or via environment variables) must be equal to one another.

File descriptors check

Minimum file descriptors must have been set to at least 65535

Memory lock check

There are various methods used to prevent memory swapping, and you must use one of them.  The most common is to set in elasticsearch.yml

bootstrap.memory_lock: true

For this to be effective you must give permission to elasticsearch to enable this. There are various ways to do so, depending upon your operating system.

Discovery configuration checks

At least one of the following properties must be configured in elasticsearch.yml to ensure that your node can form a cluster properly:

  • discovery.seed_hosts
  • discovery.seed_providers
  • cluster.initial_master_nodes

Less common bootstrap check issues

If you are not using RPM or debian packages, you may come across the following issues:

Max number of threads check

You must allow your system to create at least 4096 threads. In linux this is done by editing /etc/security/limits.conf and adjusting the nproc setting.

Max file size check

Your system should be able to create unlimited file sizes. In linux this is done by editing /etc/security/limits.conf and adjusting the fsize setting

Max virtual memory check

The system should be able to create unlimited virtual memory for the elasticsearch user.

This is done by editing /etc/security/limits.conf 
<user> - as unlimited

Max map count check

The system must be able to use mmap effectively.  This is done by running the command 

sysctl vm.max_map_count 262144

Other checks

The following checks are also carried out, but are rarely found:

OsX File Descriptor Check
Client Jvm Check
UseS erial GC Check
System Call Filter Check
Might Fork Check
On Error Check
On Out Of Memory Error Check
Early Access Check
G1GC Check
All Permission Check

ElasticSearch Bootstrap check failure

Upgrading ElasticSearch can be quite challenging(at least for me it was). I talked about some other issues I had while upgrading before. Let’s add another one to the list…

One of the ways how ElasticSearch helps you to do the right things is to do some bootstrap checks. These bootstrap checks inspect a variety of Elasticsearch and system settings and compare them to values that are safe for the operation of Elasticsearch. If Elasticsearch is in development mode, any bootstrap checks that fail appear as warnings in the Elasticsearch log. If Elasticsearch is in production mode, any bootstrap checks that fail will cause Elasticsearch to refuse to start.

In this case the bootstrap checks returned the following errors:

[2022-05-09T09:53:42,647][ERROR][o.e.b.Bootstrap          ] [SERVER1] node validation exception

[2] bootstrap checks failed. You must address the points described in the following [2] lines before starting Elasticsearch.

bootstrap check failure [1] of [2]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured

bootstrap check failure [2] of [2]: Transport SSL must be enabled if security is enabled. Please set [xpack.security.transport.ssl.enabled] to [true] or disable security by setting [xpack.security.enabled] to [false]

[2022-05-09T09:53:42,651][INFO ][o.e.n.Node               ] [SERVER1] stopping …

[2022-05-09T09:53:42,723][INFO ][o.e.n.Node               ] [SERVER1] stopped

[2022-05-09T09:53:42,724][INFO ][o.e.n.Node               ] [SERVER1] closing …

[2022-05-09T09:53:42,736][INFO ][o.e.n.Node               ] [SERVER1] closed

This was a local development cluster with only one node where I didn’t want to add security. So I fixed the bootstrap check errors by updating my elasticsearch.yml to the following:

Cover image for Failing bootstrap checks in Elasticsearch

Opster

Elasticsearch has many settings that can cause significant performance problems if not set correctly. To prevent this from happening, Elasticsearch carries out «bootstrap checks» to ensure that these important settings have been covered. If any of the checks fail, Elasticsearch will write an error to the logs and will not start.

Here’s a guide with common bootstrap checks you should know and how to configure your settings correctly to pass the checks successfully. You can read the guide here: https://opster.com/elasticsearch-glossary/elasticsearch-bootstrap-checks/

The Complete Guide to Full Stack Web3 Development

The most important tools, protocols, and frameworks for building full stack web3 apps, and most importantly — how to put everything together to lay the groundwork for building out any of your own ideas in the future.

2.3.0:

OpenJDK 64-Bit Server VM (build 9-internal+0-2016-04-14-195246.buildd.src, mixed mode):

Ubuntu 16.04 x64:

Elasticsearch fails to start:

I installed java9, elasticsearch 2.3.0 under non-root (elasticserch) user.
I gave the user sudo privileges

When I try to access elasticsearch I get

 curl localhost:9200/_cat/aliases

curl: (7) Failed to connect to localhost port 9200: Connection refused

This is what I see in the /var/log/elasticsearch/elasticsearch.log

[2016-06-07 03:00:26,614][WARN ][env ] [Ape-X] max file descriptors [65535] for elasticsearch process likely too low, consider increasing to at least [65536] [2016-06-07 03:00:26,663][ERROR][bootstrap ] Exception java.lang.Error: java.security.AccessControlException: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks") at com.twitter.jsr166e.Striped64.<clinit>(Striped64.java:319) at org.elasticsearch.common.metrics.CounterMetric.<init>(CounterMetric.java:28) at org.elasticsearch.common.util.concurrent.EsAbortPolicy.<init>(EsAbortPolicy.java:30) at org.elasticsearch.common.util.concurrent.EsExecutors.newFixed(EsExecutors.java:80) at org.elasticsearch.threadpool.ThreadPool.rebuild(ThreadPool.java:482) at org.elasticsearch.threadpool.ThreadPool.build(ThreadPool.java:400) at org.elasticsearch.threadpool.ThreadPool.<init>(ThreadPool.java:232) at org.elasticsearch.node.Node.<init>(Node.java:170) at org.elasticsearch.node.Node.<init>(Node.java:140) at org.elasticsearch.node.NodeBuilder.build(NodeBuilder.java:143) at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:178) at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:270) at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:35) Caused by: java.security.AccessControlException: access denied ("java.lang.reflect.ReflectPermission" "suppressAccessChecks") at java.security.AccessControlContext.checkPermission(java.base@9-internal/AccessControlContext.java:468) at java.security.AccessController.checkPermission(java.base@9-internal/AccessController.java:894) at java.lang.SecurityManager.checkPermission(java.base@9-internal/SecurityManager.java:541) at java.lang.reflect.AccessibleObject.checkPermission(java.base@9-internal/AccessibleObject.java:74) at java.lang.reflect.Field.setAccessible(java.base@9-internal/Field.java:163) at com.twitter.jsr166e.Striped64$1.run(Striped64.java:340) at com.twitter.jsr166e.Striped64$1.run(Striped64.java:336) at java.security.AccessController.doPrivileged(java.base@9-internal/Native Method) at com.twitter.jsr166e.Striped64.getUnsafe(Striped64.java:335) at com.twitter.jsr166e.Striped64.<clinit>(Striped64.java:312) ... 12 more

I googled this issue, but could not find the fix. Could you give me some clue on how to fix it please?

Предисловие

Собственно, из-за чего я все это затеял? На одном проекте был написан свой поиск на базе SQL с фильтрами и прочей лабудой. И пока было мало записей в БД все работало отлично, но в один прекрасный день мы сделали выгрузку в БД на 100000 уникальных записей, и что-то резко пошло не так… Запрос на выборку выполнялся вместо 0,01сек аж 15сек, естественно это не дело. Первое что сделали как временное решение проблемы, перекинули сервер на более мощное железо, и этим мы немного улучшили свое положение. Теперь время запроса было 0,5сек. Тоже так себе, но появилось время на подумать. И пошел мыслительный процесс… Решили использовать поисковой движок, и выбор был между ElasticSearch (Далее ES) и Sphinx. Наш выбор пал на ES из-за его простоты в масштабируемости в будущем.

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

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

Установка ES на сервер

Сразу скажу что для ES нужно мощное железо, тк он работает на JAVA и поднимает свой виртуальный сервер.

Требования к железу

минимальные

рекомендуемые

CPU

2

4+

Memory

6 Gb

8+ Gb

Disk

10 Gb

10+ Gb

Я использовал для теста всего этого чуда бесплатные сервера Ampere от Oracle (4core 24ram 45rom).

Итак начнем с установки. Я использовал образ Ubuntu 20.04 так что буду описывать процесс основываясь на нем.

Копируем себе публичный ключ репозитория:

# wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

Если у вас нет пакета apt-transport-https, то надо установить:

# apt install apt-transport-https

Добавляем репозиторий Elasticsearch в систему:

# echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list

Устанавливаем Elasticsearch :

# apt update && apt install elasticsearch

После установки добавляем elasticsearch в автозагрузку и запускаем.

# systemctl daemon-reload 
# systemctl enable elasticsearch.service 
# systemctl start elasticsearch.service

Проверяем, запустился ли он:

# systemctl status elasticsearch.service

Проверим теперь, что elasticsearch действительно нормально работает. Выполним к нему простой запрос о его статусе.

# curl 127.0.0.1:9200
{
  "name" : "ubuntu10",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "zsYgZQSeY6uvhWCkFJPiAA",
  "version" : {
    "number" : "7.15.1",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "8ced7813d6f16d2ef30792e2fcde3e755795ee04",
    "build_date" : "2021-10-07T21:56:19.031608185Z",
    "build_snapshot" : false,
    "lucene_version" : "8.9.0",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}

Если все в порядке, то переходим к настройке Elasticsearch.

Настройка Elasticsearch

Настройки Elasticsearch находятся в файле /etc/elasticsearch/elasticsearch.yml. На начальном этапе нас будут интересовать следующие параметры:

path.data: /var/lib/elasticsearch # директория для хранения данных
network.host: 127.0.0.1 # слушаем только локальный интерфейс

По умолчанию Elasticsearch слушает localhost. Нам это и нужно, так как данные в него будет передавать logstash, который будет установлен локально. Обращаю отдельное внимание на параметр для директории с данными. Чаще всего они будут занимать значительное место, иначе зачем нам Elasticsearch :) Подумайте заранее, где вы будете хранить логи. Все остальные настройки я оставляю дефолтными. После изменения настроек, надо перезапустить службу:

# systemctl restart elasticsearch.service

Смотрим, что получилось:

# netstat -tulnp | grep 9200
tcp6       0      0 127.0.0.1:9200          :::*                    LISTEN      19788/java

Elasticsearch повис на локальном интерфейсе. Причем я вижу, что он слушает ipv6, а про ipv4 ни слова. Но его он тоже слушает, так что все в порядке. Переходим к установке Kibana. Если вы хотите, чтобы elasticsearch слушал все сетевые интерфейсы, настройте параметр:

network.host: 0.0.0.0

Только не спешите сразу же запускать службу. Если запустите, получите ошибку

Чтобы ее избежать, дополнительно надо добавить еще один параметр:

discovery.seed_hosts: ["127.0.0.1", "[::1]"]

Этим мы указываем, что хосты кластера следует искать только локально.

Итоговый вид файла конфига

# Имя нашего кластера 
cluster.name: cluster-app
# имя нашей ноды 
node.name: node-1
# путь к фалам 
path.data: /var/lib/elasticsearch
# путь к логам 
path.logs: /var/log/elasticsearch
# интерфейс который слушает ES
network.host: 0.0.0.0
discovery.seed_hosts: ["127.0.0.1", "[::1]"]

Установка Kibana

Дальше устанавливаем web панель Kibana для визуализации данных, полученных из Elasticsearch. Можно и без нее , но с ней удобнее, по крайней мере мне))

Подключаем репозиторий и ставим из deb пакета. Добавляем публичный ключ:

# wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add -

Добавляем рпозиторий Kibana:

# echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | tee -a /etc/apt/sources.list.d/elastic-7.x.list

Запускаем установку Kibana:

# apt update && apt install kibana

Добавляем Кибана в автозагрузку и запускаем:

# systemctl daemon-reload
# systemctl enable kibana.service
# systemctl start kibana.service

Проверяем состояние запущенного сервиса:

# systemctl status kibana.service

По умолчанию, Kibana слушает порт 5601. Только не спешите его проверять после запуска. Кибана стартует долго. Подождите примерно минуту и проверяйте.

# netstat -tulnp | grep 5601
tcp        0      0 127.0.0.1:5601          0.0.0.0:*               LISTEN      1487/node

Настройка Kibana

Файл с настройками Кибана располагается по пути — /etc/kibana/kibana.yml. На начальном этапе можно вообще ничего не трогать и оставить все как есть. По умолчанию Kibana слушает только localhost и не позволяет подключаться удаленно. Это нормальная ситуация, если у вас будет на этом же сервере установлен nginx в качестве reverse proxy, который будет принимать подключения и проксировать их в Кибана. Так и нужно делать в production, когда системой будут пользоваться разные люди из разных мест. С помощью nginx можно будет разграничивать доступ, использовать сертификат, настраивать нормальное доменное имя и т.д. Если же у вас это тестовая установка, то можно обойтись без nginx. Для этого надо разрешить Кибана слушать внешний интерфейс и принимать подключения. Измените параметр server.host, указав ip адрес сервера, например вот так:

server.host: "10.20.1.23"

Если хотите, чтобы она слушала все интерфейсы, укажите в качестве адреса 0.0.0.0. После этого Kibana надо перезапустить:

# systemctl restart kibana.service

Теперь можно зайти в веб интерфейс по адресу http://10.20.1.23:5601.

Периодически вы можете видеть в веб интерфейсе предупреждение:

server.publicBaseUrl is missing and should be configured when running in a production environment. Some features may not behave correctly.

Чтобы его не было, просто добавьте в конфиг Kibana параметр:

server.publicBaseUrl: "http://10.20.1.23:5601/"

Или доменное имя, если используете его. 

Установка и настройка Logstash

Logstash устанавливается так же просто, как Elasticsearch и Kibana, из того же репозитория. Не буду еще раз показывать, как его добавить. Просто установим его и добавим в автозагрузку.

Установка Logstash:

# apt install logstash

Добавляем logstash в автозагрузку:

# systemctl enable logstash.service

Запускать пока не будем, надо его сначала настроить. Основной конфиг logstash лежит по адресу /etc/logstash/logstash.yml. Я его не трогаю, а все настройки буду по смыслу разделять по разным конфигурационным файлам в директории /etc/logstash/conf.d. Создаем первый конфиг input.conf, который будет описывать прием информации с beats агентов.

input {
  beats {
    port => 5044
  }
}

Тут все просто. Указываю, что принимаем информацию на 5044 порт. Этого достаточно. Если вы хотите использовать ssl сертификаты для передачи логов по защищенным соединениям, здесь добавляются параметры ssl. Я буду собирать данные из закрытого периметра локальной сети, у меня нет необходимости использовать ssl. Теперь укажем, куда будем передавать данные. Тут тоже все относительно просто. Рисуем конфиг output.conf, который описывает передачу данных в Elasticsearch.

output {
        elasticsearch {
            hosts    => "localhost:9200"
            index    => "nginx-%{+YYYY.MM.dd}"
        }
    #stdout { codec => rubydebug }
}

Что мы настроили? Передавать все данные в elasticsearch под указанным индексом с маской в виде даты. Разбивка индексов по дням и по типам данных удобна с точки зрения управления данными. Потом легко будет выполнять очистку данных по этим индексам. Я закомментировал последнюю строку. Она отвечает за логирование. Если ее включить, то все поступающие данные logstash будет отправлять дополнительно в системный лог. В centos это /var/log/messages. Используйте только во время отладки, иначе лог быстро разрастется дублями поступающих данных. Остается последний конфиг с описанием обработки данных. Тут начинается небольшая уличная магия, в которой я разбирался некоторое время. Расскажу ниже. Рисуем конфиг filter.conf.

filter {
 if [type] == "nginx_access" {
    grok {
        match => { "message" => "%{IPORHOST:remote_ip} - %{DATA:user} [%{HTTPDATE:access_time}] "%{WORD:http_method} %{DATA:url} HTTP/%{NUMBER:http_version}" %{NUMBER:response_code} %{NUMBER:body_sent_bytes} "%{DATA:referrer}" "%{DATA:agent}"" }
    }
  }
  date {
        match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ]
  }
  geoip {
         source => "remote_ip"
         target => "geoip"
         add_tag => [ "nginx-geoip" ]
  }
}

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

Модули filebeat работают только в том случае, если вы отправляете данные напрямую в Elasticsearch. На него вы тоже ставите соответствующий плагин и получаете отформатированные данные с помощью elastic ingest. Но у нас работает промежуточное звено Logstash, который принимает данные. С ним плагины filebeat не работают, поэтому приходится отдельно в logstash парсить данные. Это не очень сложно, но тем не менее. Как я понимаю, это плата за удобства, которые дает logstash. Если у вас много разрозненных данных, то отправлять их напрямую в Elasticsearch не так удобно, как с использованием предобработки в Logstash.

Для фильтра grok, который использует Logstash, есть удобный дебаггер, где можно посмотреть, как будут парситься ваши данные. Покажу на примере одной строки из конфига nginx. Например, возьмем такую строку из лога:

180.163.220.100 - travvels.ru [05/Sep/2021:14:45:52 +0300] "GET /assets/galleries/26/1.png HTTP/1.1" 304 0 "https://travvels.ru/ru/glavnaya/" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"

И посмотрим, как ее распарсит правило grok, которое я использовал в конфиге выше.

%{IPORHOST:remote_ip} - %{DATA:user} [%{HTTPDATE:access_time}] "%{WORD:http_method} %{DATA:url} HTTP/%{NUMBER:http_version}" %{NUMBER:response_code} %{NUMBER:body_sent_bytes} "%{DATA:referrer}" "%{DATA:agent}"

Собственно, результат вы можете сами увидеть в дебаггере. Фильтр распарсит лог и на выходе сформирует json, где каждому значению будет присвоено свое поле, по которому потом удобно будет в Kibana строить отчеты и делать выборки. Только не забывайте про формат логов. Приведенное мной правило соответствует дефолтному формату main логов в nginx. Если вы каким-то образом модифицировали формат логов, внесите изменения в grok фильтр. Надеюсь понятно объяснил работу этого фильтра. Вы можете таким образом парсить любые логи и передавать их в еластикс. Потом на основе этих данных строить отчеты, графики, дашборды.

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

В конце я использую geoip фильтр, который на основе ip адреса, который мы получили ранее с помощью фильтра grok и записали в поле remote_ip, определяет географическое расположение. Он добавляет новые метки и записывает туда географические данные. Для его работы используется база данных из файла /usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-filter-geoip-6.0.3-java/vendor/GeoLite2-City.mmdb. Она будет установлена вместе с logstash. Впоследствии вы скорее всего захотите ее обновлять. Раньше она была доступна по прямой ссылке, но с 30-го декабря 2019 года правила изменились. База по-прежнему доступна бесплатно, но для загрузки нужна регистрация на сайте сервиса. Регистрируемся и качаем отсюда — https://dev.maxmind.com/geoip/geoip2/geolite2/#Download_Access. Передаем на сервер, распаковываем и копируем в /etc/logstash файл GeoLite2-City.mmdb. Теперь нам нужно в настройках модуля geoip указать путь к файлу с базой. Добавляем в /etc/logstash/conf.d/filter.conf:

geoip {
 database => "/etc/logstash/GeoLite2-City.mmdb"
 source => "remote_ip"
 target => "geoip"
 add_tag => [ "nginx-geoip" ]
}

Закончили настройку logstash. Запускаем его:

# systemctl start logstash.service

Можете проверить на всякий случай лог /var/log/logstash/logstash-plain.log, чтобы убедиться в том, что все в порядке. Признаком того, что скачанная geoip база успешно добавлена будет вот эта строчка в логе:

[2021-10-18T12:52:07,118][INFO ][logstash.filters.geoip   ][main] Using geoip database {:path=>"/etc/logstash/GeoLite2-City.mmdb"}

Теперь настроим агенты для отправки данных.

Установка Filebeat для отправки логов в Logstash

Установим первого агента Filebeat на сервер с nginx для отправки логов веб сервера на сервер с ELK. Ставить можно как из общего репозитория, который мы подключали ранее, так и по отдельности пакеты. Как ставить — решать вам. В первом случае придется на все хосты добавлять репозиторий, но зато потом удобно обновлять пакеты. Если подключать репозиторий не хочется, можно просто скачать пакет и установить его.

Можно ставить так:

# curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-7.15.1-amd64.deb
# dpkg -i filebeat-7.15.1-amd64.deb

Или просто:

# yum install filebeat
# apt install filebeat

После установки рисуем примерно такой конфиг /etc/filebeat/filebeat.yml для отправки логов в logstash.

filebeat.inputs:
- type: log
  enabled: true
  paths:
      - /var/log/nginx/*-access.log
  fields:
    type: nginx_access
  fields_under_root: true
  scan_frequency: 5s


type: log
enabled: true
paths:- /var/log/nginx/*-error.log

fields:
  type: nginx_error
fields_under_root: true
scan_frequency: 5s

output.logstash:
  hosts: ["10.1.4.114:5044"]
xpack.monitoring:
  enabled: true
  elasticsearch:
    hosts: ["http://10.1.4.114:9200"]

Некоторые пояснения к конфигу, так как он не совсем дефолтный и минималистичный. Я его немного модифицировал для удобства. Во-первых, я разделил логи access и error с помощью отдельного поля type, куда записываю соответствующий тип лога: nginx_access или nginx_error. В зависимости от типа меняются правила обработки в logstash. Плюс, я включил мониторинг и для этого указал адрес elastichsearch, куда filebeat передает данные мониторинга напрямую. Показываю это для вас просто с целью продемонстрировать возможность. У меня везде отдельно работает мониторинг на zabbix, так что большого смысла в отдельном мониторинге нет. Но вы посмотрите на него, возможно вам он пригодится. Чтобы мониторинг работал, его надо активировать в соответствующем разделе в Management — Stack Monitoring.

И не забудьте запустить elasticsearch на внешнем интерфейсе. В первоначальной настройке я указал слушать только локальный интерфейс. Запускаем filebeat и добавляем в автозагрузку.

# systemctl start filebeat
systemctl enable filebeat

Проверяйте логи filebeat в дефолтном системном логе. По умолчанию, он все пишет туда. Лог весьма информативен. Если все в порядке, увидите список всех логов в директории /var/log/nginx, которые нашел filebeat и начал готовить к отправке. Если все сделали правильно, то данные уже потекли в elasticsearch. Мы их можем посмотреть в Kibana. Для этого открываем web интерфейс и переходим в раздел Discover. Так как там еще нет индекса, нас перенаправит в раздел Managemet, где мы сможем его добавить.

Вы должны увидеть индекс, который начал заливать logstash в elasticsearch. В поле Index pattern введите nginx-* . Выберите имя поля для временного фильтра. У вас будет только один вариант — @timestamp, выбирайте его и жмите Create Index Pattern.

Новый индекс добавлен. Теперь при переходе в раздел Discover, он будет открываться по умолчанию со всеми данными, которые в него поступают.

Получение логов с веб сервера nginx на linux настроили. Подобным образом настраивается сбор и анализ любых логов. Можно либо самим писать фильтры для парсинга с помощью grok, либо брать готовые.

Настройка безопасности и авторизация в Kibana

Во время предыдущих настроек вы могли заметить информационные сообщения в веб интерфейсе, которые постоянно выскакивали. Текст их следующий:

Warning: 299 Elasticsearch-7.15.1-83c34f456ae29d60e94d886e455e6a3409bba9ed «Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.15/security-minimal-setup.html to enable security.»

Нас предупреждают, что в настоящий момент аутентификация не настроена, поэтому доступ к информации может получить любой желающий. Если для вас это не проблема и вы изолировали доступ к данным, к примеру, на уровне firewall, можете игнорировать эти сообщения. Далее я расскажу, как избавиться от этого предупреждения и настроить доступ к поиску elastic, а также информации в Kibana с помощью авторизации по пользователю и паролю. 

Открываем конфиг кластера в файле elasticsearch.yml и добавляем туда параметр:

xpack.security.enabled: true

Перезапускаем службу elasticsearch:

# systemctl restart elasticsearch

Если вы ранее не настраивали работу кластера по ssl, то скорее всего получите ошибку:

[ERROR][o.e.b.Bootstrap          ] [centos8] node validation exception
[1] bootstrap checks failed. You must address the points described in the following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: Transport SSL must be enabled if security is enabled on a [basic] license. Please set [xpack.security.transport.ssl.enabled] to [true] or disable security by setting [xpack.security.enabled] to [false]

Для того, чтобы настройки xpack.security заработали, добавляем еще один параметр:

xpack.security.transport.ssl.enabled: true

Запускаем elasticsearch еще раз. Теперь он должен запуститься, но доступа к нему ни у кого не будет. Kibana будет показывать ошибку:

{"statusCode":503,"error":"Service Unavailable","message":"License is not available."}

Нам нужно подготовить учётные данные, которые будем использовать для доступа к elasticsearch. Для этого запускаем утилиту elasticsearch-setup-passwords. По умолчанию она находится в папке /usr/share/elasticsearch/bin.

# /usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto

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

Настраиваем парольный доступ к кластеру для Kibana, используя сгенерированный только что пароль. Для этого добавляем в конфиг kibana.yml параметры:

xpack.security.enabled: true 
elasticsearch.username: "kibana_system"
elasticsearch.password: "JArsJZj10YC8LlPlQr4u"

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

Мы настроили доступ в Kibana по паролю. Управялть пользователями и ролями можно через веб интерфейс. Делается это в разделе Stack Management -> Users. Там можно как отредактировать встроенные учетные записи, так и добавить новые. 

Сделаем это на примере пользователя для Logstash. Создадим отдельного юзера с правами на запись в нужные нам индексы. Для этого сначала создадим роль с соответствующими правами. Переходим в Roles и добавляем новую.

Набор индексов и права доступа к ним вы можете выбрать те, что вам нужны. Можно разделить доступ: одни могут только писать данные, другие удалять и т.д. После создания роли, добавьте пользователя и добавьте ему созданную ранее роль. 

Сразу можем создать пользователей и для Yii и Mysql чтоб по 5 раз не ходить. Только я не знаю почему, но им нужно задать роль суперюзера , по другому у меня не завелось, но вы можете попробовать создать свои роли и попробовать использовать их.

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

[ERROR][logstash.outputs.elasticsearch][main][f8cdb7a9c640d0ed412a776071b8530fd5c0011075712a1979bee6c58b4c1d9f] Encountered a retryable error (will retry with exponential backoff) {:code=>401, :url=>"http://localhost:9200/_bulk", :content_length=>2862}

Открываем конфиг logstash, отвечающий за output и добавляем туда учетные данные для доступа в кластер. Выглядеть это будет примерно так:

output {
        elasticsearch {
            user     => "logstash_nginx_rw"
            password => "gdhsgfadsfsdfgsfdget45t"
            hosts    => "localhost:9200"
            index    => "nginx-%{+YYYY.MM.dd}"
        }
}

После этого данные как и прежде начнут поступать из logstash в elasticsearch, только теперь уже с авторизацией по пользователю и паролю.

Автоматическая очистка индексов в ES

Kibana есть встроенный инструмент для очистки данных — Index Lifecycle Policies. Его не трудно настроить самостоятельно, хотя и не могу сказать, что там всё очевидно. Есть некоторые нюансы, так что я по шагам расскажу, как это сделать. Для примера возьму всё тот же индекс nginx-, который использовал ранее в статье.

Настроим срок жизни индексов следующим образом:

  1. Первые 30 дней — Hot phase. В этом режиме индексы активны, в них пишутся новые данные. 

  2. После 30-ти дней — Cold phase. В этой фазе в индексы невозможна запись новых данных. Запросы к этим данным имеют низкий приоритет. 

  3. Все, что старше 90 дней удаляется.

Чтобы реализовать эту схему хранения данных, идем в раздел Stack Management -> Index Lifecycle Management и добавляем новую политику. Я её назвал Nginx_logs. Выставляем параметры фаз в соответствии с заданными требованиями. 

Не уместилось полное изображение настроек, но, думаю, вы там сами разберётесь, что выбрать. Ничего сложного тут нет. Далее нам нужно назначить новую политику хранения данных к индексам. Для этого переходим в Index Management -> Index Templates и добавляем новый индекс. В качестве шаблона укажите nginx-, все остальные параметры можно оставить дефолтными. 

Теперь возвращаемся в Index Lifecycle Policies, напротив нашей политики нажимаем на + и выбираем только что созданный шаблон. 

Проверяем свойства шаблона и убеждаемся в том, что Lifecycle Policies применилась. 

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

Такими несложными действиями можно настроить автоматическую очистку индексов встроенными инструментами Elasticsearch и Kibana. В некоторых случаях быстрее и удобнее воспользоваться Curator, особенно если нужно быстро реализовать много разных схем. Единый конфиг куратора выглядит более наглядным, но это уже вкусовщина и от ситуации зависит. 

Подключение к Mysql и настройка автоматического индексирования.

Зачем это нужно, в моем случае весь бэк заточен на MySql и контачит с ним , и мне надо постоянно актуализировать данные в ES согласно SQL. Если у вас статичные данные или вы решите хранить все данные в ES без SQL, то можно пропустить этот шаг.

Покажу как все сделать на примере Mysql для других видов БД все также только в конфиге меняем Mysql на название вашего движка.

Итак идем в папку «/usr/share/logstash» и создаем новый файл logstash-db.conf с содержанием :

input { 
    jdbc { 
    # путь к драйверу БД "гуглится за 2 минуты запросом "
    jdbc_driver_library => "/etc/logstash/conf.d/mysql-connector-java-8.0.27.jar" 
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://localhost/my_test_db"
    # лог и пароль к БД
    jdbc_user => "root" 
    jdbc_password => "admin" 
 		# Можно настроить расписание выполнения индексирования, но у меня опять же хз почему оно не завелось .
    # Я сделал обычную CRON функцию.
    # schedule => "* * * * *" 
    # Наш SQL запрос к БД, как видим может быть абсалютно любым.
    statement => "SELECT s.* , ST_AsText(s.geo) as geo ,st.`name` AS type_name ,
                        CONCAT(' ', group_concat(DISTINCT benefits.name SEPARATOR ' ')  ,' ') as concat_bn,
                        st.alias as spot_type_alias, benefits.alias as benefit_alias,
                        group_concat(DISTINCT benefits.id SEPARATOR ' ') as concat_bn,
                        countries.name as country
                        FROM `spots` s
                        JOIN `spot_type` st ON s.id_spot_type = st.id
                        left join spots_benefits
                         on spots_benefits.spot = s.id
                        left join benefits
                         on benefits.id = spots_benefits.benefit
                         left join countries
                         on s.id_country = countries.id
                         where category = 1
                          group by s.id
                          "
    } 
} 
output { 
    elasticsearch { 
    # название индекса в ES 
        index => "spots" 
        document_type => "spots" 
        document_id => "%{id}"
        # путь к хосту ES и лог и пароль те что мы ранее создали в kibana
        hosts => "localhost:9200"
        user     => "db"
        password => "MascasdaehaefwP"
        }
}

Все вроде настроили, можно запустить индексацию командой:

sudo /usr/share/logstash/bin/logstash -f  /usr/share/logstash/logstash-db.conf

Можете сразу создать крон функцию и настроить необходимый интервал обновления, у меня индексация 100000 полей sql занимала порядком 5-10сек.

Настройка и работа с ES в Yii2

И так перейдем к настройке в Yii

Для начала установим плагин «Elasticsearch Query and ActiveRecord for Yii 2»

composer require --prefer-dist yiisoft/yii2-elasticsearch:"~2.1.0"

Далее в backend/config/main.php в поле «components» бэка добавим следующее

'elasticsearch' => [
            'class' => 'yiielasticsearchConnection',
            # адрес нашей ноды
            'nodes' => [
                ['http_address' => '127.0.0.1:9200', ],
                // configure more hosts if you have a cluster
            ],
            # данные для входа что мы создали ранее 
            'auth' => ['username' => 'yiiuser', 'password' => 'MascasdasdwP8NGa3hfnn'],
            'dslVersion' => 7, // default is 5
        ],

Теперь можно создать модель для нашего ES

<?php

namespace commonmodels;

use yiielasticsearchActiveRecord;

class ElasticObj extends ActiveRecord
{
    public static function index()
    {
    # имя нашего индеса в ES
        return 'spots';
    }

		# мапинг индекса лучше заполнить чтобы потом проблем было меньше 
    # подробнее об этом будет в ссылках ниже
    public static function mapping()
    {
        return [
            'properties' => [
                'name'      => ['type' => 'text'],
                //.....
            ]
        ];
    }

    #Атрибуты. Важно указать. Иначе, данные не сохранятся, и если в БД и индексе 
    # есть поле условно type и вы его тут не укажите , то на выдачу оно вам не вернется 
    # те проще говоря это те поля что вы сохраните и что будут видны после запроса 
    public function attributes()
    {
        return [
            "id",
            "name",
            //....
            ];
    }

    
    #Правила. Важно указать. Иначе, данные не сохранятся.
    #Я, поставил всем атрибутам правила как безопасные.
    #В можете указать любые другие, которые вам необходимы.
     
    public function rules()
    {
        return [
            [$this->attributes(), 'safe']
        ];
    }
}

Теперь попробуем провзаимодействовать с данными.

Создание:

$model = new ElasticObj();
$model->attributes = [  
    "name" => "test",
];
$model->save();

Получаем данные по определенному Id:

$model = ElasticObj::get(1)

Ищем все данные:

$model = ElasticObj::find()->all();

Поиск по параметрам:

$params = [    
	'match' => [        
    	'last_name' => 'Smith'    
    ]
  ];
$model = ElasticObj::find()->query($params)->all();

Фильтры:

$params = [
    'filtered' => [
        'filter' => [
            'range' => [ // - диапазонный фильтр
                'age' => [
                    'gt'=> 20 // - ищем старше 20 лет (параметр - gt)
                ]
            ]
        ],
        'query'  => [
            'match' => [
                'last_name' => 'smith'
            ]
         ],
       ],
];
$model = ElasticObj::find()->query($params)->all();

Полнотекстовый поиск по всем полям:

 $params = [
                "query_string" => [
                    "query"=> 'test'
                ],
            ];
$model = ElasticObj::find()->query($params)->all();

Добавление обязательных вхождений в выдачу:

 $params['bool']['must'][]['match']['name'] = 'test';
 $model = ElasticObj::find()->query($params)->all();

параметры bool можно задать необязательными или исключить какие-то данные из выдачи:

$params = [
        'bool' => [
            'must' => [
                'match' => ['name' => 'test']
            ],
            'should' => [
                            'match' => ['name' => 'not test'],
                        ],
            'must_not' => [
                'match' => [ 'name' => 'one']
            ]
        ]
    ]

Можно обеденить несколько фильтров :

 $params['bool']['must'][] = [
                "query_string" => [
                    "query"=> 'test'
                ],
            ];
 $params['bool']['must'][] =
                [
                    'range' => [
                        'age' => [
                            'gt'=> 20
                        ]
                    ]
                ];
$model = ElasticObj::find()->query($params)->all();

и все в этом духе.

Для более углубленного понимания происходящего и построения более сложных запросов советую почитать

офф дока

на русском

Заключение

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

А так в общем хочу сказать что технология очень интересная и быстрая, но капец какая прожорливая по ресурсам. И использовать ее нужно только с очень жирными проектами, если у вас нет огромной БД и/или в будущем ее не предвидится, то смысла от ES нету , лучше посмотрите в сторону Sphinx или вообще сделайте свою реализацию на базе Sql благо в последних версиях завезли поддержку полнотекстового поиска.

Что почитать дополнительно

Инфа по ES на русском , очень хорошо написано, для общего понимания происходящего отлично подойдет.

Базовые запросы из PHP и Yii

Дока по плагину ES для Yii (есть на русском)

Дока по query DSL на русском

Источники

Инфа по установке взята тут

Понравилась статья? Поделить с друзьями:
  • El apartamento tiene terraza где ошибка
  • Ejudge ошибка выполнения
  • Ejudge marking error фоксфорд
  • Echo mysql error php
  • Echo error code linux