Wraz z premierą Solr 8.4.0 dostajemy w nasze ręce nową funkcjonalność – zarządzanie dodatkami do Solr. Solr udostępnia nam możliwość instalowania oraz zarządzania dodatkami i repozytoriami dodatków. Spójrzmy zatem jak to działa.
Zarządzanie pakietami, czyli co?
Wraz z Solr 8.4.0 dostaliśmy nie tylko sam skrypt umożliwiający pobieranie i usuwanie pakietów. W ramach zmian dostaliśmy także cały pakiet zmian takich jak przechowywanie informacji o pakietach, zarządzanie kluczami, API do odczytu i zapisu oraz odizolowanie na poziomie classloadera.
Zacznijmy zatem od początku, uruchamiamy pojedynczą instancję SolrCloud następującym poleceniem:
$ bin/solr start -c -f -Denable.packages=true
I zaczynamy zabawę pakietami.
Podstawy zarządzania pakietami
Po wpisaniu komendy:
$ bin/solr package
Dostaniemy następujące informacje:
Found 1 Solr nodes: Solr process 20949 running on port 8983 Package Manager ./solr package add-repo Add a repository to Solr. ./solr package install [:] Install a package into Solr. This copies over the artifacts from the repository into Solr's internal package store and sets up classloader for this package to be used. ./solr package deploy [:] [-y] [--update] -collections <package-name>[:] [-y] [--update] -collections [-p param1=value1 -p param2=value2 … Bootstraps a previously installed package into the specified collections. It the package accepts parameters for its setup commands, they can be specified (as per package documentation). ./solr package list-installed Print a list of packages installed in Solr. ./solr package list-available Print a list of packages available in the repositories. ./solr package list-deployed -c Print a list of packages deployed on a given collection. ./solr package list-deployed Print a list of collections on which a given package has been deployed. ./solr package undeploy -collections Undeploys a package from specified collection(s) Note: (a) Please add '-solrUrl http://host:port' parameter if needed (usually on Windows). (b) Please make sure that all Solr nodes are started with '-Denable.packages=true' parameter.
Jak widać mamy dostępnych całkiem sporo opcji, a sam mechanizm zarządzania pakietami weryfikuje działające instancje Solr i sprawdza pakiety na nich zainstalowane.
Dodawanie nowego repozytorium
W celu dodania nowego repozytorium musimy podać jego nazwę oraz jego lokalizację – URL pod którym można dostać się do repozytorium. Oczywiście w podanym repozytorium muszą znajdować się pliki, których Solr oczekuje – na przykład pliku repository.json wyglądający następująco (przykład z kodu źródłowego Solr):
[
{
"name": "question-answer",
"description": "A natural language question answering plugin",
"versions": [
{
"version": "1.0.0",
"date": "2019-01-01",
"artifacts": [
{
"url": "qarh-1.0.jar",
"sig": "C9UWKkucmY3UNzqn0VLneVMe9kCbJjw7Urc76vGenoRwp32xvNn5ZIGZ7G34xZP7cVjqn/ltDlLWBZ/C3eAtuw=="
}
],
"manifest": {
"version-constraint": "8 - 9",
"plugins": [
{
"name": "request-handler",
"setup-command": {
"path": "/api/collections/${collection}/config",
"payload": {"add-requesthandler": {"name": "${RH-HANDLER-PATH}", "class": "question-answer:fullstory.QARequestHandler"}},
"method": "POST"
},
"uninstall-command": {
"path": "/api/collections/${collection}/config",
"payload": {"delete-requesthandler": "${RH-HANDLER-PATH}"},
"method": "POST"
},
"verify-command": {
"path": "/api/collections/${collection}/config/requestHandler?componentName=${RH-HANDLER-PATH}&meta=true",
"method": "GET",
"condition": "$['config'].['requestHandler'].['${RH-HANDLER-PATH}'].['_packageinfo_'].['version']",
"expected": "${package-version}"
}
}
],
"parameter-defaults": {
"RH-HANDLER-PATH": "/mypath"
}
}
}
]
}
]
Spróbujmy zatem dodać nowe repozytorium za pomocą następującego polecenia oraz korzystając z plików dostępnych w kodzie źródłowym Solr:
$ bin/solr package add-repo solrpl http://repo.solr.pl
W przypadku poprawnego dodania repozytorium powinniśmy zobaczyć następujący komunikat:
Added repository: solrpl
Uwaga: w powyższym przykładzie skorzystałem z repozytorium do którego można się dostać bez SSL – proszę, nie powtarzajcie tego. Nie jest to dobra praktyka ze względu na możliwość ataków typu man in the middle i podmiany plików pobieranych z repozytorium.
Instalowanie i usuwanie pakietów
Po dodaniu repozytorium możemy sprawdzić listę pakietów jakie mamy dostępne. Aby to zrobić uruchamiamy polecenie:
$ bin/solr package list-available
W odpowiedzi powinniśmy dostać następujące informacje:
Available packages:
-----
question-answer A natural language question answering plugin
Version: 1.0.0
Przed instalacją pakietów musimy jeszcze dodać klucz publiczny, za pomocą którego Solr będzie w stanie zweryfikować pliki związane z pakietami. Gdzie szukać takiego klucza? W repozytorium lub u dostawcy pakietów 🙂 Mając już klucz możemy go zainstalować następującym poleceniem:
$ bin/solr package add-key publickey.der
Mając te dane oraz dodany klucz możemy zacząć instalować pakiety. To dość proste, wystarczy nam następujące polecenie:
$ bin/solr package install question-answer:1.0.0
Odpowiedź powinna być następująca:
Posting manifest...
Posting artifacts...
Executing Package API to register this package...
Response: {"responseHeader":{
"status":0,
"QTime":66}}
question-answer installed.
Oznacza to, iż nasz pakiet jest gotowy do wykorzystania. Musimy wybrać kolekcję oraz uruchomić polecenie deploy, np w następujący sposób:
$ bin/solr package deploy question-answer:1.0.0 -collections test
Tym razem odpowiedź Solr była następująca:
Executing {"add-requesthandler":{"name":"/mypath","class":"question-answer:fullstory.QARequestHandler"}} for path:/api/collections/test/config
Execute this command (y/n):
y
Executing http://localhost:8983/api/collections/test/config/requestHandler?componentName=/mypath&meta=true for collection:test
{
"responseHeader":{
"status":0,
"QTime":0},
"config":{"requestHandler":{"/mypath":{
"name":"/mypath",
"class":"question-answer:fullstory.QARequestHandler",
"_packageinfo_":{
"package":"question-answer",
"version":"1.0.0",
"files":["/package/question-answer/1.0.0/question-answer-request-handler-1.0.jar"],
"manifest":"/package/question-answer/1.0.0/manifest.json",
"manifestSHA512":"a91ab5a2c5abd53f0f72c256592c2be8b667cecb8226ac054aeed4d28aac9d743311442f2d58539bb83663a19bd1efb310aaadfd77bea458f3d475161721a114"}}}}}
Actual: 1.0.0, expected: 1.0.0
Deployed on [test] and verified package: question-answer, version: 1.0.0
Deployment successful
Jeżeli wszystko poszło tak, jak się spodziewaliśmy oraz odpowiedzieliśmy, iż chcemy dodać pakiet do kolekcji jesteśmy gotowi 🙂
Gdy chcemy pozbyć się niechcianych pakietów wystarczy wysłać do Solr polecenie undeploy wraz z nazwą kolekcji oraz pakietem z którego nie chcemy już więcej korzystać. Na przykład, jeżeli nie chcemy już korzystać z pakietu, który dodaliśmy wcześniej wystarczy następujące polecenie:
$ bin/solr package undeploy question-answer -collections test
W tym wypadku odpowiedź będzie następująca:
Executing {"delete-requesthandler":"/mypath"} for path:/api/collections/test/config
Jak to naprawdę działa?
Całość zaimplementowanego mechanizmu kręci się tak naprawdę wokół ładowania klas. Mechanizm zakłada, iż jakakolwiek zmiana w plikach znajdujących się w classpath Solr wymaga restartu serwera. Wszystkie inne pliki mogą być ładowane dynamicznie i związane są z konfiguracją, która trzymana jest w Zookeeper.
U podstaw całego mechanizmu znajduje się tak zwany Package Store. Rozproszony system plików, który trzyma swoje dane na każdej z instancji Solr w katalogu $SOLR_HOME/filestore, a każdy plik opisany jest za pomocą metadanych trzymanych w pliku JSON. Meta dane pliku przechowują sumę kontrolną pliku pozwalając tym samym na weryfikację.
Na tym wszystkim zbudowane jest API pozwalające na zarządzanie pojedynczymi plikami, jak również całymi pakietami – np. instalowanie pakietów, czy ich uruchamianie dla poszczególnych kolekcji.
API
Oczywiście bin/solr oraz instalowanie pakietów z poziomu tego narzędzia to nie wszystko co oferuje Solr. Do dyspozycji dostaliśmy także API pozwalające na:
- dodawanie plików do Solr za pomocą metody PUT protokołu HTTP z wykorzystaniem /api/cluster/files/{ścieżka_do_pliku}
- pobieranie plików za pomocą metody GET protokołu HTTP z wykorzystaniem /api/cluster/files/{ścieżka_do_pliku}
- pobieranie meta danych o danym pliku za pomocą metody GET protokołu HTTP z wykorzystaniem /api/cluster/files/{ścieżka_do_pliku}?meta=true
- pobieranie dostępnych plików w ramach podanej ścieżki za pomocą metody GET protokołu HTTP z wykorzystaniem /api/cluster/files/{ścieżka_do_katalogu}
Warto pamiętać, iż dodanie pliku to nie tylko same wysłanie go do Solr, należy go najpierw podpisać kluczem, który dostępny jest dla Solr. Oficjalna dokumentacja Solr pokazuje, jak to zrobić: https://lucene.apache.org/solr/guide/8_5/package-manager-internals.html.
Jednak API do instalowania plików i ich pobierania to nie wszystko. Mamy także możliwość dodawania, usuwania oraz pobierania pakietów i ich wersji, czyli:
- GET na /api/cluster/package w celu pobrania listy pakietów
- PUT na /api/cluster/package w celu dodania pakietu
- DELETE na /api/cluster/package w celu usunięcia pakietu
Na przykład dodanie pakietu do Solr mogłoby odbyć się za pomocą następującego polecenia:
curl -XPUT 'http://localhost:8983/api/cluster/package' -H 'Content-type:application/json' -d '{
"add": {
"package" : "testsolrpl",
"version" : "1.0.0",
"files" : [
"/test/solrpl/1.0.0/testsolrpl.jar"
]
}
}'
Bezpieczeństwo
Korzystanie z elastyczności, jaką daje hot-deploy oraz możliwość instalowania pakietów rozszerzających możliwości Solr w dowolnym momencie niesie ze sobą szereg niebezpieczeństw. Ze względu na to nie powinniśmy instalować pakietów ze źródeł, których nie znamy lub nie jesteśmy pewni co się w nich znajduje. Warto też pamiętać o korzystaniu tylko z tych repozytoriów, które dodaliśmy z wykorzystaniem SSL co zapobiegnie atakom typu man in the middle. Oczywiście wszystko to powinno być także poprzedzone normalnym zabezpieczeniem Solr – np. brakiem możliwości dostania się do Solr z zewnątrz.
Podsumowanie
Funkcjonalność instalowania pakietów bez konieczności manualnego wgrywania ich na każdy z serwerów, bez konieczności ponownego uruchamiania Solr, możliwość zarządzania nimi za pomocą API oraz weryfikacja samych plików binarnych jest bardzo fajną funkcjonalnością i przyda się niektórym użytkownikom. Należy jednak pamiętać, iż elastyczność niesie za sobą pewne niebezpieczeństwo. Jeżeli jednak pamiętamy z jakimi ograniczeniami i potencjalnymi problemami możemy mieć do czynienia nie powinniśmy obawiać się korzystania z opisanej funkcjonalności.