Wdróż w Google Kubernetes Engine aplikację mikronauty skonteneryzowaną przy użyciu Jib

1. Omówienie

Mikronauty

Micronaut to oparta na JVM nowoczesna platforma typu full stack do tworzenia modułowych, łatwych do przetestowania mikroserwisów i aplikacji bezserwerowych. Firma Micronaut stara się zapewnić krótki czas uruchamiania, wysoką przepustowość przy minimalnym zużyciu pamięci. Programiści mogą programować przy użyciu oprogramowania Micronaut w języku Java oraz Groovy lub Kotlin.

Mikronaut zapewnia:

  • Szybkie uruchamianie małe wykorzystanie pamięci – platformy IoC oparte na odbiciach wczytują i buforują dane odbicia w pamięci podręcznej dla każdego pola, metody i konstruktora w kodzie, podczas gdy w przypadku Micronaut czas uruchamiania aplikacji i wykorzystanie pamięci nie są powiązane z rozmiarem bazy kodu.
  • Deklaratywny, reaktywny, kompilowany klient HTTP w czasie kompilowania – deklaratywne tworzenie reaktywnych klientów HTTP, które są wdrażane podczas kompilacji, co zmniejsza wykorzystanie pamięci.
  • Nieblokujący serwer HTTP oparty na Netty – dzięki płynnej krzywej uczenia się serwer HTTP firmy Micronaut ułatwia udostępnianie interfejsów API do wykorzystania przez klienty HTTP.
  • Szybkie i łatwe testowanie – łatwo uruchamiaj serwery i klienty w testach jednostkowych i od razu je uruchamiaj.
  • Efektywne wstrzykiwanie zależności podczas kompilacji oraz AOP – Micronaut zapewnia prosty, zorientowany na aspekt interfejs API do programowania w czasie kompilacji, który nie wymaga odbicia.
  • Tworzenie w pełni reaktywnych i nieblokujących aplikacji – Micronaut obsługuje dowolną platformę wykorzystującą strumienie reaktywne, w tym RxJava i Reactor.

Więcej informacji znajdziesz na stronie Micronaut.

Kubernetes

Kubernetes to projekt open source, który może działać w wielu różnych środowiskach, od laptopów po klastry z wieloma węzłami o wysokiej dostępności, od chmur publicznych po wdrożenia lokalne, od maszyn wirtualnych po usługi Bare Metal.

W tym module wdrożysz w Kubernetes prosty mikroserwis Micronaut oparty na Groovy, który działa w Kubernetes Engine.

Celem tego ćwiczenia w Codelabs jest uruchomienie mikroserwisu jako replikowanej usługi działającej w Kubernetes. W tym celu bierzesz kod na komputerze, zmieniasz go w obraz kontenera Dockera, a następnie uruchamiasz ten obraz w Kubernetes Engine.

Oto schemat poszczególnych części tego ćwiczenia z programowania, które pomogą Ci zrozumieć, jak elementy się ze sobą łączą. Wykorzystaj go jako pomoc podczas wykonywania ćwiczeń z programowania. Zanim dojdziesz do końca, wszystko powinno mieć sens (ale na razie możesz to pominąć).

Schemat 1 (2) ćwiczeń z programowania w Kubernetes

Na potrzeby tego ćwiczenia z programowania korzystanie z zarządzanego środowiska takiego jak Kubernetes Engine (hostowana przez Google wersja Kubernetes działająca w Compute Engine) pozwala skupić się bardziej na korzystaniu z Kubernetes, a nie na konfiguracji bazowej infrastruktury.

Jeśli zamierzasz uruchomić Kubernetes na swoim komputerze lokalnym (np. na laptopie programistycznym), prawdopodobnie warto zainteresować się usługą Minikube. Umożliwia to prostą konfigurację klastra Kubernetes z 1 węzłem na potrzeby programowania i testowania. Jeśli chcesz, możesz wykonać to ćwiczenia z programowania za pomocą Minikube.

Informacje o Jib

Jib to narzędzie typu open source, które umożliwia tworzenie obrazów Dockera i OCI na potrzeby aplikacji w Javie. Jest dostępna jako wtyczki do Maven i Gradle oraz jako biblioteka Java.

