Wdrażanie w Kubernetes Engine aplikacji Spring Boot w Javie w Google Kubernetes Engine

1. Zanim zaczniesz

Kubernetes to projekt 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 i od maszyn wirtualnych po serwery fizyczne.

W tych ćwiczeniach z programowania wdrożysz prostą aplikację internetową Spring Boot w Javie w Kubernetes w GKE. Celem jest uruchomienie aplikacji internetowej jako replikowanej aplikacji w Kubernetes. Kod opracowany na komputerze przekształcisz w obraz kontenera Dockera i uruchomisz go w GKE.

Będziesz używać GKE, w pełni zarządzanej usługi Kubernetes w Google Cloud, dzięki czemu możesz skupić się na korzystaniu z Kubernetes, a nie na konfigurowaniu infrastruktury bazowej.

Jeśli chcesz uruchomić Kubernetes na komputerze lokalnym, np. na laptopie deweloperskim, zapoznaj się z Minikube, które oferuje prostą konfigurację jednowęzłowego klastra Kubernetes do celów programistycznych i testowych. Jeśli chcesz, możesz skorzystać z Minikube, aby przejść przez codelab.

W tym ćwiczeniu z programowania użyjemy przykładowego kodu z przewodnika Tworzenie aplikacji za pomocą Spring Boot.

Wymagania wstępne

  • Znajomość języka programowania Java i narzędzi
  • Znajomość standardowych edytorów tekstu systemu Linux, takich jak Vim, Emacs i nano.

Co musisz zrobić

  • spakować prostą aplikację Java jako kontener Dockera,
  • Utwórz klaster Kubernetes w GKE.
  • Wdróż aplikację w Javie w Kubernetes w GKE.
  • skalować w górę usługę i wdrażać uaktualnienie,
  • Dostęp do panelu, internetowego interfejsu Kubernetes.

Czego potrzebujesz

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Zawsze możesz ją zaktualizować.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się tym przejmować. W większości ćwiczeń z programowania musisz odwoływać się do identyfikatora projektu (zwykle oznaczanego jako PROJECT_ID). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować własnej nazwy i sprawdzić, czy jest dostępna. Po tym kroku nie można go zmienić i pozostaje on taki przez cały czas trwania projektu.
  • Warto wiedzieć, że istnieje też trzecia wartość, numer projektu, której używają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Wykonanie tego laboratorium nie będzie kosztować dużo, a może nawet nic. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub projekt. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z opisem tego środowiska. Jeśli pojawił się ekran pośredni, kliknij Dalej.

9c92662c6a846a5c.png

Uzyskanie dostępu do środowiska Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

9f0e51b578fecce5.png

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym module, a być może wszystkie, możesz wykonać w przeglądarce.

Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.

  1. Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list

Wynik polecenia

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project

Wynik polecenia

[core]
project = <PROJECT_ID>

Jeśli nie, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Wynik polecenia

Updated property [core/project].

3. Pobieranie kodu źródłowego

Po uruchomieniu Cloud Shell możesz użyć wiersza poleceń, aby sklonować przykładowy kod źródłowy w katalogu głównym.

$ git clone https://github.com/spring-guides/gs-spring-boot.git
$ cd gs-spring-boot/complete

4. Lokalne uruchamianie aplikacji

  1. Sprawdź, czy zmienna JAVA_HOME jest ustawiona na prawidłową wersję:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
  1. Aplikację Spring Boot możesz uruchomić normalnie za pomocą wtyczki Spring Boot.
$ ./mvnw -DskipTests spring-boot:run
  1. Po uruchomieniu aplikacji kliknij Podgląd w przeglądarce1a94d5bd10bfc072.png na pasku narzędzi Cloud Shell i wybierz Podejrzyj na porcie 8080.

6252b94905f3f7bd.png

W przeglądarce otworzy się karta, która połączy się z uruchomionym serwerem.

9b6c29059957bd0.jpeg

5. Pakowanie aplikacji w Javie jako kontenera Dockera

Następnie musisz przygotować aplikację do uruchomienia w klastrze Kubernetes. Pierwszym krokiem jest zdefiniowanie kontenera i jego zawartości.

  1. Utwórz plik JAR do wdrożenia aplikacji.
$ ./mvnw -DskipTests package
  1. Włącz interfejs Artifact Registry API, aby przechowywać utworzony obraz kontenera.
$ gcloud services enable artifactregistry.googleapis.com
  1. Utwórz nowe repozytorium Dockera, jeśli jeszcze go nie masz. Aby móc przekazać do repozytorium obrazy, musisz je utworzyć:
$ gcloud artifacts repositories create codelabrepo     --repository-format=docker --location=us-central1 
  1. Obraz będzie miał format:

{LOCATION}-docker.pkg.dev/{PROJECT-ID}/{REPOSITORY}/{IMAGE-NAME}

Jeśli na przykład utworzysz repozytorium w lokalizacji us-central1 o nazwie codelabrepo i chcesz nazwać obraz hello-java:v1, obraz będzie miał nazwę:

us-central1-docker.pkg.dev/{PROJECT-ID}/codelabrepo/hello-java:v1

  1. Użyj Jib, aby utworzyć obraz kontenera i przenieść go do Artifact Registry.
$ export GOOGLE_CLOUD_PROJECT=`gcloud config list --format="value(core.project)"`

$ ./mvnw -DskipTests com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/${GOOGLE_CLOUD_PROJECT}/codelabrepo/hello-java:v1
  1. Obraz kontenera powinien być widoczny na stronie Obrazy w Artifact Registry w konsoli Cloud. Masz teraz dostępny obraz Dockera w całym projekcie, do którego Kubernetes może uzyskać dostęp i którym może zarządzać. Zobaczysz to za kilka minut.
  2. (Opcjonalnie) Po zakończeniu (pobieranie i wyodrębnianie wszystkich plików zajmie trochę czasu) przetestuj obraz za pomocą tego polecenia, które uruchomi kontener Dockera jako proces w tle na porcie 8080 z nowo utworzonego obrazu kontenera. Jeśli napotkasz problemy z uprawnieniami, najpierw uruchom gcloud auth configure-docker us-central1-docker.pkg.dev:
$ docker run -ti --rm -p 8080:8080 \
  us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Ponownie skorzystaj z funkcji podglądu w przeglądarce Cloud Shell.

6252b94905f3f7bd.png

  1. W nowej karcie powinna się otworzyć strona domyślna. Gdy sprawdzisz, że aplikacja działa lokalnie w kontenerze Docker, możesz zatrzymać działający kontener, naciskając Control+C.

6. Tworzenie klastra

Możesz już utworzyć klaster GKE. Klaster składa się z serwera Kubernetes API zarządzanego przez Google i zestawu węzłów roboczych. Węzły robocze to maszyny wirtualne Compute Engine.

  1. Najpierw upewnij się, że włączone są powiązane funkcje interfejsu API.
$ gcloud services enable compute.googleapis.com container.googleapis.com
  1. Utwórz klaster z 2 węzłami n1-standard-1 (wykonanie tego kroku może potrwać kilka minut).
$ gcloud container clusters create hello-java-cluster \
  --num-nodes 2 \
  --machine-type n1-standard-1 \
  --zone us-central1-c

Na koniec powinien pojawić się utworzony klaster.

