Миграция Java-приложения Google App Engine в Cloud Run с Jib

1. Обзор

Эта серия учебных пособий (практических руководств для самостоятельного обучения) призвана помочь разработчикам Google App Engine (стандартного) Java модернизировать свои приложения, проведя их через серию миграций. Выполнив эти действия, вы можете обновить свое приложение, чтобы оно стало более переносимым, и принять решение о контейнеризации его для Cloud Run , дочерней службы размещения контейнеров Google Cloud для App Engine и других служб размещения контейнеров.

Из этого руководства вы узнаете, как поместить в контейнер приложение App Engine для развертывания в полностью управляемом сервисе Cloud Run с помощью Jib . С помощью Jib вы можете создавать образы Docker — известной в отрасли платформы для разработки, доставки и запуска приложений в контейнерах.

Помимо обучения необходимым шагам для перехода с App Engine на Cloud Run, вы также узнаете, как обновить приложение Java 8 App Engine до Java 17.

Если ваше приложение интенсивно использует устаревшие комплексные сервисы App Engine или другие функции App Engine, мы рекомендуем выполнить миграцию этих встроенных сервисов или заменить эти функции перед переходом на Cloud Run. Если вам нужно больше времени для изучения вариантов миграции или вы хотите пока продолжать использовать устаревшие встроенные службы, вы можете продолжить доступ к встроенным службам App Engine для Java 11/17 при обновлении до более новой среды выполнения. Когда ваше приложение станет более переносимым, вернитесь к этой лаборатории кода, чтобы узнать, как применить инструкции к вашему приложению.

Вы узнаете, как

  • Используйте Cloud Shell
  • Включите API Cloud Run, Artifact Registry и Cloud Build.
  • Контейнеризируйте свое приложение с помощью Jib и Cloud Build.
  • Разверните образы контейнеров в Cloud Run

Что вам понадобится

Опрос

Как вы будете использовать этот урок?

Прочтите только до конца Прочитайте его и выполните упражнения.

Как бы вы оценили свой опыт работы с Java?

Новичок Средний Опытный

Как бы вы оценили свой опыт использования сервисов Google Cloud?

Новичок Средний Опытный

2. Предыстория

Системы «Платформа как услуга» (PaaS), такие как App Engine и Cloud Functions, предоставляют множество удобств для вашей команды и приложения, например позволяют системным администраторам и специалистам по DevOps сосредоточиться на создании решений. Благодаря безраздельным платформам ваше приложение может автоматически масштабироваться по мере необходимости, уменьшаться до нуля с оплатой по факту использования, чтобы контролировать затраты, а также использовать различные распространенные языки разработки.

Однако гибкость контейнеров также привлекательна. Благодаря возможности выбирать любой язык, любую библиотеку и любой двоичный файл, контейнеры дают вам лучшее из обоих миров: удобство бессерверной работы и гибкость контейнеров. В этом и заключается суть Cloud Run .

Изучение того, как использовать Cloud Run, не входит в задачи этой лаборатории; это описано в документации Cloud Run . Целью здесь является ознакомление вас с тем, как контейнеризировать приложение App Engine для Cloud Run (или других служб, размещенных в контейнере). Прежде чем двигаться дальше, вам следует знать несколько вещей, в первую очередь то, что ваш пользовательский опыт будет немного отличаться.

В этой лаборатории кода вы узнаете, как создавать и развертывать контейнеры. Вы узнаете, как:

  • Контейнеризируйте свое приложение с помощью Jib
  • Миграция из конфигурации App Engine
  • и, при необходимости, определите этапы сборки для Cloud Build.

Это потребует отказа от некоторых специфических функций App Engine. Если вы предпочитаете не идти по этому пути, вы все равно можете перейти на среду выполнения Java 11/17, сохранив вместо этого свои приложения в App Engine .

3. Настройка/Предварительная работа

1. Проект установки

В этом руководстве вы будете использовать пример приложения из репозитория appengine-java-migration-samples в совершенно новом проекте . Убедитесь, что у проекта есть активный платежный аккаунт.

Если вы собираетесь переместить существующее приложение App Engine в Cloud Run, вместо этого вы можете использовать это приложение.

Выполните следующую команду, чтобы включить необходимые API для вашего проекта:

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

2. Получите базовый образец приложения.

Клонируйте пример приложения на своем компьютере или в Cloud Shell , а затем перейдите в базовую папку.

Примером является приложение Datastore на основе сервлетов Java 8, предназначенное для развертывания в App Engine. Следуйте инструкциям в README о том, как подготовить это приложение к развертыванию App Engine.

