Migracja z aplikacji Google App Engine w Javie do Cloud Run przy użyciu Dockera

1. Przegląd

Ta seria ćwiczeń z programowania (samodzielnych samouczków praktycznych) ma pomóc deweloperom aplikacji w Javie na platformie Google App Engine (Standard) w modernizacji aplikacji poprzez przeprowadzenie ich przez serię migracji. Wykonując te czynności, możesz zaktualizować aplikację, aby była bardziej przenośna, i zdecydować się na jej skonteneryzowanie na potrzeby Cloud Run, siostrzanej usługi Google Cloud do hostowania kontenerów, która jest podobna do App Engine, oraz innych usług hostowania kontenerów.

Z tego samouczka dowiesz się, jak konteneryzować aplikację App Engine na potrzeby wdrożenia w pełni zarządzanej usłudze Cloud Run za pomocą pliku Dockerfile. Pliki Dockerfile to najbardziej praktyczna metoda wdrażania w przypadku tej migracji, ale oferują też najwięcej opcji dostosowywania procesu kompilacji.

Oprócz tego, że dowiesz się, jak przejść z App Engine na Cloud Run, poznasz też sposób uaktualnienia aplikacji App Engine w Javie 8 do Javy 17.

Jeśli aplikacja, którą chcesz przenieść, w dużym stopniu korzysta ze starszych usług pakietowych App Engine lub innych funkcji specyficznych dla App Engine, lepszym punktem wyjścia niż ten codelab może być przewodnik Dostęp do usług pakietowych App Engine w przypadku Javy 11/17.

Dowiesz się, jak:

  • Użyj Cloud Shell.
  • Włączanie interfejsów Cloud Run API, Artifact Registry API i Cloud Build API
  • Konteneryzowanie aplikacji za pomocą Dockera i Cloud Build
  • Wdrażanie obrazów kontenerów w Cloud Run

Czego potrzebujesz

Ankieta

Jak zamierzasz korzystać z tego samouczka?

Tylko przeczytaj Przeczytaj i wykonaj ćwiczenia

Jak oceniasz swoje doświadczenie z językiem Java?

Początkujący Średnio zaawansowany Zaawansowany

Jak oceniasz korzystanie z usług Google Cloud?

Początkujący Średnio zaawansowany Zaawansowany

2. Tło

Systemy PaaS, takie jak App Engine i Cloud Functions, zapewniają zespołowi i aplikacji wiele udogodnień, np. umożliwiają administratorom systemów i inżynierom DevOps skupienie się na tworzeniu rozwiązań. Platformy bezserwerowe umożliwiają automatyczne skalowanie aplikacji w górę w miarę potrzeb, skalowanie w dół do zera z płatnościami za użycie, co pomaga kontrolować koszty, oraz korzystanie z różnych popularnych języków programowania.

Elastyczność kontenerów jest jednak również atrakcyjna. Kontenery umożliwiają wybór dowolnego języka, biblioteki i pliku binarnego, dzięki czemu łączą w sobie wygodę technologii bezserwerowej i elastyczność kontenerów. Właśnie tym zajmuje się Google Cloud Run.

Ten przewodnik nie obejmuje informacji o tym, jak korzystać z Cloud Run. Znajdziesz je w dokumentacji Cloud Run. Chcemy, abyś zapoznał się z tym, jak umieścić aplikację App Engine w kontenerze na potrzeby Cloud Run (lub innych usług hostowanych w kontenerach). Zanim przejdziesz dalej, musisz wiedzieć, że Twoje wrażenia z użytkowania będą nieco inne.

Z tego przewodnika dowiesz się, jak tworzyć i wdrażać kontenery. Dowiesz się, jak skonteneryzować aplikację za pomocą pliku Dockerfile, przeprowadzić migrację z konfiguracji App Engine i (opcjonalnie) zdefiniować etapy kompilacji dla Cloud Build. Będzie to wymagało rezygnacji z niektórych funkcji specyficznych dla App Engine. Jeśli nie chcesz tego robić, możesz przejść na środowisko wykonawcze Java 11/17, pozostawiając aplikacje w App Engine.

