Migrazione dall'app Java di Google App Engine a Cloud Run con Docker

1. Panoramica

Questa serie di codelab (tutorial pratici con il proprio ritmo) ha lo scopo di aiutare gli sviluppatori Java di Google App Engine (Standard) a modernizzare le loro app guidandoli attraverso una serie di migrazioni. Se segui questi passaggi, puoi aggiornare l'app per renderla più portabile e decidere di eseguirne il containerizzazione per Cloud Run, il servizio di hosting di container di Google Cloud complementare ad App Engine, e per altri servizi di hosting di container.

Questo tutorial insegna come containerizzare un'app App Engine per eseguire il deployment nel servizio completamente gestito Cloud Run con un Dockerfile. I file Docker sono il metodo di deployment più pratico per questa migrazione, ma offrono anche il maggior numero di opzioni per personalizzare il processo di compilazione.

Oltre a insegnarti i passaggi necessari per passare da App Engine a Cloud Run, imparerai anche come eseguire l'upgrade di un'app App Engine Java 8 a Java 17.

Se l'applicazione di cui vuoi eseguire la migrazione fa un uso intensivo dei servizi integrati legacy di App Engine o di altre funzionalità specifiche di App Engine, la guida Accesso ai servizi integrati di App Engine per Java 11/17 potrebbe essere un punto di partenza migliore di questo codelab.

Imparerai a utilizzare

  • Utilizzare Cloud Shell
  • Abilita le API Cloud Run, Artifact Registry e Cloud Build
  • Containerizza la tua app con Docker, Docker e Cloud Build
  • Esegui il deployment delle immagini container in Cloud Run

Che cosa ti serve

Sondaggio

Come utilizzerai questo tutorial?

Leggi solo Leggi e completa gli esercizi

Come giudichi la tua esperienza con Java?

Principiante Intermedio Proficiente

Come giudichi la tua esperienza di utilizzo dei servizi Google Cloud?

Principiante Intermedio Proficiente

2. Sfondo

I sistemi PaaS come App Engine e Cloud Functions offrono molti vantaggi per il team e l'applicazione, ad esempio consentono agli amministratori di sistema e ai DevOps di concentrarsi sulla creazione di soluzioni. Con le piattaforme serverless, la tua app può scalare automaticamente in base alle esigenze, scalare fino a zero con la fatturazione pay-per-use per contribuire a controllare i costi e utilizzare una serie di linguaggi di sviluppo comuni.

Tuttavia, anche la flessibilità dei container è convincente. Con la possibilità di scegliere qualsiasi linguaggio, libreria e programma binario, i container offrono il meglio di entrambi i mondi: la comodità del serverless e la flessibilità dei container. Questo è lo scopo di Google Cloud Run.

L'apprendimento dell'utilizzo di Cloud Run non rientra nell'ambito di questo codelab, ma è trattato nella documentazione di Cloud Run. L'obiettivo è acquisire familiarità con la containerizzazione dell'app App Engine per Cloud Run (o altri servizi ospitati su container). Prima di procedere, devi sapere alcuni aspetti, in particolare che la tua esperienza utente sarà leggermente diversa.

In questo codelab imparerai a creare e implementare i container. Scoprirai come eseguire il containerizzazione dell'app con un Dockerfile, eseguire la migrazione dalla configurazione di App Engine e (facoltativo) definire i passaggi di compilazione per Cloud Build. Ciò comporterà l'abbandono di alcune funzionalità specifiche di App Engine. Se preferisci non seguire questa strada, puoi comunque eseguire l'upgrade a un runtime Java 11/17 mantenendo le tue app su App Engine.

3. Configurazione/preparazione

1. Configura progetto

Per questo tutorial, utilizzerai un'app di esempio del repository appengine-java-migration-samples in un nuovo progetto. Assicurati che il progetto abbia un account di fatturazione attivo.

Se intendi spostare un'app App Engine esistente in Cloud Run, puoi utilizzare questa app per seguire la procedura.

Esegui il seguente comando per abilitare le API necessarie per il tuo progetto:

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

2. Ottieni l'app di esempio di riferimento

Clona l'app di esempio sulla tua macchina o in Cloud Shell, quindi vai alla cartella baseline.