3. (Необязательно) Разверните базовое приложение.

Следующие действия необходимы только в том случае, если вы хотите убедиться, что приложение работает в App Engine, прежде чем мы перейдем на Cloud Run.

См. шаги в README.md:

  1. Установите/повторно ознакомьтесь с интерфейсом командной строки gcloud
  2. Инициализируйте интерфейс командной строки gcloud для вашего проекта с помощью gcloud init
  3. Создайте проект App Engine с помощью gcloud app create
  4. Развертывание примера приложения в App Engine
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. Убедитесь, что приложение работает на App Engine без проблем.

4. Создайте репозиторий реестра артефактов.

После контейнеризации приложения вам понадобится место для отправки и хранения изображений. Рекомендуемый способ сделать это в Google Cloud — с помощью реестра артефактов .

Создайте репозиторий с именем « migration с помощью gcloud следующим образом:

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

Обратите внимание, что этот репозиторий использует тип формата docker , но доступно несколько типов репозитория .

На этом этапе у вас есть базовое приложение App Engine, и ваш проект Google Cloud готов к переносу его в Cloud Run.

4. Измените файлы приложения.

В тех случаях, когда ваше приложение активно использует устаревшие встроенные службы, настройки или другие функции App Engine, мы рекомендуем продолжать получать доступ к этим службам при обновлении до новой среды выполнения. В этой лаборатории кода демонстрируется путь миграции для приложений, которые уже используют автономные службы или могут быть подвергнуты рефакторингу для этого.

1. Обновление до Java 17

Если ваше приложение работает на Java 8, рассмотрите возможность обновления до более поздней версии LTS, например 11 или 17, чтобы не отставать от обновлений безопасности и получить доступ к новым языковым функциям.

Начните с обновления свойств в вашем pom.xml , включив в него следующее:

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

Это установит версию проекта 17, сообщит плагину компилятора, что вы хотите получить доступ к функциям языка Java 17 и хотите, чтобы скомпилированные классы были совместимы с Java 17 JVM.

2. Включение веб-сервера

Между App Engine и Cloud Run существует ряд различий, которые стоит учитывать при переходе между ними. Единственное отличие состоит в том, что среда выполнения Java 8 App Engine предоставляет и управляет сервером Jetty для размещенных на нем приложений, а Cloud Run этого не делает. Мы будем использовать Spring Boot, чтобы предоставить нам веб-сервер и контейнер сервлетов.

Добавьте следующие зависимости:

<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 по умолчанию встраивает сервер Tomcat, но в этом примере этот артефакт будет исключен и будет использоваться Jetty, чтобы минимизировать различия в поведении по умолчанию после миграции. Мы также можем настроить версию Jetty так, чтобы она соответствовала той, которую App Engine предоставляет « из коробки».

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

3. Настройка Spring Boot

Хотя Spring Boot сможет повторно использовать ваши сервлеты без изменений, для обнаружения потребуется определенная настройка.

Создайте следующий класс MigratedServletApplication.java в пакете 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);
    }
}

Обратите внимание, что сюда входит аннотация @ServletComponentScan , которая будет искать (по умолчанию в текущем пакете ) любые @WebServlets и делать их доступными, как и ожидалось.

4. Упаковка приложения в виде JAR-файла.

Хотя вы можете контейнеризировать свое приложение с помощью Jib , начиная с войны , это станет проще, если вы упакуете свое приложение в виде исполняемого JAR-файла. Это не потребует особой настройки, особенно для проектов, использующих Maven в качестве инструмента сборки, поскольку упаковка jar является поведением по умолчанию.

Удалите тег packaging в файле pom.xml :

<packaging>war</packaging>

Затем добавьте плагин 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. Переход от конфигурации, служб и зависимостей App Engine

Как упоминалось в начале лабораторной работы, Cloud Run и App Engine созданы для того, чтобы предлагать различный пользовательский опыт. Некоторые функции, которые App Engine предлагает «из коробки», например службы Cron и Task Queue , необходимо пересоздавать вручную, и они будут рассмотрены более подробно в последующих модулях.

Пример приложения не использует устаревшие встроенные службы, но пользователи, чьи приложения используют, могут обратиться к следующим руководствам:

Поскольку с этого момента вы будете выполнять развертывание в Cloud Run, 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. Контейнеризация приложения

На этом этапе вы можете вручную развернуть свое приложение в Cloud Run прямо из исходного кода . Это отличный вариант, который незаметно использует Cloud Build для обеспечения возможности развертывания без участия пользователя. Мы рассмотрим развертывание исходного кода более подробно в последующих модулях.

