Jib를 사용하여 Google App Engine 자바 앱에서 Cloud Run으로 마이그레이션

1. 개요

이 Codelab 시리즈 (자기 주도형 실습 튜토리얼)는 Google App Engine (표준) 자바 개발자가 일련의 이전을 안내하여 앱을 현대화할 수 있도록 돕는 것을 목표로 합니다. 이 단계를 따르면 앱을 더 쉽게 이식할 수 있도록 업데이트하고 Cloud Run, App Engine에 대한 Google Cloud의 컨테이너 호스팅 자매 서비스 및 기타 컨테이너 호스팅 서비스에 맞게 앱을 컨테이너화할 수 있습니다.

이 가이드에서는 Jib을 사용하여 Cloud Run 완전 관리형 서비스에 배포하기 위해 App Engine 앱을 컨테이너화하는 방법을 설명합니다. Jib를 사용하면 컨테이너에서 애플리케이션을 개발, 제공, 실행하기 위해 업계에서 잘 알려진 플랫폼인 Docker 이미지를 만들 수 있습니다.

App Engine에서 Cloud Run으로 이전하는 데 필요한 단계를 설명하는 것 외에도 자바 8 App Engine 앱을 자바 17로 업그레이드하는 방법도 배웁니다.

애플리케이션에서 App Engine 기존 번들 서비스나 기타 App Engine 기능을 많이 사용하는 경우 Cloud Run으로 이동하기 전에 이러한 번들 서비스에서 마이그레이션하거나 해당 기능을 교체하는 것이 좋습니다. 이전 옵션을 조사하는 데 시간이 더 필요하거나 당분간 기존 번들 서비스를 계속 사용하려면 최신 런타임으로 업그레이드할 때 자바 11/17용 App Engine 번들 서비스에 계속 액세스할 수 있습니다. 앱의 이식성이 더 높아지면 이 Codelab으로 돌아와 안내를 앱에 적용하는 방법을 알아보세요.

다음 실습에서는

  • Cloud Shell 사용
  • Cloud Run, Artifact Registry, Cloud Build API 사용 설정
  • Jib 및 Cloud Build를 사용하여 앱 컨테이너화
  • Cloud Run에 컨테이너 이미지 배포

필요한 항목

설문조사

이 튜토리얼을 어떻게 사용하실 계획인가요?

읽기만 할 계획입니다 읽은 다음 연습 활동을 완료할 계획입니다

귀하의 Java 사용 경험을 평가해 주세요.

초급 중급 고급

귀하의 Google Cloud 서비스 사용 경험을 평가해 주세요.

<ph type="x-smartling-placeholder"></ph> 초보자 중급 숙련도

2. 배경

App Engine 및 Cloud Functions와 같은 PaaS (Platform as a Service) 시스템은 SysAdmin 및 DevOps가 솔루션 빌드에 집중할 수 있도록 하는 등 팀과 애플리케이션에 많은 편의성을 제공합니다. 서버리스 플랫폼을 사용하면 앱이 필요에 따라 자동 확장하고, 사용한 만큼만 지불하는 방식으로 0으로 축소하여 비용을 관리하고, 다양한 공통 개발 언어를 사용할 수 있습니다.

하지만 컨테이너의 유연성 또한 강력합니다. 원하는 언어, 모든 라이브러리, 바이너리를 선택할 수 있는 컨테이너는 서버리스의 편의성과 컨테이너의 유연성이라는 두 가지 이점을 모두 제공합니다. 이것이 Cloud Run의 핵심입니다.

Cloud Run 사용 방법을 배우는 것은 이 Codelab에서 다루지 않습니다. 자세한 내용은 Cloud Run 문서를 참조하세요. 이 가이드의 목표는 Cloud Run (또는 기타 컨테이너 호스팅 서비스)용 App Engine 앱을 컨테이너화하는 방법을 익히는 것입니다. 진행하기 전에 알아두어야 할 몇 가지 사항이 있으며, 주로 사용자 환경이 약간 달라진다는 점을 유념해 주시기 바랍니다.

이 Codelab에서는 컨테이너를 빌드하고 배포하는 방법을 알아봅니다. 다음 작업을 수행하는 방법을 배우게 됩니다.

  • Jib로 앱 컨테이너화
  • App Engine 구성에서 마이그레이션
  • 필요한 경우 Cloud Build의 빌드 단계를 정의합니다.

여기에는 특정 App Engine 관련 기능에서 지원이 중단되는 것이 포함됩니다. 이 경로를 따르지 않으려는 경우에도 App Engine에서 앱을 유지하면서 자바 11/17 런타임으로 업그레이드할 수 있습니다.

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 폴더로 이동합니다.

샘플은 App Engine에 배포하기 위한 Java 8, Servlet 기반의 Datastore 앱입니다. App Engine 배포를 위해 이 앱을 준비하는 방법에 대한 README의 안내를 따릅니다.

3. (선택사항) 기준 앱 배포

다음은 Cloud Run으로 이전하기 전에 앱이 App Engine에서 작동하는지 확인하려는 경우에만 필요합니다.

README.md의 단계를 참조하세요.

  1. gcloud CLI 설치 및 익히기
  2. gcloud init로 프로젝트의 gcloud CLI 초기화
  3. gcloud app create로 App Engine 프로젝트 만들기
  4. App Engine에 샘플 앱 배포
./mvnw package appengine:deploy -Dapp.projectId=$PROJECT_ID
  1. 앱이 App Engine에서 문제 없이 실행되는지 확인

4. Artifact Registry 저장소 만들기

앱을 컨테이너화한 후에는 이미지를 푸시하고 저장할 곳이 필요합니다. Google Cloud에서 이 작업을 수행하기 위해 권장되는 방법은 Artifact Registry를 사용하는 것입니다.