Creating cluster hello-java-cluster...done.
Created [https://container.googleapis.com/v1/projects/...].
kubeconfig entry generated for hello-dotnet-cluster.
NAME                  ZONE            MASTER_VERSION  
hello-java-cluster  us-central1-c  ...

Powinien być teraz dostępny w pełni funkcjonalny klaster Kubernetes obsługiwany przez GKE.

758c7fca14f70623.png

Czas wdrożyć skonteneryzowaną aplikację w klastrze Kubernetes. Od teraz będziesz używać wiersza poleceń kubectl (skonfigurowanego już w środowisku powłoki Cloud Shell). Pozostała część tego samouczka wymaga, aby wersja klienta i serwera Kubernetes była co najmniej 1.2. kubectl version wyświetli aktualną wersję polecenia.

7. Wdrażanie aplikacji w Kubernetes

  1. Wdrożenie Kubernetes może tworzyć wiele instancji aplikacji, zarządzać nimi i je skalować za pomocą utworzonego przez Ciebie obrazu kontenera. Wdróż jedną instancję aplikacji w Kubernetes za pomocą polecenia kubectl run.
$ kubectl create deployment hello-java --image=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1
  1. Aby wyświetlić utworzone wdrożenie, uruchom to polecenie:
$ kubectl get deployments

NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   1         1         1            1           37s
  1. Aby wyświetlić instancje aplikacji utworzone przez wdrożenie, uruchom to polecenie:
$ kubectl get pods

NAME                         READY     STATUS    RESTARTS   AGE
hello-java-714049816-ztzrb   1/1       Running   0          57s

W tym momencie kontener powinien działać pod kontrolą Kubernetes, ale nadal musisz udostępnić go do użytku publicznego.

8. Zezwalaj na ruch zewnętrzny

Domyślnie pod jest dostępny tylko przez wewnętrzny adres IP w klastrze. Aby kontener hello-java był dostępny spoza wirtualnej sieci Kubernetes, musisz udostępnić poda jako usługę Kubernetes.

  1. W Cloud Shell możesz udostępnić poda w publicznym internecie, tworząc usługę Kubernetes LoadBalancer.
$ kubectl create service loadbalancer hello-java --tcp=8080:8080

Pamiętaj, że bezpośrednio udostępniasz wdrożenie, a nie poda. Spowoduje to zrównoważenie obciążenia ruchem w usłudze na wszystkich podach zarządzanych przez wdrożenie (w tym przypadku tylko na jednym podzie, ale później dodasz więcej replik).

Master Kubernetes tworzy system równoważenia obciążenia oraz powiązane z nim reguły przekierowania Compute Engine, pule docelowe i reguły zapory, aby usługa była w pełni dostępna spoza Google Cloud.

  1. Aby znaleźć publicznie dostępny adres IP usługi, wystarczy wysłać żądanie kubectl, aby wyświetlić listę wszystkich usług klastra.
$ kubectl get services

NAME         CLUSTER-IP     EXTERNAL-IP      PORT(S)    AGE
hello-java   10.3.253.62    aaa.bbb.ccc.ddd  8080/TCP    1m
kubernetes   10.3.240.1     <none>           443/TCP    5m
  1. Usługa powinna być teraz dostępna pod adresem http://<EXTERNAL_IP>:8080.

9. Skalowanie usługi

Jedną z najważniejszych funkcji Kubernetes jest łatwość skalowania aplikacji. Załóżmy, że nagle potrzebujesz większej pojemności dla swojej aplikacji. Wystarczy, że powiesz kontrolerowi replikacji, aby zarządzał nową liczbą replik instancji aplikacji.

$ kubectl scale deployment hello-java --replicas=3

deployment "hello-java" scaled

$ kubectl get deployment
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-java   3         3         3            3           22m

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.

10. Wdrażanie uaktualnienia usługi

W pewnym momencie aplikacja wdrożona w środowisku produkcyjnym będzie wymagać poprawek lub dodatkowych funkcji. Kubernetes może pomóc Ci w wdrożeniu nowej wersji w środowisku produkcyjnym bez wpływu na użytkowników.

  1. W menu Cloud Shell kliknij Otwórz edytor 2109d75686c889a.png, aby otworzyć edytor kodu.
  2. Przejdź do src/main/java/com/example/springboot/HelloController.java i zaktualizuj wartość odpowiedzi.
package com.example.springboot;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;

@RestController
public class HelloController {

    @RequestMapping("/")
    public String index() {
        return "Greetings from Google Kubernetes Engine!";
    }
}
  1. Użyj Jib, aby utworzyć i przesłać nową wersję obrazu kontenera. Tworzenie i przesyłanie zaktualizowanego obrazu powinno być znacznie szybsze, ponieważ w pełni wykorzystujesz pamięć podręczną.
$ ./mvnw -DskipTests package com.google.cloud.tools:jib-maven-plugin:build -Dimage=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Kubernetes może teraz bezproblemowo zaktualizować kontroler replikacji do nowej wersji aplikacji.

  1. Aby zmienić etykietę obrazu uruchomionego kontenera, musisz edytować istniejące wdrożenie hello-java i zmienić obraz z us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v1

do: us-central1-docker.pkg.dev/PROJECT_ID/codelabrepo/hello-java:v2

  1. Za pomocą polecenia kubectl set image możesz poprosić Kubernetes o wdrożenie nowej wersji aplikacji w całym klastrze po jednej instancji naraz za pomocą aktualizacji kroczących.
$ kubectl set image deployment/hello-java hello-java=us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

deployment "hello-java" image updated
  1. Sprawdź ponownie http://EXTERNAL_IP:8080, aby upewnić się, że zwraca nową odpowiedź.

11. 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 przywrócić poprzedni stan. Wycofaj zmiany w aplikacji, uruchamiając następujące polecenie:

$ kubectl rollout undo deployment/hello-java

Gdy ponownie klikniesz http://EXTERNAL_IP:8080, zobaczysz starą odpowiedź.

12. Gratulacje

Dowiedzieliśmy się, jak utworzyć i wdrożyć nową aplikację internetową opartą na Javie w Kubernetes w GKE.

Czyszczenie danych

$ gcloud container clusters delete hello-java-cluster --zone us-central1-c

$ gcloud container images delete us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v1 us-central1-docker.pkg.dev/$GOOGLE_CLOUD_PROJECT/codelabrepo/hello-java:v2

Więcej informacji