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

1. Обзор

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

Из этого руководства вы узнаете, как поместить в контейнер приложение App Engine для развертывания в полностью управляемом сервисе Cloud Run с помощью Dockerfile. Dockerfiles — это наиболее удобный метод развертывания для этой миграции, но они также предлагают больше возможностей для настройки процесса сборки.

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

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

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

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

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

Опрос

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

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

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

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

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

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

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

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

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

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

В этой лаборатории кода вы узнаете, как создавать и развертывать контейнеры. Вы узнаете, как поместить свое приложение в контейнер с помощью файла Dockerfile, перейти от конфигурации 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, чтобы минимизировать различия в поведении по умолчанию после миграции.

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-файла.

Хотя можно поместить ваше приложение в контейнер, начиная с войны , это станет проще, если вы упакуете свое приложение в виде исполняемого 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 Build о том, как на самом деле создать контейнер вашего приложения. При использовании этого метода контейнеризации отдельный файл конфигурации сборки (cloudbuild.yaml) не требуется. Мы можем просто определить минимальный Dockerfile в качестве отправной точки:

ОТ затмения-темурина

ARG JAR_FILE=JAR_FILE_MUST_BE_SPECIFIED_AS_BUILD_ARG

КОПИРОВАТЬ ${JAR_FILE} app.jar

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

Этот dockerfile объединяет версию uber-jar вашей службы загрузки Spring в один слой. Это самый простой подход к контейнеризации Dockerfile, но он имеет ряд недостатков, особенно при сравнении повторяющихся периодов, когда зависимости относительно стабильны. Подобные опасения являются причиной того, что этот метод контейнеризации считается более продвинутым. Однако есть и положительная сторона: написание собственного файла Docker дает полный контроль над базовым образом и доступ к преимуществам производительности, получаемым при написании тщательно многоуровневого образа .

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

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

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

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

Замените значения заполнителей в приведенной выше команде следующим:

  • РАСПОЛОЖЕНИЕ: региональное или мультирегиональное расположение вашего репозитория.
  • PROJECT_ID: идентификатор вашего облачного проекта.
  • РЕПОЗИТАРИЙ: имя вашего хранилища реестра артефактов.
  • IMAGE_NAME: имя вашего образа контейнера.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Видео

Лицензия

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