3. Konfiguracja/przygotowanie

1. Konfigurowanie projektu

W tym samouczku użyjesz przykładowej aplikacji z repozytorium appengine-java-migration-samples w nowym projekcie. Sprawdź, czy projekt ma aktywne konto rozliczeniowe.

Jeśli chcesz przenieść istniejącą aplikację App Engine do Cloud Run, możesz użyć jej zamiast tej w samouczku.

Aby włączyć w projekcie niezbędne interfejsy API, uruchom to polecenie:

gcloud services enable artifactregistry.googleapis.com cloudbuild.googleapis.com run.googleapis.com

2. Pobieranie przykładowej aplikacji podstawowej

Sklonuj przykładową aplikację na własnym komputerze lub w Cloud Shell, a następnie przejdź do folderu baseline.

Przykładowa aplikacja to aplikacja Datastore oparta na Javie 8 i serwletach, która jest przeznaczona do wdrożenia w App Engine. Postępuj zgodnie z instrukcjami w pliku README, aby przygotować tę aplikację do wdrożenia w App Engine.

3. (Opcjonalnie) Wdróż aplikację podstawową

Poniższe czynności są konieczne tylko wtedy, gdy chcesz sprawdzić, czy aplikacja działa w App Engine, zanim przeniesiemy ją do Cloud Run.

Postępuj zgodnie z instrukcjami w pliku README.md:

  1. Instalowanie interfejsu wiersza poleceń gcloud i zapoznawanie się z nim
  2. Zainicjuj gcloud CLI na potrzeby projektu za pomocą polecenia gcloud init.
  3. Utwórz projekt App Engine za pomocą gcloud app create
  4. Wdrażanie przykładowej aplikacji w App Engine
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. Sprawdź, czy aplikacja działa w App Engine bez problemów.

4. Tworzenie repozytorium Artifact Registry

Po umieszczeniu aplikacji w kontenerze musisz mieć miejsce, do którego możesz przesłać i w którym możesz przechowywać obrazy. Zalecany sposób na Google Cloud to użycie Artifact Registry.

Utwórz repozytorium o nazwie migration za pomocą gcloud w ten sposób:

gcloud artifacts repositories create migration --repository-format=docker \
--description="Docker repository for the migrated app" \
--location="northamerica-northeast1"

Pamiętaj, że to repozytorium używa typu formatu docker, ale dostępnych jest kilka typów repozytoriów.

Na tym etapie masz już podstawową aplikację App Engine, a projekt w chmurze Google Cloud jest gotowy do przeniesienia jej do Cloud Run.

4. Modyfikowanie plików aplikacji

Jeśli Twoja aplikacja w dużym stopniu korzysta z starszych usług pakietowych App Engine, konfiguracji lub innych funkcji dostępnych tylko w App Engine, zalecamy dalsze korzystanie z tych usług podczas uaktualniania do nowego środowiska wykonawczego. W tym laboratorium dowiesz się, jak przeprowadzić migrację aplikacji, które już korzystają z samodzielnych usług lub można je przekształcić, aby to robiły.

1. Przechodzenie na Javę 17

Jeśli Twoja aplikacja działa na Javie 8, rozważ przejście na nowszą wersję LTS, np. 11 lub 17, aby mieć dostęp do aktualizacji zabezpieczeń i nowych funkcji języka.

Zacznij od zaktualizowania właściwości w obiekcie pom.xml, aby uwzględnić te elementy:

<properties>
    <java.version>17</java.version>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
</properties>

Ustawisz w ten sposób wersję projektu na 17, poinformujesz wtyczkę kompilatora, że chcesz mieć dostęp do funkcji języka Java 17, i sprawisz, że skompilowane klasy będą zgodne z maszyną JVM Java 17.

2. w tym serwer WWW,

