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

1. Обзор

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

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

Помимо обучения необходимым шагам для перехода с App Engine на Cloud Run, вы также узнаете, как обновить приложение App Engine на Java 8 до 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 , затем перейдите в папку baseline .

В качестве примера представлено 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 — использовать Artifact Registry .

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

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

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

ОТ eclipse-temurin

ARG JAR_FILE=JAR_FILE_MUST_BE_SPECIFIED_AS_BUILD_ARG

Скопировать ${JAR_FILE} app.jar

ТОЧКА ВХОДА ["java", "-jar","/app.jar"]

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

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

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

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

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

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

  • МЕСТОПОЛОЖЕНИЕ: региональное или многорегиональное местоположение вашего репозитория.
  • PROJECT_ID: идентификатор вашего облачного проекта.
  • REPOSITORY: имя вашего репозитория в реестре артефактов.
  • 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 отключены, они не будут получать трафик, за который взимается плата, однако использование Datastore может быть платным, если оно превысит бесплатную квоту , поэтому удалите достаточное количество данных, чтобы оно не превышало этот лимит.

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

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

Проблемы/обратная связь по модулю миграции App Engine на Codelabs

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

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

Онлайн-ресурсы

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

App Engine

Прочая информация об облачных сервисах

Видео

Лицензия

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