Альтернативно, если вам нужен больший контроль над способом развертывания вашего приложения, вы можете добиться этого, определив файл cloudbuild.yaml , в котором явно излагаются предполагаемые этапы сборки:

1. Определите файл cloudbuild.yaml.

Создайте следующий файл cloudbuild.yaml на том же уровне, что и pom.xml :

steps:
  # Test your build
  - name: maven:eclipse-temurin
    entrypoint: mvn
    args: ["test"]
  # Build with Jib
  - name: maven:eclipse-temurin
    entrypoint: mvn
    args: [ "compile", "com.google.cloud.tools:jib-maven-plugin:3.2.1:build", "-Dimage=northamerica-northeast1-docker.pkg.dev/PROJECT_ID/migration/visitors:jib"]
  # Deploy to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args: [ 'run', 'deploy', 'visitors', '--image', 'northamerica-northeast1-docker.pkg.dev/PROJECT_ID/migration/visitors:jib', '--region', 'northamerica-northeast1', '--allow-unauthenticated']

Как только мы сообщим Cloud Build выполнить следующие действия, он:

  1. Запустите тесты с помощью ./mvnw test
  2. Создайте, отправьте и пометьте свое изображение в реестре Artifact с помощью Jib.
  3. Разверните свой образ в Cloud Run с помощью gcloud run deploy

Обратите внимание, что 'visitors' предоставляются Cloud Run в качестве желаемого имени службы. Флаг –allow-unauthenticated позволяет пользователям посещать веб-приложение без необходимости аутентификации. Обязательно замените PROJECT_ID идентификатором вашего проекта в файле cloudbuild.yaml .

Затем добавьте следующие привязки политики IAM, чтобы разрешить учетной записи службы Cloud Build в реестре артефактов:

export PROJECT_ID=$(gcloud config list --format 'value(core.project)')
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)" )

gcloud projects add-iam-policy-binding $PROJECT_ID \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role=roles/run.admin \
--project=$PROJECT_ID
gcloud iam service-accounts add-iam-policy-binding $PROJECT_NUMBER-compute@developer.gserviceaccount.com \
--member=serviceAccount:$PROJECT_NUMBER@cloudbuild.gserviceaccount.com \
--role roles/iam.serviceAccountUser --project=$PROJECT_ID

2. Запустите процесс сборки

Теперь, когда вы сообщили Cloud Build о желаемых этапах сборки, вы готовы к развертыванию одним щелчком мыши.

Выполните следующую команду:

gcloud builds submit

После завершения процесса образ контейнера будет создан, сохранен в реестре артефактов и развернут в Cloud Run.

В конце этой лабораторной работы ваше приложение должно выглядеть так же, как в java17-and-cloud-run/finish .

И вот оно! Вы успешно перенесли приложение Java 8 App Engine на Java 17 и Cloud Run и теперь имеете более четкое представление о работе, связанной с переключением и выбором между вариантами хостинга .

6. Подведение итогов/очистка

Поздравляем, вы обновили, контейнеризировали, перенесли свое приложение, и это завершает это руководство!

Следующий шаг — узнать больше о функциях безопасности CI/CD и цепочки поставок программного обеспечения, которые теперь доступны и могут быть развернуты с помощью Cloud Build:

Необязательно: очистите и/или отключите службу.

Если вы развернули пример приложения на App Engine во время работы с этим руководством, не забудьте отключить приложение , чтобы избежать дополнительных расходов. Когда вы будете готовы перейти к следующей лаборатории кода, вы можете снова включить ее. Пока приложения App Engine отключены, они не будут получать трафик, за который взимается плата, однако за использование Datastore может взиматься плата, если оно превышает бесплатную квоту , поэтому удалите достаточно трафика, чтобы попасть под этот лимит.

С другой стороны, если вы не собираетесь продолжать миграцию и хотите полностью удалить все, вы можете либо удалить свой сервис , либо полностью закрыть проект .

7. Дополнительные ресурсы

Проблемы и отзывы о модулях миграции App Engine

Если вы обнаружите какие-либо проблемы с этой кодовой лабораторией, сначала найдите свою проблему, прежде чем подавать заявку. Ссылки для поиска и создания новых задач:

Миграционные ресурсы

Интернет-ресурсы

Ниже приведены онлайн-ресурсы, которые могут иметь отношение к этому руководству:

Механизм приложений

Другая информация об облаке

Видео

Лицензия

Эта работа распространяется под лицензией Creative Commons Attribution 2.0 Generic License.