W przykładzie posłużę się najnowszą w chwili obecnej wersją Apache Karaf 3.0.1. Ale na początek, warto wspomnieć, co tak naprawdę wchodzi w skład dystrybucji Apache Karaf.
Struktura dystrybucji
W zasadzie każda dystrybucja Apache Karaf (niezależnie czy jest to właśnie czysty Karaf czy ServiceMix) wygląda identycznie. Po rozpakowaniu archiwum z dystrybucją dostajemy kilka katalogów jak w przykładzie:
Katalog bin zawiera skrypty uruchomieniowe dla unix/windows, katalog data zawiera cache, logi i inne pliki generowane w trakcie działania kontenera, deploy jest to katalog skanowany na obecność artefaktów, które mogą być automatycznie instalowane, etc zawiera konfigurację kontenera, lib podstawowe biblioteki OSGI i najważniejszy w każdej dystrybucji: system zawiera lokalne repozytorium maven, skąd mogą być instalowane kolejne bundle i feature'y. I to właśnie system jest tym, co nas najbardziej interesuje, bo przygotowując dystrybucję decydujemy które bundle i feature'y będą umieszczone w repozytorium system, oraz które z nich będą automatycznie uruchamiane. A wszystko to dzieje się z wykorzystaniem karaf-maven-plugin. Ale zanim dojdziemy do jego użycia, pokażę wykorzystywaną przeze mnie strukturę projektu Maven.
Struktura projektu
Jak to zwykle w korporacjach, obowiązującym standardem jest Maven wykorzystywany do budowania wielomodułowych projektów. Konkretna struktura projektu wygląda mniej więcej tak:
Projekt główny podzielony jest zwykle na 2 moduły: assembly, który zawiera kolejne moduły związane z budowaniem dystrybucji oraz services, który zawiera konkretne usługi wchodzące w skład dystrybucji. W omawianym przykładzie services zawiera tylko jeden projekt z prostym użyciem Apache Camel, które ma na celu tylko i wyłącznie pokazać, że się zainstalowało i działa.
Przykładowy przepływ będzie co wskazany interwał logował na konsolę. A teraz najważniejsze, czyli jak spakować to w gotową dystrybucję.
Budowa dystrybucji
Dystrybucję buduje się w dwóch etapach: pierwszy polega na zebraniu wszystkich naszych usług w grupę feature, drugi polega na przyłączeniu naszego feature do budowanej dystrybucji.
Pierwszy etap, zebranie usług w grupy realizuje się przez utworzenie modułu budującego feature lub KAR (KAR to jest archiwum jar zawierające spakowane bundle opisane przez feature - rzecz specyficzna dla Karaf). Ja zwykle stosuję metodę budującą archiwum KAR, gdyż po drodze i tak powstaje feature, a dostaję jeszcze automatycznie archiwum KAR, które przydaje się czasem przy innych sposobach deploymentu.
W przykładowym projekcie, moduł assembly/custom-feature realizuje funkcję grupującą usługi. Jest to projekt wygenerowany z archetypu karaf-kar-archetype i jego pom.xml wygląda mniej więcej tak:
Na uwagę zasługują 2 szczegóły: typ projektu określony na kar oraz wykorzystanie pluginu karaf-maven-plugin, który obsługuje generowanie pliku feature.xml i archiwum KAR.
Jedynym elementem źródłowym tego projektu jest plik src/main/feature/feature.xml, w którym opisana jest przykładowa usługa wraz z jej zależnościami (w tym przypadku jest to camel-blueprint):
Drugi etap, najciekawszy z tego wszystkiego, realizowany jest w module assembly/custom-distro, a wygenerowany z wykorzystaniem archetypu karaf-assembly-archetype. Jego pom.xml wygląda następująco:
Jest to projekt typu karaf-assembly obsługiwany przez karaf-maven-plugin do budowania dystrybucji. Zależności tego modułu zawierają przede wszystkim odniesienia do plików feature.xml, z których chcemy preinstalować paczki wchodzące w skład naszej dystrybucji:
Na liście zależności znajduje się podstawowy kar ze szkieletem Karafa (framework) oraz pliki feature.xml pochodzące z Karafa, Camela i naszego modułu custom-feature.
Dalej pozostaje tylko wybrać, które konkretne features mają zostać preinstalowane. Dzieje się to w konfiguracji karaf-maven-plugin:
Jeśli wszystko jest gotowe, można zbudować projekt (mvn install) i poszukać w custom-distro/target archiwum z dystrybucją, w naszym przypadku będzie to plik ./assembly/custom-distro/target/custom-distro-1.0.0-SNAPSHOT.tar.gz. Po rozpakowaniu i uruchomieniu powinniśmy móc sprawdzić jakie features i bundle zostały automatycznie uruchomione:
Jak widać, custom-feature jest na liście features, Sample-Service jest na liście aktywnych bundli, w logach można spodziewać się wpisów z aktywności usługi.
Wnioski
Dla mnie najważniejszy wniosek (i zarazem zaleta) budowania własnej dystrybucji jest taki, że dzięki temu możemy dostarczać gotowe rozwiązanie, którego nie trzeba instalować w pustym kontenerze. Koniec z pisaniem mozolnych instrukcji instalacji, możemy ograniczyć się do kilku słów instruktażu związanego z rozpakowaniem archiwum i uruchomieniem skryptu startowego. To skutkuje większą powtarzalnością procesu instalacyjnego i pozwala uniknąć nieprzyjemnych sytuacji podczas wdrożeń na produkcję, gdzie zawsze coś może pójść nie tak, jak byśmy chcieli.Budowanie tego rodzaju własnych dystrybucji jest małym kroczkiem w kierunku immutable deployments, o którym być może kiedyś coś napiszę. A następnym razem, pokażę jeszcze inny sposób przygotowania własnego distro oparty o Docker i obrazy kontenerów :)
Źródła przykładowego projektu znajdują się na githubie.
Brak komentarzy:
Prześlij komentarz