Istnieje wiele różnic między App Engine a Cloud Run, które warto wziąć pod uwagę podczas przenoszenia usług między tymi platformami. Jedna z różnic polega na tym, że środowisko wykonawcze Java 8 w App Engine udostępniało serwer Jetty i zarządzało nim na potrzeby hostowanych aplikacji, a Cloud Run tego nie robi. Użyjemy Spring Boot, aby zapewnić serwer WWW i kontener serwletów.

Dodaj te zależności:

<dependencies>
<!-- ... -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
       <version>2.6.6</version>
       <exclusions>
           <!-- Exclude the Tomcat dependency -->
           <exclusion>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-starter-tomcat</artifactId>
           </exclusion>
       </exclusions>
   </dependency>
   <!-- Use Jetty instead -->
   <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-jetty</artifactId>
       <version>2.6.6</version>
   </dependency>
<!-- ... -->
</dependencies>

Spring Boot domyślnie osadza serwer Tomcat, ale ten przykład wyklucza ten artefakt i pozostaje przy Jetty, aby zminimalizować różnice w domyślnym działaniu po migracji.

3. Konfiguracja Spring Boot

Spring Boot będzie mógł ponownie użyć servletów bez modyfikacji, ale będzie wymagał pewnej konfiguracji, aby można było je wykryć.

Utwórz tę klasę MigratedServletApplication.java w pakiecie com.example.appengine:

package com.example.appengine;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@ServletComponentScan
@SpringBootApplication
@EnableAutoConfiguration
public class MigratedServletApplication {
    public static void main(String[] args) {
        SpringApplication.run(MigratedServletApplication.class, args);
    }
}

Pamiętaj, że obejmuje to adnotację @ServletComponentScan, która (w bieżącym pakiecie domyślnie) będzie wyszukiwać wszystkie @WebServlets i udostępniać je zgodnie z oczekiwaniami.

4. Pakowanie aplikacji jako pliku JAR

Chociaż można umieścić aplikację w kontenerze zaczynając od pliku WAR, jest to łatwiejsze, jeśli spakujesz aplikację jako wykonywalny plik JAR. Nie wymaga to dużej konfiguracji, zwłaszcza w przypadku projektów, w których jako narzędzie do kompilacji używany jest Maven, ponieważ pakowanie w formacie JAR jest domyślnym działaniem.

Usuń tag packaging z pliku pom.xml:

<packaging>war</packaging>

Następnie dodaj spring-boot-maven-plugin:

<plugins>
<!-- ... -->
  <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.6.6</version>
  </plugin>
<!-- ... -->
</plugins>

5. Migracja z konfiguracji, usług i zależności App Engine

Jak wspomnieliśmy na początku tego przewodnika, Cloud Run i App Engine zostały zaprojektowane tak, aby zapewniać różne wrażenia użytkownikom. Niektóre funkcje oferowane przez App Engine od razu po wyjęciu z pudełka, takie jak usługi CronTask Queue, trzeba będzie odtworzyć ręcznie. Omówimy je szczegółowo w dalszych modułach.

Przykładowa aplikacja nie korzysta ze starszych usług pakietowych, ale użytkownicy, których aplikacje z nich korzystają, mogą zapoznać się z tymi przewodnikami:

Od teraz będziesz wdrażać w Cloud Run, więc możesz usunąć appengine-maven-plugin:

<plugin>
 <groupId>com.google.cloud.tools</groupId>
 <artifactId>appengine-maven-plugin</artifactId>
 <version>2.4.1</version>
 <configuration>
   <!-- can be set w/ -DprojectId=myProjectId on command line -->
   <projectId>${app.projectId}</projectId>
   <!-- set the GAE version or use "GCLOUD_CONFIG" for an autogenerated GAE version -->
   <version>GCLOUD_CONFIG</version>
 </configuration>
</plugin>

5. Konteneryzacja aplikacji

W tym momencie możesz poinformować Cloud Build, jak skompilować kontener aplikacji. W przypadku tej metody konteneryzacji nie jest wymagany osobny plik konfiguracji kompilacji (cloudbuild.yaml). Jako punkt początkowy możemy po prostu zdefiniować minimalny plik Dockerfile:

