Elasticsearch - это мощный поисковый и аналитический движок. Его используют для логирования, поиска по сайту, аналитики и работы с большими объемами данных.
На VDS с его помощью можно искать логи, индексировать данные за миллисекунды.
На сайте с помощью него можно реализовать качественный поиск по сайту, с автодополнением, пониманием опечаток и пр.
В этой статье разберём установку, базовую настройку и несколько примеров применения (в администрировании сервера и применение в бекенде сайта) Elasticsearch на Ubuntu
Note
Если вы только купили сервер:
Выполните подготовку сервера к работе
Elasticsearch работает на Java.
Проверим, установлена ли Java:
java -version
Если система ответила «command not found», установите OpenJDK:
apt install openjdk-17-jdk -y
Современные версии Elasticsearch ориентированы на эту ветку. С более старыми версиями возможны проблемы совместимости.
После установки снова проверьте:
java -version
Если версия отображается, то всё готово.
Используем официальный репозиторий.
Добавим ключ подписи:
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add -
Затем добавим репозиторий:
echo "deb https://artifacts.elastic.co/packages/8.x/apt stable main" | tee /etc/apt/sources.list.d/elastic-8.x.list
Обновим список пакетов:
apt update
apt install elasticsearch -y
Пакет устанавливается как системный сервис.
Это удобно, он автоматически интегрируется с systemd.
После установки сервис не всегда запускается автоматически. Проверим статус:
systemctl status elasticsearch
Если он не активен, запустите вручную:
systemctl start elasticsearch
И добавьте автозапуск:
systemctl enable elasticsearch
На практике лучше всегда включать автозапуск. После перезагрузки сервера сервис должен подниматься сам.
Основной конфигурационный файл находится здесь:
/etc/elasticsearch/elasticsearch.yml
Откройте его:
nano /etc/elasticsearch/elasticsearch.yml
По умолчанию Elasticsearch слушает только localhost. Это безопасно, но недоступно извне.
Если вы планируете подключаться удалённо, укажите IP сервера:
network.host: 0.0.0.0
Открывать Elasticsearch в интернет без защиты не нужно. Если нужен внешний доступ, обязательно настройте firewall и аутентификацию.
Если сервер используется только локально (например, вместе с Nginx и приложением), лучше оставить localhost.
Выполните
/usr/share/elasticsearch/bin/elasticsearch-reset-password -u elastic
У вас запросят пароль, введите его, потом повторите.
Проверим, отвечает ли сервер:
curl -u elastic:password -v https://127.0.0.1:9200 --insecure
Если всё работает, вы получите JSON-ответ с информацией о версии и имени узла.
Это подтверждает, что сервис слушает порт и готов к работе.
Версию сервера нужно иметь ввиду, это пригодится при установке клиента. Если версии клиента и сервера не будут совместимы, то вы получите ошибку.
Если используется UFW, откройте порт 9200 только при необходимости:
ufw allow 9200
Открытый Elasticsearch это частая цель атак
Если доступ нужен только приложению на том же сервере, то порт открывать не нужно. В нашем случае Elasticsearch используется локально.
Проверить логи можно в директории:
/var/log/elasticsearch/
Или через journalctl:
journalctl -u elasticsearch -f
Например, у вас есть сайт на сервере Ubuntu. Нужно быстро искать ошибки 500, анализировать IP-адреса или смотреть, какие страницы чаще всего вызывают проблемы.
Elasticsearch идеально подходит для этого.
Создадим индекс с простым описанием структуры данных:
curl -X PUT "https://localhost:9200/nginx-logs" \
-u elastic:password \
-H 'Content-Type: application/json' \
-d '{
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"ip": { "type": "ip" },
"method": { "type": "keyword" },
"url": { "type": "text" },
"status": { "type": "integer" }
}
}
}' --insecure
Теперь Elasticsearch знает, какие поля мы будем хранить.
Добавим одну запись, имитирующую строку лога:
curl -X POST "https://localhost:9200/nginx-logs/_doc" \
-u elastic:password \
-H 'Content-Type: application/json' \
-d '{
"timestamp": "2026-02-28T12:00:00",
"ip": "192.168.1.10",
"method": "GET",
"url": "/login",
"status": 500
}' --insecure
Документ мгновенно индексируется. Теперь по нему можно искать.
curl -X GET "https://localhost:9200/nginx-logs/_search" \
-u elastic:password \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"status": 500
}
}
}' --insecure
В ответе вы получите найденные записи.
Даже если таких записей будут миллионы, поиск займёт миллисекунды.
Например, нужно проверить активность конкретного IP:
curl -X GET "https://localhost:9200/nginx-logs/_search" \
-u elastic:password \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"ip": "192.168.1.10"
}
}
}' --insecure
Так можно быстро выявлять подозрительную активность или анализировать поведение пользователей.
Например, приложение на PHP, Node.js или Python может напрямую отправлять JSON-документы в Elasticsearch.
Дальше данные визуализируют через Kibana или используют для построения внутренней аналитики.
Представим, что у вас есть сайт с товарами или статьями. Нужно реализовать быстрый полнотекстовый поиск.
Установим официальный клиент:
pip install elasticsearch==8.19.0
Он позволяет работать с Elasticsearch напрямую через API.
Разберем пример на Python. Тут реализована инициация Elasticsearch в коде, заполнение БД данными (для презентации функционала поиска, если у вас уже есть база с данными, то это делать не нужно), создание индекса и индексация данных и сам поиск по данным.
import random
import string
from datetime import datetime, timedelta
import mysql.connector
from elasticsearch import Elasticsearch, exceptions, helpers
# -------------------------------
# Настройки MySQL
# -------------------------------
DB_CONFIG = {
"host": "localhost",
"user": "example_user",
"password": "password", # ваш пароль
"database": "example_database"
}
# -------------------------------
# Настройки Elasticsearch
# -------------------------------
es = Elasticsearch(
"https://localhost:9200",
basic_auth=("elastic", "password"), # ваш пароль elastic
verify_certs=False
)
index_name = "articles"
# -------------------------------
# Подключение к MySQL
# -------------------------------
conn = mysql.connector.connect(**DB_CONFIG)
cursor = conn.cursor()
# -------------------------------
# Создадим тестовую базу данных, вы можете использовать для поиска свою, если она у вас уже есть
# -------------------------------
cursor.execute("DROP TABLE IF EXISTS articles")
cursor.execute("""
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255),
content TEXT,
category VARCHAR(50),
published_at DATE
)
""")
conn.commit()
categories = ["devops", "web", "data", "security"]
def random_text(words=10):
return " ".join("".join(random.choices(string.ascii_lowercase, k=random.randint(3,10)))
for _ in range(words))
# Добавим 10_000 записей
for _ in range(10000):
title = random_text(5)
content = random_text(20)
category = random.choice(categories)
published_at = datetime.now() - timedelta(days=random.randint(0, 365))
cursor.execute(
"INSERT INTO articles (title, content, category, published_at) VALUES (%s, %s, %s, %s)",
(title, content, category, published_at.date())
)
conn.commit()
print("Добавлено 10 000 записей в MySQL")
# -------------------------------
# Перенос данных из MySQL в Elasticsearch
# -------------------------------
cursor.execute("SELECT title, content, category, published_at FROM articles")
rows = cursor.fetchall()
# -------------------------------
# Создание индекса в Elasticsearch
# -------------------------------
# Создание индекса
try:
if not es.indices.exists(index=index_name):
es.indices.create(
index=index_name,
mappings={
"properties": {
"title": {"type": "text"},
"content": {"type": "text"},
"category": {"type": "keyword"},
"published_at": {"type": "date"}
}
}
)
print(f"Индекс '{index_name}' создан")
else:
print(f"Индекс '{index_name}' уже существует")
except exceptions.BadRequestError as e:
print("Ошибка при создании индекса:", e)
actions = [
{
"_index": index_name,
"_source": {
"title": row[0],
"content": row[1],
"category": row[2],
"published_at": row[3].isoformat()
}
}
for row in rows
]
helpers.bulk(es, actions) # используем bulk API вместо одиночных insert, т.к. у нас 10000 записей
print("Данные загружены в Elasticsearch")
# -------------------------------
# Пример поиска через Elasticsearch
# -------------------------------
def search_es(query_text):
response = es.search(
index=index_name,
body={
"query": {
"multi_match": {
"query": query_text,
"fields": ["title", "content"]
}
}
}
)
for hit in response["hits"]["hits"][:10]: # первые 10 результатов
print(f"Title: {hit['_source']['title']}")
print(f"Category: {hit['_source']['category']}")
print(f"Published: {hit['_source']['published_at']}")
print("-"*40)
# Пример поиска
search_es("abc") # замените на слово, которое хотите искать
После выполнения видим результат поиска по нашим тестовым данным
Это можно подключить к:
SQL отлично подходит для точных выборок. Но для полнотекстового поиска Elasticsearch даёт гораздо более гибкий результат.
1. Не размещайте Elasticsearch на слабых VDS.
1 ГБ RAM - это минимальный порог для тестов, если RAM будет мало, сервис не запустится и не будет работать
2. Следите за диском.
Elasticsearch активно пишет данные. Когда диск заканчивается, кластер блокирует запись.
3. Делайте снапшоты.
4. Не отключайте защиту
Современные версии включают базовую безопасность по умолчанию
5. Несовместимость версии клиента и сервера
Клиент и сервер должны быть совместимы, поэтому нужно проверять версию сервера перед установкой клиента