# NebulaGraph 3.8 + Elasticsearch 7 + Studio ## Быстрый запуск ```bash make verify make es-health make ps ``` Первый `make verify` сам создаёт `.env` из `.env.example`, поднимает контейнеры и проводит проверку. | Команда | Что делает | | --- | --- | | `make verify` | Поднимает стек и проверяет регистрацию storage, вход в Elasticsearch, listener, полнотекстовый индекс и поиск `doc-001`. | | `make es-health` | Показывает состояние кластера Elasticsearch. Ожидается `green` и три узла. | | `make ps` | Печатает статус контейнеров. `es-certs` в `Exited (0)` значит, что сертификат уже создан. | Локальный кластер: | Сервис | Число | Адрес в сети Docker | Порт | | --- | --- | --- | --- | | metad | 3 | `172.30.80.11`–`.13` | 9559 | | storaged | 3 | `172.30.80.21`–`.23` | 9779 | | graphd | 1 | `172.30.80.31` | 9669 | | storaged-listener | 1 | `172.30.80.41` | 9789 | | Elasticsearch 7.17 | 3 | `172.30.80.51`–`.53` | 9200 | | Nebula Studio 3.10 | 1 | имя `studio` | 7001 | С хоста опубликованы только `127.0.0.1:9669` (graphd), `127.0.0.1:9200` (Elasticsearch) и `127.0.0.1:7001` (Studio). Адреса заданы в `.env` и совпадают на macOS, Linux и Windows: контейнеры видят одну сеть `nebula-stack-net`, а не localhost хоста. ## Что нужно - Docker Engine или Docker Desktop и Docker Compose v2 (`docker compose`). - Для `make`: macOS, Linux, либо Windows через WSL или Git Bash. - Память Docker: комфортно от 8 ГБ. В `.env` у каждого узла Elasticsearch куча 512 МБ. - Место на диске под образы (около 3–4 ГБ). На Linux перед первым запуском ядро должно разрешать Elasticsearch много memory map: ```bash sudo sysctl -w vm.max_map_count=262144 echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-elasticsearch.conf sudo sysctl --system ``` На macOS и Windows это настройка виртуальной машины Docker Desktop, обычно уже `262144`. Проверка из любого хоста: ```bash make check ``` Число в ответе должно быть не меньше `262144`. ## Запуск ```bash cp .env.example .env # make up сделает это сам make up make init # ADD HOSTS и SIGN IN TEXT SERVICE make verify # listener, индекс и поиск по тестовым вершинам ``` `make verify` включает `make init`. Контейнер `es-certs` после успеха в `make ps` будет `Exited (0)`: сертификат транспортного TLS уже записан в том. Studio: | Поле | Значение | | --- | --- | | Graphd IP | `172.30.80.31` | | Port | `9669` | | Username | `root` | | Password | `nebula` | Адрес `127.0.0.1` в Studio не подходит: запрос к graphd уходит из контейнера Studio. `172.30.80.31` — адрес graphd в сети Docker. Авторизация NebulaGraph в этом стенде выключена, пароль `nebula` принимает консоль и Studio. Интерактивная консоль: ```bash make console ``` Остановить, не удаляя данные: `make down`. Удалить тома: `make clean`. ### Windows без make В PowerShell из каталога проекта: ```powershell Copy-Item .env.example .env docker compose up -d docker compose --profile ops run --rm --no-deps -e OPS_COMMAND=init ops docker compose --profile ops run --rm --no-deps -e OPS_COMMAND=verify ops docker compose --profile ops run --rm --no-deps console ``` ### Полезные команды ```bash make ps make logs make es-health docker compose logs -f storaged-listener ``` Проверка Elasticsearch с хоста (пароль из `.env`): ```bash curl -u "elastic:NebulaEsLab2026" "http://127.0.0.1:9200/_cluster/health?pretty" curl -u "elastic:NebulaEsLab2026" "http://127.0.0.1:9200/_cat/indices?v" ``` Если меняли `ELASTIC_PASSWORD` в `.env`, подставьте его. ## Как подключён listener Полнотекстовый индекс NebulaGraph пишет в Elasticsearch не сам storaged, а отдельный процесс Raft Listener. Это тот же бинарник `nebula-storaged`, но со своим портом и каталогом WAL. В compose у `storaged-listener` свой entrypoint: флаги listener не смешиваются с обычным `nebula-storaged.conf`. Слушает он `172.30.80.41:9789` (`LISTENER_IP` в `.env`). В кластер хранения через `ADD HOSTS` его не добавляют. Для каждого графового пространства listener регистрируется один раз, все адреса — одним оператором `ADD LISTENER`. Пока `SHOW LISTENER` не покажет `ONLINE` по всем партициям, полнотекстовый индекс не создают. Учётные данные Elasticsearch глобальные для кластера, не для пространства: один `SIGN IN TEXT SERVICE` на все space. Повторный вход делается после `SIGN OUT TEXT SERVICE`. `make init` и `make verify` выполняют команды ниже сами и повторяют попытку, пока метаданные и listener не станут готовы. Вручную между `CREATE SPACE`, `CREATE TAG` и индексом нужно подождать одно-два сердцебиения meta (около 20 секунд): иначе пространство или тег ещё не видны. Пароль в примерах — значение `ELASTIC_PASSWORD` из `.env`. Адреса — значения по умолчанию из `.env.example`. ### 1. Узлы хранения ```ngql ADD HOSTS "172.30.80.21":9779, "172.30.80.22":9779, "172.30.80.23":9779; SHOW HOSTS; ``` В `SHOW HOSTS` три строки `ONLINE`. До этой команды контейнеры storaged уже запущены, но метаданные ещё не отдают им партиции. `make ps` может показывать их unhealthy, пока `ADD HOSTS` не пройдёт. ### 2. Elasticsearch Транспорт между `es01`–`es03` зашифрован общим сертификатом, HTTP оставлен без TLS и закрыт basic-авторизацией. NebulaGraph ходит по HTTP, поэтому в `SIGN IN` схема `HTTP`, пользователь `elastic` и пароль из `.env`. ```ngql SIGN IN TEXT SERVICE (172.30.80.51:9200, HTTP, "elastic", "NebulaEsLab2026"), (172.30.80.52:9200, HTTP, "elastic", "NebulaEsLab2026"), (172.30.80.53:9200, HTTP, "elastic", "NebulaEsLab2026"); SHOW TEXT SEARCH CLIENTS; ``` Ожидаются три строки `ELASTICSEARCH`. Клиент один на весь кластер. Сброс: `SIGN OUT TEXT SERVICE;`. ### 3. Пространство и listener ```ngql CREATE SPACE IF NOT EXISTS demo ( partition_num = 12, replica_factor = 3, vid_type = FIXED_STRING(64) ); USE demo; ADD LISTENER ELASTICSEARCH "172.30.80.41":9789; SHOW LISTENER; ``` `USE` и `ADD LISTENER` должны быть в одной сессии консоли. `SHOW LISTENER` — тоже после `USE demo`. Для 12 партиций будет 12 строк. Ждите `ONLINE` в каждой. Снять listener с пространства: `REMOVE LISTENER ELASTICSEARCH;`. ### 4. Схема, индекс и данные ```ngql USE demo; CREATE TAG IF NOT EXISTS document ( title STRING, content STRING ); CREATE FULLTEXT TAG INDEX document_search ON document(title, content) ANALYZER = "standard"; SHOW FULLTEXT INDEXES; ``` В NebulaGraph 3.8 у `CREATE FULLTEXT TAG INDEX` нет `IF NOT EXISTS`. Повторный запуск отвечает `Existed!`, `make verify` это учитывает. ```ngql INSERT VERTEX document(title, content) VALUES "doc-001":("Kubernetes", "Container orchestration platform"), "doc-002":("NebulaGraph", "Distributed graph database"); ``` Индексация идёт асинхронно через listener. Для уже лежащих в пространстве данных: ```ngql USE demo; REBUILD FULLTEXT INDEX; ``` Проверка со стороны NebulaGraph — запрос в Elasticsearch через индекс: ```ngql USE demo; LOOKUP ON document WHERE ES_QUERY(document_search, "Kubernetes") YIELD id(vertex); ``` В ответе должен быть `doc-001`. Анализатор `standard` приводит слово к нижнему регистру, поэтому в Elasticsearch документ ищется и по `Kubernetes`. Появление индекса снаружи: ```bash curl -u "elastic:NebulaEsLab2026" "http://127.0.0.1:9200/_cat/indices?v" ``` ## Если адреса другие Поменяйте подсеть и IP в `.env`, затем `make clean && make up && make verify`. Команды nGQL и поле Graphd IP в Studio берите уже из своего `.env`: listener и `ADD HOSTS` должны указывать те же адреса, что `--local_ip` у контейнеров. На сервере со свободным диском в `.env` поставьте `ES_DISK_THRESHOLD=true`. Кучу Elasticsearch увеличивают через `ES_JAVA_OPTS`. `ES_MEMORY_LOCK=true` включайте на Linux, где для контейнера разрешён memlock.