FROM eclipse-temurin

ARG JAR_FILE=JAR_FILE_MUST_BE_SPECIFIED_AS_BUILD_ARG

COPY ${JAR_FILE} app.jar

ENTRYPOINT ["java", "-jar","/app.jar"]

Ten plik Dockerfile łączy wersję uber-jar usługi Spring Boot w jednej warstwie. Jest to najprostsze podejście do konteneryzacji Dockerfile, ale ma wiele wad, zwłaszcza w przypadku powtarzających się sytuacji, w których zależności są stosunkowo stabilne. Właśnie dlatego ta metoda konteneryzacji jest uważana za bardziej zaawansowaną. Z drugiej strony napisanie własnego pliku Dockerfile daje pełną kontrolę nad obrazem bazowym i dostęp do korzyści związanych z wydajnością, jakie daje starannie warstwowy obraz.

2**. Uruchom proces kompilacji**

Po poinformowaniu Cloud Build o odpowiednich krokach kompilacji możesz wdrożyć aplikację jednym kliknięciem.

Uruchom to polecenie:

gcloud builds submit --tag LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/IMAGE_NAME

Zastąp wartości zastępcze w powyższym poleceniu tymi wartościami:

  • LOCATION: lokalizacja regionalna lub obejmująca wiele regionów w przypadku repozytorium.
  • PROJECT_ID: identyfikator Twojego projektu Cloud.
  • REPOSITORY: nazwa repozytorium Artifact Registry.
  • IMAGE_NAME: nazwa obrazu kontenera.

Po zakończeniu procesu obraz kontenera zostanie skompilowany, zapisany w Artifact Registry i wdrożony w Cloud Run.

Po ukończeniu tego laboratorium Twój projekt powinien wyglądać tak samo jak ten w folderze mod4-migrate-to-cloud-run.

I to wszystko! Udało Ci się przenieść aplikację App Engine w Java 8 do Java 17 i Cloud Run. Teraz lepiej rozumiesz, co trzeba zrobić, aby przełączyć się na inne opcje hostingu.

6. Podsumowanie i czyszczenie

Gratulacje! Udało Ci się uaktualnić, skonteneryzować i przenieść aplikację. To koniec tego samouczka.

Następnym krokiem jest zapoznanie się z funkcjami CI/CD i zabezpieczeń łańcucha dostaw oprogramowania, które są teraz dostępne dzięki możliwości wdrażania za pomocą Cloud Build:

Opcjonalnie: zwalnianie miejsca i/lub wyłączanie usługi

Jeśli w ramach tego samouczka wdrożysz przykładową aplikację w App Engine, pamiętaj, aby ją wyłączyć, aby uniknąć obciążenia konta opłatami. Gdy zechcesz przejść do kolejnych ćwiczeń, możesz ponownie włączyć tę funkcję. Gdy aplikacje App Engine są wyłączone, nie generują ruchu, a tym samym nie powodują naliczania opłat. Jednak korzystanie z Datastore może podlegać opłatom, jeśli przekroczy bezpłatny limit. Usuń więc wystarczającą ilość danych, aby zmieścić się w tym limicie.

Jeśli jednak nie chcesz kontynuować migracji i chcesz wszystko całkowicie usunąć, możesz usunąć usługę lub całkowicie zamknąć projekt.

7. Dodatkowe materiały

Problemy i opinie dotyczące ćwiczeń z programowania modułu migracji App Engine

Jeśli zauważysz jakieś problemy z tym kursem, najpierw poszukaj rozwiązania, a dopiero potem zgłoś problem. Linki do wyszukiwania i tworzenia nowych problemów:

Materiały dotyczące migracji

Zasoby online

Poniżej znajdziesz zasoby online, które mogą być przydatne w tym samouczku:

App Engine

Inne informacje o chmurze

Filmy

Licencja

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