Jib ma na celu:

  • Szybkość – szybko wdrażaj zmiany. Jib dzieli aplikację na kilka warstw, dzieląc zależności od klas. Nie musisz już czekać, aż Docker utworzy ponownie Twoją aplikację w języku Java – wystarczy, że wdrożysz zmienione warstwy.
  • Łatwa do odtwarzania – ponowne kompilowanie obrazu kontenera z tą samą zawartością zawsze powoduje wygenerowanie tego samego obrazu. Nigdy nie uruchamiaj niepotrzebnej aktualizacji.
  • Daemonless – zmniejsz zależności interfejsu wiersza poleceń. Utwórz obraz Dockera w narzędziu Maven lub Gradle i przekaż go do dowolnego rejestru. Koniec z pisaniem Dockerfiles i wywołaniem kompilacji/push w usłudze Docker.

Więcej informacji na temat Jib znajdziesz na stronie projektu w GitHub.

Informacje o tym samouczku

W tym samouczku używamy przykładowego kodu z narzędzia Jib do tworzenia kontenerów dla aplikacji w Javie.

Przykładem jest prosta usługa hello world używająca platformy 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ć usługę i wdrożyć uaktualnienie.
  • Jak uzyskać dostęp do graficznego panelu Kubernetes.

Czego potrzebujesz

  • Projekt Google Cloud Platform
  • przeglądarkę, np. Chrome lub Firefox;
  • znajomość standardowych edytorów tekstu systemu Linux, takich jak Vim, EMAC lub Nano;

Jak wykorzystasz ten samouczek?

Tylko do przeczytania Przeczytaj go i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenie z tworzeniem aplikacji internetowych HTML/CSS?

Początkujący Poziom średnio zaawansowany Biegły

Jak oceniasz swoje wrażenia z korzystania z usług Google Cloud Platform?

Początkujący Poziom średnio zaawansowany Biegły
.

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub wykorzystaj już istniejący. Jeśli nie masz jeszcze konta Gmail lub G Suite, musisz je utworzyć.

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

Zapamiętaj identyfikator projektu, unikalną nazwę we wszystkich projektach Google Cloud (powyższa nazwa jest już zajęta i nie będzie Ci odpowiadać). W dalszej części tego ćwiczenia w Codelabs będzie ona określana jako PROJECT_ID.

  1. Następnie musisz włączyć płatności w Cloud Console, aby korzystać z zasobów Google Cloud.

Ukończenie tego ćwiczenia z programowania nie powinno kosztować zbyt wiele. Postępuj zgodnie z instrukcjami podanymi w sekcji „Czyszczenie” W tym samouczku znajdziesz wskazówki, jak wyłączyć zasoby, aby uniknąć naliczania opłat. Nowi użytkownicy Google Cloud mogą skorzystać z programu bezpłatnego okresu próbnego o wartości 300 USD.

3. Pobierz przykładowy kod źródłowy Micronaut

Po uruchomieniu Cloud Shell możesz za pomocą wiersza poleceń skopiować przykładowy kod źródłowy z katalogu głównego i zapisać go w katalogu zawierającym naszą przykładową usługę:

$ git clone https://github.com/GoogleContainerTools/jib.git
$ cd jib/examples/micronaut/

4. Rzuć okiem na kod

Nasza prosta usługa Micronaut składa się z kontrolera, który generuje złą sławę wiadomość Hello World:

@Controller("/hello")
class HelloController {
    @Get("/")
    String index() {
        "Hello World"
    }
}

Kontroler HelloController odpowiada na żądania w ścieżce /hello, a metoda index() akceptuje żądania HTTP GET.

Dostępna jest też klasa testowa Spock do sprawdzenia, czy w danych wyjściowych jest podany właściwy 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"
    }
}

Ten test to coś więcej niż zwykły test jednostkowy, który uruchamia ten sam stos serwera Micronaut (opartego na platformie Netty), który jest uruchamiany w środowisku produkcyjnym. Działanie kodu w usłudze będzie więc takie samo jak w testach.

Aby sprawdzić, czy wszystko jest w porządku, możesz uruchomić to polecenie:

./gradlew test

5. Lokalne uruchamianie aplikacji

Usługę Micronaut możesz uruchomić normalnie za pomocą tego polecenia Gradle:

$ ./gradlew run

Po uruchomieniu aplikacji możesz otworzyć dodatkową instancję Cloud Shell, klikając ikonę +. Następnie za pomocą narzędzia curl możesz sprawdzić, czy otrzymujesz oczekiwane wyniki:

$ 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, aby wykonać dla nas ciężką pracę, dzięki czemu nie będziemy musieli stykać się z Dockerfile.

Uruchommy polecenie, aby utworzyć kontener:

$ ./gradlew jibDockerBuild

Oto dane wyjściowe, które powinny być widoczne:

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

Skoro obraz jest już skompilowany, sprawdźmy, czy możemy wyświetlić przyjazną wiadomość powitalną, uruchamiając 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 możemy teraz uruchomić polecenie curl na drugiej karcie Cloud Shell, aby sprawdzić, czy działa prawidłowo:

$ curl localhost:8080/hello
Hello World

Aby zatrzymać kontener, kliknij Ctrl+C w Cloud Shell.

7. Przekazywanie naszej usługi skonteneryzowanej do rejestru

Gdy obraz działa zgodnie z oczekiwaniami, możesz go przekazać do Google Container Registry – prywatnego repozytorium obrazów Dockera, które jest dostępne z każdego projektu Google Cloud (ale także spoza Google Cloud Platform).

Zanim będzie można przekazać dane do rejestru, sprawdź, czy Container Registry jest włączony w naszym projekcie. Aby to zrobić, kliknij Narzędzia > Container Registry. Jeśli ta opcja nie jest włączona, powinno wyświetlić się okno. Kliknij „Włącz Container Registry API”. aby ją włączyć:

ac812e6260ac7dfb.png

Gdy rejestr będzie gotowy, prześlij do niego obraz, uruchamiając następujące 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 pozwalają pakietowi gcloud SDK skonfigurować i autoryzować dockera do przekazywania obrazów do Twojej instancji Container Registry, aby oznaczyć obraz tagiem wskazujący jego lokalizację w rejestrze, a następnie przekazać go do rejestru.

Jeśli wszystko pójdzie dobrze, po chwili powinien pojawić się w konsoli obraz kontenera: Narzędzia > Container Registry. W tej chwili dostępny jest obraz Dockera obejmujący cały projekt, do którego Kubernetes może uzyskać dostęp i administrować – jak to będzie widoczne za kilka minut.

12224c4e42183b4e.png

8. Tworzenie klastra

Teraz możesz utworzyć klaster Kubernetes Engine, ale wcześniej przejdź do sekcji Google Kubernetes Engine w konsoli internetowej i poczekaj na zainicjowanie systemu (powinno to potrwać tylko kilka sekund).

20c0587c0108b8ba.png

Klaster składa się z serwera Kubernetes master API zarządzanego przez Google oraz zbioru węzłów roboczych. Węzły robocze to maszyny wirtualne Compute Engine. Użyjmy interfejsu wiersza poleceń gcloud z sesji CloudShell, 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 zobaczysz 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

Teraz w pełni działający klaster Kubernetes obsługiwany przez Google Kubernetes Engine:

d9e1e314769753e7.png

Czas wdrożyć własną aplikację skonteneryzowaną w klastrze Kubernetes. Od teraz będziesz używać wiersza poleceń kubectl (jest on już skonfigurowany w Twoim środowisku Cloud Shell). Pozostała część tego ćwiczenia w Codelabs wymaga, aby klient i serwer Kubernetes były w wersji 1.2 lub nowszej. kubectl version wyświetli bieżącą wersję polecenia.

9. Wdrażanie aplikacji w Kubernetes

Wdrożenie Kubernetes może tworzyć i skalować wiele instancji Twojej aplikacji oraz zarządzać nimi, korzystając z nowo utworzonego obrazu kontenera. Utwórzmy wdrożenie Twojej 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ć nowo utworzone wdrożenie, po prostu uruchom 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 światu zewnętrznemu.

10. Zezwalaj na ruch zewnętrzny

Domyślnie pod jest dostępny tylko przez jego wewnętrzny adres IP w klastrze. Aby umożliwić dostęp do kontenera hello-micronaut spoza sieci wirtualnej Kubernetes, musisz udostępnić poda jako usługę Kubernetes.

W Cloud Shell możesz udostępnić poda w internecie publicznym za pomocą polecenia kubectl expose w połączeniu z flagą --type=LoadBalancer. Ta flaga jest wymagana do utworzenia dostępnego zewnętrznie adresu IP :

