Marcin Lewandowski
Marcin Lewandowski
Programista PHP ( Symfony ), blogger, trener oraz miłośnik kawy. Na co dzień pracuję z Symfony, RabbitMQ, ElasticSearch, Node.js, Redis, Docker, MySQL.

Migracja serwera ElasticSearch na nowszą wersję z wykorzystaniem _reindex

Migracja serwera ElasticSearch na nowszą wersję z wykorzystaniem _reindex

ElasticSearch rozwija się bardzo dynamicznie w związku z czym możemy zaobserwować dość częste wydawanie nowej wersje silnika. I pojawia się pytanie, czy aktualizować ? Osobiście chętnie aktualizuję, czy to ElasticSearch-a, czy też frameworki na których pracuję. Wyznaję przy tym kilka zasad, jedna z nich to stabilność działania. Dlatego w tym wpisie pokażę, jak w prosty sposób przenieść nasze indeksy do nowszej wersji ElasticSearch-a wykorzystując _reindex.

Dla nielubiących czytać ;) Poniżej zamieszczam filmik pokazujący jak przeprowadzić proces przenosin pomiędzy wersją 6.2 do 6.7.

Zanim przejdziemy do samego procesu musimy wiedzieć, że przed rozpoczęciem konieczne jest stworzenie indeksu do którego zostaną przeniesione dane na nowym serwerze. Najlepiej gdy indeks zawiera ten sam mapping oraz ustawienia. W innym przypadku mogą wystąpić błędy.

Rozważając opcję migracji należy zwrócić uwagę na wersję pomiędzy którymi planujemy wykonywać migrację. W tym przypadku będziemy robili migrację w ramach wersji 6.x. Oczywiście możliwe są migracje pomiędzy wersjami 5.x -> 6.x czy 6.x -> 7.x. Takie migracje wymagać mogą modyfikacji mappingu czy ustawień, dlatego skupimy się na najprostszej opcji czyli migracja w ramach tej samej wersji głównej.

Na starym serwerze znajdują się nasze indeksy i wszystkie dane. Na nowym serwerze tworzymy indeksy wraz z mappingiem i ustawieniami zgodnymi z tymi ze starego serwera.

W konfiguracji nowego serwera dodajemy adres starego serwer do białej listy. Robimy to dodając do pliku elasticsearch.yml poniższy wpis ( sam plik znajdziemy w lokalizacji: /etc/elasticsearch/elasticsearch.yml).

reindex.remote.whitelist: stary:9200

Zamiast stary wpisujemy adres IP naszego serwera ;) Po zmianach w pliku restartujemy serwer ElasticSearch i możemy przystąpić do uruchomienia procesu reindeksacji.

_reindex

Wchodzimy do Kibany na nowym serwerze lub konsoli i przesyłamy poniższe polecenie.

POST _reindex?wait_for_completion=false
{
  "source": {
    "remote": {
      "host": "http://stary:9200"
    },
    "index": "indeks_a"
  },
  "dest": {
    "index": "indeks_a"
  }
}

Zaczynając od samego początku. Opcja reindeksacji jest dostępna pod adresem _reindex. Po adresie został dodany parametr wait_for_completion ustawiony na wartość false, co oznacza że nie chcemy czekać na zakończenie polecenia i jego rezultat. Gdybym z tej opcji zrezygnowali to czekali byśmy na zakończenie wykonywania całego procesu. W zależności od wielkości indeksu i wydajności maszyny oczekiwanie może zająć różny okres czasu. A najprawdopodobniej po 30 sekundach proces zostanie zakończony, a my zobaczymy błąd. Jest to ograniczenie Kibany, które możemy zmienić w ustawieniach. Pytanie tylko po co skoro mamy inną opcję. Dlatego zalecam pozostawienie parametru i obserwowanie poziomu jego wykonania przez API zadań o czym opowiem za chwilę.

W ciele polecenia znajdują się dwa istotne obiekty source oraz dest.

source

Obiekt definiuje źródło z którego mają być pobierane dane. Znajdziemy tam obiekt remote w którym pod parametrem host został wpisany adres serwera źródłowego.

"source": {
  "remote": {
    "host": "http://stary:9200"
  },
  "index": "indeks_a"
}

Mamy także parametr index, gdzie podajemy nazwę indeksu, który chcemy przenieść.

dest

Drugim obiektem, jest obiekt dest. Definiuje on gdzie należy dane przenieść. W parametrze index podajemy nazwę indeksu, w tym przypadku mamy taką samą nazwę indeksu, co oczywiście nie jest wymogiem.

"dest": {
  "index": "indeks_a"
}

Proces reindeksacji

Po wykonaniu przedstawionego polecenia z opcją wait_for_completion ustawioną na false. Zostanie nam zwrócony identyfikator zadania uruchomionego w tle.

Mając taki identyfikator jesteśmy w stanie odwołać się do niego wykorzystując API ElasticSearch. I dowiedzieć jak wygląda status wykonywanego zadania.

GET _tasks/xF0lhlBgTRSjH4dFYLmLTA:39842

Zapytanie to powinno zwrócić nam informację o zadaniu na podstawie podanego identyfikatora.

Najważniejsza jest dla nas informacja, czy zadanie zostało zakończone. Informację tą znajdziemy pod kluczem completed, gdy wartość zostanie zmieniona na true to indeks został przeniesiony.

Dodatkowe informacje o stanie przenosin danych pomiędzy indeksami znajdziemy w obiekcie znajdującym się pod kluczem status. Mamy tam informację o ilości dokumentów, klucz total. Oraz pod kluczami updated, created, deleted znajdziemy informację o ilościach wykonanych poszczególnych operacji w ramach reindeksacji.

Warto także rzucić okiem na klucz description, który opisowo pokazuje polecenie jakie jest wykonywane.

Podsumowanie

Powyższy proces jest najprostszym przypadkiem przenoszenia indeksu pomiędzy starą i nową instalacją ElasticSearch. Oczywiście nie jedyną, ale w wielu przypadkach najprostszą i najszybszą.

Zaletą tego rozwiązania jest możliwość bardzo łatwego sprawdzenia czy po aktualizacji do nowszej wersji wszystkie nasze aplikację będą działały bez problemu z nową wersją ElasticSearch.

Drobną wadą jest konieczność tworzenia indeksu i przenoszenia mappingu, ustawień do nowej maszyny. Choć jestem w stanie sobie wyobrazić, że tę część wykonuje za nas nasza aplikacja ;)