L'esempio è un'app Datastore basata su Java 8 e servlet destinata al deployment su App Engine. Segui le istruzioni nel file README su come preparare questa app per il deployment in App Engine.

3. (Facoltativo) Esegui il deployment dell'app di riferimento

I passaggi che seguono sono necessari solo se vuoi verificare che l'app funzioni su App Engine prima di eseguire la migrazione a Cloud Run.

Fai riferimento ai passaggi descritti nel file README.md:

  1. Installa/Acquisisci familiarità con l'interfaccia a riga di comando gcloud
  2. Inizializza gcloud CLI per il tuo progetto con gcloud init
  3. Crea il progetto App Engine con gcloud app create
  4. Esegui il deployment dell'app di esempio in App Engine
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. Verifica che l'app venga eseguita su App Engine senza problemi

4. Crea un repository Artifact Registry

Dopo aver containerizzato l'app, dovrai trovare un luogo in cui eseguire il push e archiviare le immagini. Il modo consigliato per farlo su Google Cloud è utilizzare Artifact Registry.

Crea il repository denominato migration con gcloud nel seguente modo:

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

Tieni presente che questo repository utilizza il tipo di formato docker, ma sono disponibili diversi tipi di repository.

A questo punto, hai l'app App Engine di riferimento e il tuo progetto Google Cloud è pronto per la migrazione a Cloud Run.

4. Modifica file delle applicazioni

Nei casi in cui la tua app utilizzi frequentemente la configurazione, i servizi in bundle legacy di App Engine o altre funzionalità esclusive di App Engine, ti consigliamo di continuare ad accedere a questi servizi durante l'upgrade al nuovo runtime. Questo codelab illustra un percorso di migrazione per le applicazioni che utilizzano già servizi autonomi o che è possibile eseguire il refactoring.

1. Upgrade a Java 17

Se la tua app utilizza Java 8, valuta la possibilità di eseguire l'upgrade a un candidato LTS successivo come 11 o 17 per stare al passo con gli aggiornamenti della sicurezza e ottenere l'accesso alle nuove funzionalità del linguaggio.

Per iniziare, aggiorna le proprietà in pom.xml in modo da includere quanto segue:

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

In questo modo, la versione del progetto verrà impostata su 17, il plug-in del compilatore verrà informato che vuoi accedere alle funzionalità del linguaggio Java 17 e che vuoi che le classi compilate siano compatibili con la JVM Java 17.

2. Incluso un server web

Esistono una serie di differenze tra App Engine e Cloud Run che vale la pena considerare quando passi da un servizio all'altro. Una differenza è che, mentre il runtime Java 8 di App Engine fornisce e gestisce un server Jetty per le app che ospita, Cloud Run no. Utilizzeremo Spring Boot per fornirci un server web e un contenitore servlet.

Aggiungi le seguenti dipendenze:

<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 incorpora un server Tomcat per impostazione predefinita, ma questo esempio escluderà l'elemento e utilizzerà Jetty per ridurre al minimo le differenze nel comportamento predefinito dopo la migrazione.

3. Configurazione di Spring Boot

Sebbene Spring Boot possa riutilizzare i servlet senza modifiche, sarà necessaria una certa configurazione per assicurarsi che siano rilevabili.

Crea la seguente classe MigratedServletApplication.java nel pacchetto 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);
    }
}

Tieni presente che è inclusa l'annotazione @ServletComponentScan, che cercherà (per impostazione predefinita nel pacchetto attuale) tutti i @WebServlets e li renderà disponibili come previsto.

4. Pacchettizzazione dell'app come JAR

Sebbene sia possibile eseguire il containerizzazione dell'app a partire da un file WAR, è più semplice se la pacchettizzi come file JAR eseguibile. Ciò non richiederà molta configurazione, in particolare per i progetti che utilizzano Maven come strumento di compilazione, poiché il packaging jar è il comportamento predefinito.

Rimuovi il tag packaging nel file pom.xml:

<packaging>war</packaging>

Poi, aggiungi 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. Migrazione da configurazione, servizi e dipendenze di App Engine