$ kubectl expose deployment hello-micronaut --type=LoadBalancer --port=8080

Flaga użyta w tym poleceniu wskazuje, że będziesz używać systemu równoważenia obciążenia udostępnianego przez bazową infrastrukturę (w tym przypadku system równoważenia obciążenia Compute Engine). Pamiętaj, że udostępniasz wdrożenie, a nie bezpośrednio pod. Spowoduje to równoważenie obciążenia ruchu generowanego przez powstałą usługę we wszystkich podach zarządzanych przez wdrożenie (w tym przypadku tylko 1 pod, ale później dodasz więcej replik).

Master Kubernetes tworzy system równoważenia obciążenia i powiązane reguły przekierowania Compute Engine, pule docelowe i reguły zapory sieciowej, aby zapewnić pełną dostępność usługi spoza Google Cloud Platform.

Aby znaleźć dostępny publicznie adres IP usługi, wyślij żądanie kubectl do 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ę na 2 adresy IP dotyczące Twojej usługi, które obsługują port 8080. Pierwszym z nich jest wewnętrzny adres IP, który jest widoczny tylko w sieci wirtualnej w chmurze. a drugi to zewnętrzny adres IP z zrównoważonym obciążeniem. W tym przykładzie zewnętrzny adres IP to aaa.bbb.ccc.ddd.

Usługa powinna być teraz dostępna po wpisaniu w przeglądarce tego adresu: http://<EXTERNAL_IP>:8080/hello

11. Skalowanie usług

Jedną z zaawansowanych funkcji platformy Kubernetes jest łatwość skalowania aplikacji. Załóżmy, że nagle potrzebujesz większej pojemności na aplikację. możesz po prostu zlecić kontrolerowi replikacji zarządzanie 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, musisz zadeklarować, ile instancji powinno być działających w danym momencie. Pętle uzgadniania Kubernetes po prostu dbają o to, aby rzeczywistość była zgodna z żądaniami i w razie potrzeby podjęto odpowiednie działania.

12. Wdrażanie uaktualnienia usługi

Aplikacja wdrożona w wersji produkcyjnej będzie czasami wymagała poprawek błędów lub dodatkowych funkcji. Kubernetes pomoże Ci wdrożyć nową wersję w środowisku produkcyjnym bez wpływu na użytkowników.

Najpierw zmodyfikujmy aplikację. Otwórz edytor kodu z Cloud Shell.

5aee8f3d1e003571.png

Przejdź do pola /jib/examples/micronaut/src/main/groovy/example/micronaut/HelloController.groovy i zaktualizuj 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, aktualizując ten wiersz:

version '0.2'

Następnie ponownie skompiluj aplikację i spakuj ją z najnowszymi zmianami:

$ ./gradlew jibDockerBuild

Otaguj obraz i przekaż 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

Teraz Kubernetes może sprawnie zaktualizować kontroler replikacji do nowej wersji aplikacji. Aby zmienić etykietę obrazu aktywnego kontenera, zmodyfikuj istniejący hello-micronaut deployment i zmień obraz z gcr.io/PROJECT_ID/micronaut-jib:0.1 na gcr.io/PROJECT_ID/micronaut-jib:0.2.

Aby poprosić Kubernetes o wdrożenie nowej wersji aplikacji w całym klastrze po jednej instancji, możesz użyć polecenia kubectl set image z aktualizacją kroczącą:

$ 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 popełniłeś błąd w nowej wersji aplikacji? Być może nowa wersja zawiera błąd i musisz szybko przywrócić poprzednią wersję. W Kubernetes można łatwo przywrócić poprzedni stan. Przywróćmy aplikację, uruchamiając polecenie:

$ kubectl rollout undo deployment/hello-micronaut

Jeśli spojrzymy na dane wyjściowe usługi, wrócimy do początkowego tekstu „Hello World”. .

14. Podsumowanie

W tym kroku skonfigurujesz prostą usługę Micronaut hello world opartą na Apache Groovy i uruchomisz ją bezpośrednio z poziomu Cloud Shell, spakujesz ją jako kontener z Jib i wdrożysz w Google Kubernetes Engine.

15. Gratulacje!

Wiesz już, jak utworzyć i wdrożyć nowy internetowy mikroserwis Apache Groovy / Mikronaut w Kubernetes w Google Kubernetes Engine.

Więcej informacji

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.