1. Przegląd
Informacje o Micronaut
Micronaut to nowoczesna platforma typu full-stack oparta na JVM, która umożliwia tworzenie modułowych, łatwych do testowania mikroserwisów i aplikacji bezserwerowych. Micronaut ma zapewniać krótki czas uruchamiania, dużą przepustowość i minimalne wykorzystanie pamięci. Deweloperzy mogą tworzyć aplikacje za pomocą Micronaut w językach Java, Groovy lub Kotlin.
Micronaut zapewnia:
- Krótki czas uruchamiania i niskie zużycie pamięci – platformy IoC oparte na odbiciu wczytują i buforują dane odbicia dla każdego pola, metody i konstruktora w kodzie, natomiast w przypadku Micronaut czas uruchamiania aplikacji i zużycie pamięci nie są powiązane z rozmiarem bazy kodu.
- Deklaratywny, reaktywny klient HTTP czasu kompilacji – deklaratywne tworzenie reaktywnych klientów HTTP, którzy są implementowani w czasie kompilacji, co zmniejsza zużycie pamięci.
- Nieblokujący serwer HTTP oparty na Netty – serwer HTTP Micronaut ma prostą krzywą uczenia się, dzięki czemu maksymalnie ułatwia udostępnianie interfejsów API, które mogą być używane przez klientów HTTP.
- Szybkie i łatwe testowanie – łatwo uruchamiaj serwery i klientów w testach jednostkowych i przeprowadzaj je natychmiast.
- Wydajne wstrzykiwanie zależności w czasie kompilacji i programowanie zorientowane na aspekty – Micronaut udostępnia prosty interfejs API programowania zorientowanego na aspekty w czasie kompilacji, który nie korzysta z odbicia.
- Twórz w pełni reaktywne i nieblokujące aplikacje – Micronaut obsługuje wszystkie platformy, które implementują Reactive Streams, w tym RxJava i Reactor.
Więcej informacji znajdziesz na stronie Micronaut.
Informacje o Kubernetes
Kubernetes to projekt typu open source, który może działać w wielu różnych środowiskach, od laptopów po klastry wielowęzłowe o wysokiej dostępności, od chmur publicznych po wdrożenia lokalne, od maszyn wirtualnych po sprzęt fizyczny.
W tym module wdrożysz prosty mikroserwis Micronaut oparty na Groovy w Kubernetes działającym w Kubernetes Engine.
Celem tych ćwiczeń z programowania jest uruchomienie mikroserwisu jako replikowanej usługi działającej w Kubernetes. Kod opracowany na komputerze przekształcasz w obraz kontenera Dockera, a następnie uruchamiasz ten obraz w Kubernetes Engine.
Aby ułatwić Ci zrozumienie, jak poszczególne elementy łączą się ze sobą, przedstawiamy diagram różnych części tego laboratorium. Korzystaj z niej w trakcie wykonywania ćwiczeń. Wszystko powinno stać się jasne, gdy dotrzesz do końca (ale na razie możesz to zignorować).