다음과 같이 gcloud를 사용하여 migration라는 저장소를 만듭니다.

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 전용 기능을 많이 사용하는 경우 새 런타임으로 업그레이드하는 동안 해당 서비스에 계속 액세스하는 것이 좋습니다. 이 Codelab은 이미 독립형 서비스를 사용하고 있거나 독립형 서비스를 사용하도록 리팩터링할 수 있는 애플리케이션의 이전 경로를 보여줍니다.

1. 자바 17로 업그레이드

앱이 Java 8을 실행하는 경우 보안 업데이트를 확인하고 새로운 언어 기능에 액세스할 수 있도록 11 또는 17과 같은 최신 LTS 후보로 업그레이드하는 것이 좋습니다.

먼저 다음을 포함하도록 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 간에 이동할 때 고려해야 할 몇 가지 차이점이 있습니다. 한 가지 차이점은 App Engine의 Java 8 런타임은 호스팅하는 앱에 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를 유지하여 마이그레이션 후 기본 동작의 차이를 최소화합니다. App Engine이 제공하는 것과 일치하도록 기본적으로 Jetty 버전을 구성할 수도 있습니다.

<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는 수정 없이 서블릿을 재사용할 수 있지만 검색 가능성을 높이려면 일부 구성이 필요합니다.

com.example.appengine 패키지에 다음 MigratedServletApplication.java 클래스를 만듭니다.

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);
    }
}

여기에는 기본적으로 현재 패키지에서 @WebServlets가 있는지 확인하고 예상대로 사용할 수 있는 @ServletComponentScan 주석이 포함됩니다.

4. 앱을 JAR로 패키징

전쟁에서 시작하여 Jib를 사용하여 앱을 컨테이너화할 수 있지만, 앱을 실행 가능한 JAR로 패키징하면 더 쉽습니다. 특히 Maven을 빌드 도구로 사용하는 프로젝트의 경우 jar 패키징이 기본 동작이므로 많은 구성이 필요하지 않습니다.

pom.xml 파일에서 packaging 태그를 삭제합니다.

<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 구성, 서비스, 종속 항목에서 마이그레이션

Codelab의 시작 부분에서 언급했듯이 Cloud Run과 App Engine은 다양한 사용자 환경을 제공하도록 설계되었습니다. 크론태스크 큐 서비스와 같이 App Engine에서 즉시 사용할 수 있는 특정 기능은 수동으로 다시 만들어야 하며, 이 내용은 이후 모듈에서 자세히 다룹니다.

샘플 앱은 기존 번들 서비스를 사용하지 않지만 앱을 사용하는 사용자는 다음 가이드를 참고할 수 있습니다.

지금부터 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 파일 정의

pom.xml와 동일한 수준에서 다음 cloudbuild.yaml 파일을 만듭니다.

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. Jib을 사용하여 이미지를 빌드 및 푸시하고 Artifact Registry에 태그 지정
  3. gcloud run deploy를 사용하여 Cloud Run에 이미지 배포

‘visitors'는 Cloud Run에 원하는 서비스 이름으로 제공됩니다. –allow-unauthenticated 플래그를 사용하면 사용자가 인증 없이 웹 앱을 방문할 수 있습니다. cloudbuild.yaml 파일에서 PROJECT_ID를 프로젝트 ID로 바꿔야 합니다.

다음으로 다음 IAM 정책 바인딩을 추가하여 Cloud Build 서비스 계정이 Artifact Registry에 액세스하도록 허용합니다.

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

프로세스가 완료되면 컨테이너 이미지가 빌드되어 Artifact Registry에 저장되었으며 Cloud Run에 배포되었습니다.

이 Codelab을 마치면 앱은 java17-and-cloud-run/finish의 앱과 동일하게 표시됩니다.

이제 Cloud 함수가 완성되었네요. 자바 8 App Engine 앱을 자바 17 및 Cloud Run으로 성공적으로 마이그레이션했으며 이제 호스팅 옵션 간 선택 및 전환과 관련된 작업을 더 명확하게 이해할 수 있습니다.

6. 요약/삭제

수고하셨습니다. 앱을 업그레이드하고 컨테이너화하고 마이그레이션하여 이 튜토리얼을 마치겠습니다.

이제 다음 단계는 Cloud Build로 배포할 수 있으므로 현재 사용 가능한 CI/CD 및 소프트웨어 공급망 보안 기능에 대해 자세히 알아보는 것입니다.

선택사항: 서비스 정리 및/또는 사용 중지

이 튜토리얼을 진행하면서 App Engine에 샘플 앱을 배포한 경우 요금이 청구되지 않도록 을 사용 중지해야 합니다. 다음 Codelab으로 이동할 준비가 되면 다시 사용 설정할 수 있습니다. App Engine 앱을 사용 중지하면 요금이 발생하는 트래픽이 발생하지 않지만 Datastore 사용량무료 할당량을 초과하면 요금이 청구될 수 있으므로 이 한도 미만으로 줄일 수 있도록 삭제하세요.

반면 이전을 계속 진행하지 않고 모든 항목을 완전히 삭제하려면 서비스를 삭제하거나 프로젝트를 완전히 종료하면 됩니다.

7. 추가 리소스

App Engine 마이그레이션 모듈 Codelab 문제/의견

이 Codelab에 문제가 발견된 경우 문제를 기록하기 전에 먼저 비슷한 기록이 있는지 검색해보세요. 검색 및 새 문제 만들기 링크:

마이그레이션 리소스

온라인 리소스

다음은 이 튜토리얼과 관련이 있을 수 있는 온라인 리소스입니다.

App Engine

기타 클라우드 정보

동영상

라이선스

이 작업물은 Creative Commons Attribution 2.0 일반 라이선스에 따라 사용이 허가되었습니다.