Come accennato all'inizio del codelab, Cloud Run e App Engine sono progettati per offrire esperienze utente diverse. Alcune funzionalità offerte da App Engine, come i servizi Cron e Coda di lavoro, devono essere ricreati manualmente e verranno trattate in modo più dettagliato nei moduli successivi.

L'app di esempio non utilizza i servizi legacy in bundle, ma gli utenti le cui app lo fanno possono fare riferimento alle seguenti guide:

Dato che d'ora in poi eseguirai il deployment in Cloud Run, appengine-maven-plugin può essere rimosso:

<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. Containerizza l'applicazione

A questo punto sei pronto per informare Cloud Build su come creare effettivamente il container della tua applicazione. Con questo metodo di contenimento non è necessario un file di configurazione di build separato (cloudbuild.yaml). Possiamo semplicemente definire un Dockerfile minimo come punto di partenza:

DA eclipse-temurin

ARG JAR_FILE=JAR_FILE_MUST_BE_SPECIFIED_AS_BUILD_ARG

COPY ${JAR_FILE} app.jar

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

Questo file dockerfile raggruppa la versione uber-jar del servizio Spring Boot in un unico livello. È l'approccio più semplice alla containerizzazione Dockerfile, ma presenta una serie di svantaggi, soprattutto quando si confrontano tempi ripetuti in cui le dipendenze sono relativamente stabili. Problemi come questo sono il motivo per cui questo metodo di contenimento è considerato più avanzato. Tuttavia, la scrittura del tuo Dockerfile offre il controllo completo sull'immagine di base e l'accesso ai vantaggi in termini di prestazioni della scrittura di un'immagine accuratamente stratificata.

2**. Esegui il processo di compilazione**

Ora che hai comunicato a Cloud Build i passaggi di compilazione che ti interessano, puoi eseguire il deployment con un solo clic.

Esegui questo comando:

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

Sostituisci i valori segnaposto nel comando precedente con quanto segue:

  • LOCATION: la località regionale o multiregionale del repository.
  • PROJECT_ID: l'ID progetto Cloud.
  • REPOSITORY: il nome del repository Artifact Registry.
  • IMAGE_NAME: il nome dell'immagine container.

Al termine del processo, l'immagine container è stata creata, archiviata in Artifact Registry ed eseguita in Cloud Run.

Al termine di questo codelab, la tua app dovrebbe essere uguale a quella nella cartella mod4-migrate-to-cloud-run.

Ecco fatto! Hai eseguito la migrazione di un'app App Engine Java 8 a Java 17 e Cloud Run e ora hai una comprensione più chiara del lavoro necessario per il passaggio e la scelta tra le opzioni di hosting.

6. Riepilogo/Pulizia

Congratulazioni, hai eseguito l'upgrade, il contenimento e la migrazione della tua app. Questo tutorial è terminato.

A questo punto, il passaggio successivo è scoprire di più sulle funzionalità di sicurezza della catena di approvvigionamento del software e CI/CD ora a tua disposizione con Cloud Build:

(Facoltativo) Ripulisci e/o disattiva il servizio

Se hai eseguito il deployment dell'app di esempio su App Engine durante questo tutorial, ricordati di disattivare l'app per evitare addebiti. Quando vuoi passare al prossimo codelab, puoi riattivarlo. Quando le app App Engine sono disattivate, non generano traffico che comporta addebiti, ma l'utilizzo di Datastore potrebbe essere fatturabile se supera la quota senza costi, quindi eliminane abbastanza per rientrare in questo limite.

Se invece non vuoi continuare con le migrazioni e vuoi eliminare tutto, puoi eliminare il servizio o chiudere completamente il progetto.

7. Risorse aggiuntive

Problemi/feedback dei codelab per i moduli di migrazione di App Engine

Se riscontri problemi con questo codelab, cerca prima il problema prima di segnalarlo. Link per cercare e creare nuovi problemi:

Risorse di migrazione

Risorse online

Di seguito sono riportate alcune risorse online che potrebbero essere pertinenti per questo tutorial:

App Engine

Informazioni su altri cloud

Video

Licenza

Questo lavoro è concesso in licenza ai sensi di una licenza Creative Commons Attribution 2.0 Generic.