Na potrzeby tego laboratorium użycie zarządzanego środowiska, takiego jak Kubernetes Engine (wersja Kubernetes hostowana przez Google i działająca w Compute Engine), pozwala skupić się na korzystaniu z Kubernetes, a nie na konfigurowaniu infrastruktury bazowej.
Jeśli chcesz uruchomić Kubernetes na komputerze lokalnym, np. na laptopie deweloperskim, prawdopodobnie zainteresuje Cię Minikube. Umożliwia to proste skonfigurowanie klastra Kubernetes z 1 węzłem na potrzeby programowania i testowania. Jeśli chcesz, możesz skorzystać z Minikube, aby przejść ten samouczek.
Informacje o Jib
Jib to narzędzie open source, które umożliwia tworzenie obrazów Dockera i OCI dla aplikacji Java. Jest dostępna jako wtyczka do Maven i Gradle oraz jako biblioteka Java.
Jib ma być:
- Szybkie – szybkie wdrażanie zmian. Jib dzieli aplikację na kilka warstw, oddzielając zależności od klas. Nie musisz już czekać, aż Docker ponownie utworzy całą aplikację Java – wystarczy wdrożyć zmienione warstwy.
- Powtarzalność – ponowne utworzenie obrazu kontenera z tą samą zawartością zawsze generuje ten sam obraz. Już nigdy nie wywołasz niepotrzebnej aktualizacji.
- Bez demona – zmniejsz zależności interfejsu wiersza poleceń. Skompiluj obraz Dockera w Maven lub Gradle i prześlij go do dowolnego rejestru. Nie musisz już pisać plików Dockerfile ani wywoływać poleceń docker build/push.
Więcej informacji o Jib znajdziesz na stronie projektu na GitHubie.
Informacje o tym samouczku
W tym samouczku używany jest przykładowy kod z narzędzia Jib do tworzenia kontenerów dla aplikacji w Javie.
Przykładowa usługa to prosta usługa hello world, która korzysta z frameworka Micronaut i języka programowania Apache Groovy.
Czego się nauczysz
- Jak spakować prostą aplikację w Javie jako kontener Dockera za pomocą Jib
- Jak utworzyć klaster Kubernetes w Kubernetes Engine.
- Jak wdrożyć usługę Micronaut w Kubernetes w Kubernetes Engine
- Jak skalować w górę usługę i wdrażać uaktualnienia.
- Jak uzyskać dostęp do graficznego panelu Kubernetes.
Czego potrzebujesz
- Projekt Google Cloud Platform
- przeglądarka, np. Chrome lub Firefox;
- Znajomość standardowych edytorów tekstu systemu Linux, takich jak Vim, EMACS lub Nano.
Jak zamierzasz korzystać z tego samouczka?
Jak oceniasz swoje doświadczenie w tworzeniu aplikacji internetowych w HTML/CSS?
Jak oceniasz korzystanie z usług Google Cloud Platform?
2. Konfiguracja i wymagania
Samodzielne konfigurowanie środowiska
- Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. (Jeśli nie masz jeszcze konta Gmail lub G Suite, musisz je utworzyć).
Zapamiętaj identyfikator projektu, czyli unikalną nazwę we wszystkich projektach Google Cloud (podana powyżej nazwa jest już zajęta i nie będzie działać w Twoim przypadku). W dalszej części tego laboratorium będzie on nazywany PROJECT_ID.
- Następnie musisz włączyć rozliczenia w konsoli Cloud, aby korzystać z zasobów Google Cloud.
Ukończenie tego laboratorium nie powinno wiązać się z dużymi kosztami, a nawet z żadnymi. Wykonaj instrukcje z sekcji „Czyszczenie”, w której znajdziesz informacje o tym, jak wyłączyć zasoby, aby uniknąć naliczenia opłat po zakończeniu tego samouczka. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.
3. Pobieranie przykładowego kodu źródłowego Micronaut
Po uruchomieniu Cloud Shell możesz użyć wiersza poleceń, aby sklonować przykładowy kod źródłowy w katalogu głównym i przejść do katalogu zawierającego przykładową usługę:
$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/
4. Szybki podgląd kodu
Nasz prosty serwis Micronaut składa się z kontrolera, który wyświetla słynny komunikat Hello World:
@Controller("/hello")
class HelloController {
@Get("/")
String index() {
"Hello World"
}
}
HelloController kontroler odpowiada na żądania w ścieżce /hello, a metoda index() akceptuje żądania HTTP GET.
Dostępna jest też klasa testowa Spock, która sprawdza, czy na wyjściu pojawia się prawidłowy komunikat.
class HelloControllerSpec extends Specification {
@Shared
@AutoCleanup
EmbeddedServer embeddedServer = ApplicationContext.run(EmbeddedServer)
@Shared
@AutoCleanup
RxHttpClient client = embeddedServer.applicationContext.createBean(RxHttpClient, embeddedServer.getURL())
void "test hello world response"() {
when:
HttpRequest request = HttpRequest.GET('/hello')
String rsp = client.toBlocking().retrieve(request)
then:
rsp == "Hello World"
}
}
To nie jest zwykły test jednostkowy. W tym przypadku uruchamiany jest ten sam stos serwera Micronaut (oparty na platformie Netty), który jest używany w środowisku produkcyjnym. Działanie kodu w usłudze będzie takie samo jak w testach.
Aby uruchomić testy i sprawdzić, czy wszystko działa prawidłowo, możesz uruchomić to polecenie:
./gradlew test
5. Lokalne uruchamianie aplikacji
Usługę Micronaut możesz uruchomić w normalny sposób za pomocą tego polecenia Gradle:
$ ./gradlew run
Po uruchomieniu aplikacji możesz otworzyć dodatkową instancję Cloud Shell, klikając małą ikonę +, a następnie sprawdzić za pomocą polecenia curl, czy otrzymujesz oczekiwane dane wyjściowe:
$ curl localhost:8080/hello
Powinien wyświetlić się prosty komunikat „Hello World”.
6. Pakowanie aplikacji jako kontenera Dockera za pomocą Jib
Następnie przygotuj aplikację do uruchomienia w Kubernetes. W tym celu wykorzystamy Jib, który wykona za nas całą pracę, ponieważ nie będziemy musieli sami tworzyć pliku Dockerfile.
Uruchommy polecenie, aby utworzyć kontener:
$ ./gradlew jibDockerBuild
Oto dane wyjściowe, które powinny się wyświetlić:
Tagging image with generated image reference micronaut-jib:0.1. If you'd like to specify a different tag, you can set the jib.to.image parameter in your build.gradle, or use the --im age=<MY IMAGE> commandline flag. Containerizing application to Docker daemon as micronaut-jib:0.1... warning: Base image 'gcr.io/distroless/java' does not use a specific image digest - build may not be reproducible Getting base image gcr.io/distroless/java... Building dependencies layer... Building resources layer... Building classes layer... Finalizing... Container entrypoint set to [java, -cp, /app/resources:/app/classes:/app/libs/*, example.micronaut.Application] Loading to Docker daemon... Built image to Docker daemon as micronaut-jib:0.1
Teraz, gdy obraz został utworzony, sprawdźmy, czy widzimy nasz przyjazny komunikat powitalny. W tym celu uruchommy obraz Dockera na pierwszej karcie Cloud Shell:
$ docker run -it -p 8080:8080 micronaut-jib:0.1 16:57:20.255 [main] INFO i.m.context.env.DefaultEnvironment - Established active environments: [cloud, gcp] 16:57:23.203 [main] INFO io.micronaut.runtime.Micronaut - Startup completed in 2926ms. Server Running: http://97b7d76ccf3f:8080
Usługa działa, więc w drugiej karcie Cloud Shell możemy uruchomić polecenie curl, aby sprawdzić, czy działa zgodnie z oczekiwaniami:
$ curl localhost:8080/hello Hello World
Aby zatrzymać kontener, w Cloud Shell naciśnij Ctrl+C.
7. przekazywanie skonteneryzowanej usługi do rejestru;
Teraz, gdy obraz działa zgodnie z oczekiwaniami, możesz przesłać go do Google Container Registry, czyli prywatnego repozytorium obrazów Dockera dostępnego z każdego projektu w chmurze Google (ale też spoza Google Cloud Platform).
Zanim będzie można przesłać obraz do rejestru, upewnijmy się, że Container Registry jest włączony w naszym projekcie. W tym celu kliknij Narzędzia > Container Registry. Jeśli nie jest włączony, zobaczysz to okno. Kliknij „Włącz interfejs Container Registry API”, aby go włączyć:

Gdy rejestr będzie gotowy, aby przesłać obraz do rejestru, uruchom te polecenia:
$ gcloud auth configure-docker
$ docker tag micronaut-jib:0.1 \
gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
$ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
Powyższe polecenia umożliwiają pakietowi SDK gcloud skonfigurowanie i autoryzowanie Dockera do wypychania obrazów do instancji Container Registry, otagowanie obrazu w celu wskazania jego lokalizacji w rejestrze, a następnie wypchnięcie go do rejestru.
Jeśli wszystko przebiegnie pomyślnie, po chwili obraz kontenera powinien być widoczny w konsoli: Narzędzia > Container Registry. W tym momencie masz już dostępny obraz Dockera w całym projekcie, do którego Kubernetes może uzyskać dostęp i którym może zarządzać, co zobaczysz za kilka minut.

8. Tworzenie klastra
Możesz już utworzyć klaster Kubernetes Engine. Zanim to zrobisz, otwórz sekcję Google Kubernetes Engine w konsoli internetowej i poczekaj, aż system się zainicjuje (powinno to zająć tylko kilka sekund).

Klaster składa się z serwera Kubernetes Master API zarządzanego przez Google i zestawu węzłów roboczych. Węzły robocze to maszyny wirtualne Compute Engine. Użyj interfejsu gcloud CLI w sesji Cloud Shell, aby utworzyć klaster z 2 węzłami n1-standard-1 (wykonanie tego kroku może potrwać kilka minut):
$ gcloud container clusters create hello-cluster \ --num-nodes 2 \ --machine-type n1-standard-1 \ --zone us-central1-c
Na koniec powinien pojawić się utworzony klaster.
Creating cluster hello-cluster in us-central1-c...done. Created [https://container.googleapis.com/v1/projects/mn-gke-test/zones/us-central1-c/clusters/hello-cluster]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-c/hello-cluster?project=mn-gke-test kubeconfig entry generated for hello-cluster. NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS hello-cluster us-central1-c 1.9.7-gke.7 35.239.224.115 n1-standard-1 1.9.7-gke.7 2 RUNNING
Powinien być teraz dostępny w pełni funkcjonalny klaster Kubernetes obsługiwany przez Google Kubernetes Engine:

Czas wdrożyć własną skonteneryzowaną aplikację w klastrze Kubernetes. Od teraz będziesz używać wiersza poleceń kubectl (jest on już skonfigurowany w środowisku Cloud Shell). W pozostałej części tego modułu wymagane jest, aby wersja klienta i serwera Kubernetes była co najmniej 1.2. kubectl version wyświetli aktualną wersję polecenia.
9. Wdrażanie aplikacji w Kubernetes
Wdrożenie Kubernetes może tworzyć wiele instancji aplikacji, zarządzać nimi i je skalować za pomocą utworzonego właśnie obrazu kontenera. Utwórzmy wdrożenie aplikacji w Kubernetes za pomocą polecenia kubectl create deployment:
$ kubectl create deployment hello-micronaut \ --image=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.1
Aby wyświetlić właśnie utworzone wdrożenie, uruchom to polecenie:
$ kubectl get deployments NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 1 1 1 1 5m
Aby wyświetlić instancje aplikacji utworzone przez wdrożenie, uruchom to polecenie:
$ kubectl get pods NAME READY STATUS RESTARTS AGE hello-micronaut-5647fb98c5-lh5h7 1/1 Running 0 5m
W tym momencie kontener powinien działać pod kontrolą Kubernetes, ale nadal musisz udostępnić go do użytku publicznego.
10. Zezwalaj na ruch zewnętrzny
Domyślnie pod jest dostępny tylko przez wewnętrzny adres IP w klastrze. Aby kontener hello-micronaut był dostępny spoza wirtualnej sieci Kubernetes, musisz udostępnić poda jako usługę Kubernetes.
W Cloud Shell możesz udostępnić poda w publicznym internecie za pomocą polecenia kubectl expose w połączeniu z flagą --type=LoadBalancer. Ta flaga jest wymagana do utworzenia adresu IP dostępnego z zewnątrz :
$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080
Flaga użyta w tym poleceniu określa, że będziesz używać systemu równoważenia obciążenia udostępnianego przez infrastrukturę bazową (w tym przypadku systemu równoważenia obciążenia Compute Engine). Pamiętaj, że udostępniasz wdrożenie, a nie bezpośrednio poda. Spowoduje to, że usługa będzie równoważyć obciążenie we wszystkich podach zarządzanych przez wdrożenie (w tym przypadku tylko 1 pod, ale później dodasz więcej replik).
Węzeł główny Kubernetes tworzy system równoważenia obciążenia oraz powiązane reguły przekierowania Compute Engine, pule docelowe i reguły zapory, aby usługa była w pełni dostępna spoza Google Cloud Platform.
Aby znaleźć publicznie dostępny adres IP usługi, po prostu poproś kubectl o wyświetlenie listy wszystkich usług klastra:
$ kubectl get services NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE hello-micronaut LoadBalancer 10.39.243.251 aaa.bbb.ccc.ddd 8080:30354/TCP 1m kubernetes ClusterIP 10.39.240.1 <none> 443/TCP 31m
Zwróć uwagę, że w przypadku Twojej usługi są wymienione 2 adresy IP, które obsługują port 8080. Jeden to wewnętrzny adres IP widoczny tylko w Twojej wirtualnej sieci w chmurze, a drugi to zewnętrzny adres IP z równoważeniem obciążenia. W tym przykładzie zewnętrzny adres IP to aaa.bbb.ccc.ddd.
Usługa powinna być teraz dostępna pod tym adresem: http://<EXTERNAL_IP>:8080/hello
11. Skalowanie w górę usługi
Jedną z najważniejszych funkcji Kubernetes jest łatwość skalowania aplikacji. Załóżmy, że nagle potrzebujesz większej mocy obliczeniowej dla aplikacji. Wystarczy, że poinformujesz kontroler replikacji, aby zarządzał nową liczbą replik instancji aplikacji:
$ kubectl scale deployment hello-micronaut --replicas=3 deployment.extensions "hello-micronaut" scaled $ kubectl get deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE hello-micronaut 3 3 3 3 16m
Zwróć uwagę na podejście deklaratywne – zamiast uruchamiać lub zatrzymywać nowe instancje deklarujesz, ile instancji powinno działać przez cały czas. Pętle uzgadniania Kubernetes po prostu sprawdzają, czy rzeczywistość jest zgodna z Twoimi żądaniami, i w razie potrzeby podejmują odpowiednie działania.
12. Wdrażanie uaktualnienia usługi
W pewnym momencie aplikacja wdrożona w środowisku produkcyjnym będzie wymagać poprawek lub dodatkowych funkcji. Kubernetes pomoże Ci wdrożyć nową wersję w środowisku produkcyjnym bez wpływu na użytkowników.
Najpierw zmodyfikujemy aplikację. Otwórz edytor kodu w Cloud Shell.

Otwórz /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy i zmień wartość odpowiedzi:
@Controller("/hello")
class HelloController {
@Get("/")
String index() {
"Hello Kubernetes World"
}
}
W /jib/examples/micronaut/build.gradle uaktualnimy wersję obrazu z 0.1 do 0.2, zmieniając ten wiersz:
version '0.2'
Następnie ponownie skompiluj i spakuj aplikację z najnowszymi zmianami:
$ ./gradlew jibDockerBuild
Dodaj tag do obrazu i prześlij go do rejestru obrazów kontenerów:
$ docker tag micronaut-jib:0.2 \
gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
$ docker push gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
Kubernetes może teraz bezproblemowo zaktualizować kontroler replikacji do nowej wersji aplikacji. Aby zmienić etykietę obrazu uruchomionego kontenera, musisz edytować istniejący plik hello-micronaut deployment i zmienić obraz z gcr.io/PROJECT_ID/micronaut-jib:0.1 na gcr.io/PROJECT_ID/micronaut-jib:0.2.
Możesz użyć polecenia kubectl set image, aby poprosić Kubernetes o wdrożenie nowej wersji aplikacji w całym klastrze po jednej instancji naraz za pomocą aktualizacji kroczącej:
$ kubectl set image deployment/hello-micronaut \
micronaut-jib=gcr.io/$GOOGLE_CLOUD_PROJECT/micronaut-jib:0.2
deployment.apps "hello-micronaut" image updated
Sprawdź ponownie adres http://EXTERNAL_IP:8080, aby upewnić się, że zwraca nową odpowiedź.
13. Wycofaj zmiany
Ups – czy w nowej wersji aplikacji wystąpił błąd? Być może nowa wersja zawiera błąd i musisz szybko przywrócić poprzednią. Dzięki Kubernetes możesz łatwo wycofać zmiany do poprzedniego stanu. Przywróćmy aplikację, uruchamiając to polecenie:
$ kubectl rollout undo deployment/hello-micronaut
Jeśli spojrzysz na wynik działania usługi, zobaczysz początkowy komunikat „Hello World”.
14. Podsumowanie
W tym kroku skonfigurowaliśmy prostą usługę Micronaut hello world opartą na Apache Groovy i uruchomiliśmy ją bezpośrednio w Cloud Shell, spakowaliśmy ją jako kontener za pomocą Jib i wdrożyliśmy w Google Kubernetes Engine.
15. Gratulacje!
Dowiedzieliśmy się, jak utworzyć i wdrożyć nowy mikroserwis internetowy Apache Groovy / Micronaut w Kubernetes w Google Kubernetes Engine.
Więcej informacji
- Dokumentacja i przykłady Jib: https://github.com/GoogleContainerTools/jib/
- Strona internetowa Micronaut: http://micronaut.io/
- Java na Google Cloud Platform: https://cloud.google.com/java/
- Przykłady w Javie: https://cloud.google.com/java/samples
- Dłuższy i bardziej szczegółowy samouczek dotyczący Kubernetes znajdziesz na stronie bit.ly/k8s-lab. Zawiera on instrukcje wdrażania aplikacji pełnostackowej.
Licencja
To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.