App Engine Memcache에서 Cloud Memorystore로 마이그레이션 (모듈 13)

1. 개요

서버리스 마이그레이션 스테이션 Codelab 시리즈 (사용자 주도형 실습 튜토리얼) 및 관련 동영상Google Cloud 서버리스 개발자가 주로 기존 서비스에서 벗어나 하나 이상의 마이그레이션을 통해 애플리케이션을 현대화하도록 돕는 것을 목표로 합니다. 이렇게 하면 앱의 이식성이 향상되고 더 많은 옵션과 유연성이 제공되므로 다양한 Cloud 제품과 통합하고 액세스하고 최신 언어 버전으로 보다 쉽게 업그레이드할 수 있습니다. 이 시리즈는 처음에는 초기 Cloud 사용자, 특히 App Engine (표준 환경) 개발자에 중점을 두고 있지만 Cloud FunctionsCloud Run과 같은 다른 서버리스 플랫폼이나 해당하는 경우 다른 플랫폼을 포함할 만큼 광범위합니다.

이 Codelab의 목적은 Python 2 App Engine 개발자에게 App Engine Memcache에서 Cloud Memorystore (Redis용)로 마이그레이션하는 방법을 보여주는 것입니다. App Engine ndb에서 Cloud NBS로의 암시적 이전도 있지만 주로 모듈 2 Codelab에서 다룹니다. 단계별 정보를 확인하세요.

다음 실습에서는

  • Cloud 콘솔 또는 gcloud 도구에서 Cloud Memorystore 인스턴스 설정
  • Cloud Console 또는 gcloud 도구에서 Cloud 서버리스 VPC 액세스 커넥터 설정
  • App Engine Memcache에서 Cloud Memorystore로 마이그레이션
  • 샘플 앱에서 Cloud Memorystore로 캐싱 구현하기
  • App Engine ndb에서 Cloud NBS로 마이그레이션

필요한 항목

설문조사

본 가이드를 어떻게 사용하실 계획인가요?

<ph type="x-smartling-placeholder"></ph> 읽어보기만 해도 됩니다. 읽고 연습 활동을 완료하세요

귀하의 Python 사용 경험이 어떤지 평가해 주세요.

초급 중급 고급

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

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

2. 배경

이 Codelab에서는 App Engine Memcache (및 NBS)에서 Cloud Memorystore (및 Cloud NBS)로 샘플 앱을 마이그레이션하는 방법을 보여줍니다. 이 프로세스에는 App Engine 번들 서비스의 종속 항목을 대체하는 작업이 포함되므로 앱의 이동성이 향상됩니다. App Engine을 계속 사용하거나 앞에서 설명한 대안으로 전환할 수 있습니다.

이 마이그레이션에는 이 시리즈의 다른 마이그레이션보다 더 많은 노력이 필요합니다. App Engine Memcache를 대체하는 것이 권장되는 것은 완전 관리형 클라우드 기반 캐싱 서비스인 Cloud Memorystore입니다. Memorystore는 널리 사용되는 오픈소스 캐싱 엔진인 RedisMemcached 쌍을 지원합니다. 이 마이그레이션 모듈은 Redis용 Cloud Memorystore를 사용합니다. 자세한 내용은 Memorystore 및 Redis 개요를 참조하세요.

Memorystore에는 실행 중인 서버가 필요하므로 Cloud VPC도 필요합니다. 특히 App Engine 앱이 비공개 IP 주소를 통해 Memorystore 인스턴스에 연결할 수 있도록 서버리스 VPC 액세스 커넥터를 만들어야 합니다. 이 실습을 완료하면 앱을 업데이트하여 전과 같이 작동하지만 Cloud Memorystore가 App Engine의 Memcache 서비스를 대체하는 캐싱 서비스가 될 것입니다.

이 튜토리얼은 Python 2의 모듈 12 샘플 앱으로 시작되며 이어서 Python 3로의 선택적 마이너 업그레이드가 추가로 진행됩니다. Python 3 App Engine SDK를 통해 Python 3에서 App Engine 번들 서비스에 액세스하는 데 이미 익숙한 경우 대신 모듈 12 샘플 앱의 Python 3 버전으로 시작해도 됩니다. Memorystore가 App Engine 번들 서비스가 아니기 때문에 이 경우 SDK 사용이 삭제됩니다. Python 3 App Engine SDK 사용 방법을 배우는 내용은 이 가이드에서 다루지 않습니다.

이 튜토리얼에서는 다음과 같은 주요 단계를 설명합니다.

  1. 설정/사전 작업
  2. 캐싱 서비스 설정
  3. 구성 파일 업데이트
  4. 기본 애플리케이션 업데이트

3. 설정/사전 작업

Cloud 프로젝트 준비

모듈 12 Codelab을 완료할 때 사용한 것과 동일한 프로젝트를 재사용하는 것이 좋습니다. 또는 새 프로젝트를 만들거나 다른 기존 프로젝트를 재사용할 수 있습니다. 이 시리즈의 모든 Codelab에는 'START' (시작할 기준 코드) 및 'FINISH' (이전된 앱) 문제가 발생할 경우 자신의 솔루션과 Google의 솔루션을 비교할 수 있도록 FINISH 코드가 제공됩니다. 문제가 발생하면 언제든지 START로 롤백할 수 있습니다. 이러한 체크포인트는 이전을 수행하는 방법을 성공적으로 학습할 수 있도록 고안되었습니다.

어떤 Cloud 프로젝트를 사용하든 활성 결제 계정이 있어야 합니다. 또한 App Engine이 사용 설정되어 있는지 확인합니다. 이 튜토리얼을 수행할 때 일반적인 비용 영향을 검토하고 이해해야 합니다. 하지만 이 시리즈의 다른 항목과 달리 이 Codelab에서는 무료 등급없는 Cloud 리소스를 사용하므로 실습을 완료하는 데 약간의 비용이 발생합니다. 청구 비용을 최소화하기 위한 리소스 해제에 대한 안내를 비롯하여 사용량 절감에 대한 권장사항과 함께 보다 구체적인 비용 정보가 제공됩니다.

기준 샘플 앱 가져오기

이 Codelab에서는 먼저 살펴볼 기본 모듈 12 코드부터 이전을 단계별로 안내합니다. 완료되면 FINISH 폴더 중 하나의 코드와 매우 유사하게 작동하는 모듈 13 앱이 표시됩니다. 리소스:

시작 폴더에는 다음 파일이 포함되어야 합니다.

$ ls
README.md               app.yaml                main.py                 requirements.txt        templates                

Python 2 버전부터 시작하는 경우 모듈 12 Codelab을 완료했다면 appengine_config.py 파일과 lib 폴더도 있을 수 있습니다.

모듈 12 앱 (재)배포

남은 사전 작업 단계:

  1. gcloud 명령줄 도구에 익숙해지기 (필요한 경우)
  2. 필요한 경우 모듈 12 코드를 App Engine에 (재)배포

Python 2 사용자는 다음 명령어를 사용하여 lib 폴더를 삭제하고 다시 설치해야 합니다.

rm -rf ./lib; pip install -t lib -r requirements.txt                

이제 모든 사용자 (Python 2 및 3 사용자)는 다음 명령어를 사용하여 App Engine에 코드를 업로드해야 합니다.

gcloud app deploy                

배포가 완료되면 앱의 모양과 기능이 모듈 12의 앱과 같은지 확인합니다. 모듈 12는 방문수를 추적하고 동일한 사용자에게 한 시간 동안 캐싱하는 웹 앱입니다.

dfe56a02ae59ddd8.png

최근 방문 기록이 캐시되기 때문에 페이지 새로고침이 상당히 빠르게 로드됩니다.

4. 캐싱 서비스 설정

Cloud Memorystore는 서버리스가 아닙니다. 인스턴스는 필수 항목입니다. 여기서는 Redis를 실행하는 포드입니다 Memcache와 달리 Memorystore는 독립형 Cloud 제품이며 무료 등급없으므로 계속 진행하기 전에 Memorystore for Redis 가격 정보를 확인해야 합니다. 이 실습 비용을 최소화하려면 운영에 필요한 최소한의 리소스(기본 서비스 등급 및 1GB 용량)를 사용하는 것이 좋습니다.

Memorystore 인스턴스는 App Engine 앱 (인스턴스)과 다른 네트워크에 있으므로 App Engine이 Memorystore 리소스에 액세스할 수 있도록 서버리스 VPC 액세스 커넥터를 만들어야 합니다. VPC 비용을 최소화하려면 인스턴스 유형 (f1-micro)과 요청할 인스턴스 수를 선택하세요 (최소 2개, 최대 3개 권장). VPC 가격 책정 정보 페이지도 확인하세요.

필요한 각 리소스를 만드는 과정을 안내하면서 비용 절감을 위한 이러한 권장사항을 반복합니다. 또한 Cloud 콘솔에서 Memorystore 및 VPC 리소스를 만들면 오른쪽 상단에 각 제품의 가격 계산기가 표시되어 월별 예상 비용을 확인할 수 있습니다 (아래 그림 참고). 옵션을 변경하면 이 값이 자동으로 조정됩니다. 다음과 같이 예상할 수 있습니다.

7eb35ebf7248c010.png

두 리소스 모두 필수이며 어느 리소스를 먼저 만드는지는 중요하지 않습니다. Memorystore 인스턴스를 먼저 만들면 VPC 커넥터가 없으면 App Engine 앱이 인스턴스에 연결할 수 없습니다. 마찬가지로 VPC 커넥터를 먼저 만들면 App Engine 앱이 VPC 네트워크에 연결할 수 없습니다. 이 튜토리얼에서는 먼저 Memorystore 인스턴스를 만든 후 VPC 커넥터를 만드는 방법을 설명합니다.

두 리소스가 모두 온라인 상태가 되면 앱이 캐시에 액세스할 수 있도록 관련 정보를 app.yaml에 추가합니다. 공식 문서에서 Python 2 또는 Python 3 가이드를 참조할 수도 있습니다. Cloud Dataplex 마이그레이션 페이지 ( Python 2 또는 Python 3)의 데이터 캐싱 가이드도 참조할 만한 가치가 있습니다.

Cloud Memorystore 인스턴스 만들기

Cloud Memorystore에는 무료 등급이 없으므로 Codelab 완료를 위해 리소스를 최소한으로 할당하는 것이 좋습니다. 다음과 같은 설정을 통해 비용을 최소로 유지할 수 있습니다.

  • 가장 낮은 서비스 등급인 기본 (콘솔 기본값: '표준', 기본값 gcloud: '기본')을 선택합니다.
  • 최소 스토리지 용량은 1GB (콘솔 기본값: 16GB, gcloud 기본값: 1GB)를 선택합니다.
  • 일반적으로 모든 소프트웨어의 최신 버전에는 가장 많은 리소스가 필요하지만 가장 오래된 버전을 선택하는 것은 권장되지 않습니다. 현재 두 번째 최신 버전은 Redis 버전 5.0 (콘솔 기본값: 6.x)입니다.

이러한 설정을 염두에 두고 다음 섹션에서는 Cloud 콘솔에서 인스턴스를 만드는 방법을 알아보겠습니다. 명령줄에서 이 작업을 수행하려면 건너뛰세요.

Cloud Console 사용

Cloud 콘솔의 Cloud Memorystore 페이지로 이동합니다 (결제 정보를 묻는 메시지가 표시될 수 있음). Memorystore를 아직 사용 설정하지 않은 경우 사용 설정하라는 메시지가 표시됩니다.

68318997e3105db6.png

이 기능을 사용 설정하면 (결제와 함께) Memorystore 대시보드로 이동합니다. 여기에서 프로젝트에 생성된 모든 인스턴스를 볼 수 있습니다. 아래에 표시된 프로젝트에는 프로젝트가 없으므로 '표시할 행 없음'이 표시됩니다. Memorystore 인스턴스를 만들려면 상단에서 인스턴스 만들기를 클릭합니다.

63547aa575838a36.png

이 페이지에는 Memorystore 인스턴스를 만들기 위해 원하는 설정을 완료할 수 있는 양식이 있습니다.

b77d927287fdf4c7.png

이 튜토리얼과 샘플 앱의 비용을 줄이려면 앞에서 다룬 권장사항을 따르세요. 선택을 완료한 후 만들기를 클릭합니다. 만드는 데 몇 분 정도 걸립니다. 완료되면 인스턴스의 IP 주소포트 번호를 복사하여 app.yaml에 추가합니다.

명령줄에서

Cloud 콘솔에서 Memorystore 인스턴스를 만드는 것이 시각적으로 유익하지만 어떤 개발자는 명령줄을 선호합니다. 계속하기 전에 gcloud설치하고 초기화해야 합니다.

Cloud 콘솔과 마찬가지로 Redis용 Cloud Memorystore를 사용 설정해야 합니다. 다음 예시와 같이 gcloud services enable redis.googleapis.com 명령어를 실행하고 완료될 때까지 기다립니다.

$ gcloud services enable redis.googleapis.com
Operation "operations/acat.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

서비스를 이미 사용하도록 설정한 경우, 명령을 다시 실행해도 부작용은 없습니다. 서비스를 사용 설정한 상태에서 Memorystore 인스턴스를 만들어 보겠습니다. 명령어는 다음과 같습니다.

gcloud redis instances create NAME --redis-version VERSION \
    --region REGION --project PROJECT_ID

Memorystore 인스턴스의 이름을 선택합니다. 이 실습에서는 'demo-ms'을(를) 사용합니다. 을 이름으로 설정합니다(프로젝트 ID 'my-project'). 이 샘플 앱의 리전은 us-central1 (us-central과 동일)이지만 지연 시간이 우려된다면 더 가까운 리전을 사용할 수 있습니다. App Engine 앱과 동일한 리전을 선택해야 합니다. 원하는 Redis 버전을 선택할 수 있지만 앞에서 권장한 대로 버전 5가 사용됩니다. 이러한 설정을 고려할 때 다음은 관련 출력과 함께 실행하는 명령어입니다.

$ gcloud redis instances create demo-ms --region us-central1 \
    --redis-version redis_5_0 --project my-project

Create request issued for: [demo-ms]
Waiting for operation [projects/my-project/locations/us-central1/operations/operation-xxxx] to complete...done.
Created instance [demo-ms].

Cloud Console 기본값과 달리 gcloud는 최소 리소스로 기본 설정됩니다. 결과적으로 이 명령어에는 서비스 등급이나 스토리지 용량이 필요하지 않습니다. Memorystore 인스턴스를 만드는 데 몇 분 정도 걸리며 완료되면 곧 app.yaml에 추가될 인스턴스의 IP 주소와 포트 번호를 기록해 두세요.

인스턴스 생성 확인

Cloud 콘솔 또는 명령줄에서

인스턴스를 Cloud 콘솔 또는 명령줄에서 만들었든 다음 명령어를 사용하면 인스턴스가 사용 가능한 상태인지, 사용할 준비가 되었는지 확인할 수 있습니다. gcloud redis instances list --region REGION

다음은 us-central1 리전의 인스턴스를 확인하는 명령어와 방금 만든 인스턴스를 보여주는 예상 출력입니다.

$ gcloud redis instances list --region us-central1
INSTANCE_NAME  VERSION    REGION       TIER   SIZE_GB  HOST         PORT  NETWORK  RESERVED_IP     STATUS  CREATE_TIME
demo-ms        REDIS_5_0  us-central1  BASIC  1        10.aa.bb.cc  6379  default  10.aa.bb.dd/29  READY   2022-01-28T09:24:45

인스턴스 정보를 요청하거나 앱을 구성하라는 메시지가 표시되면 HOSTPORT (RESERVED_IP 아님)를 사용해야 합니다. 이제 Cloud 콘솔의 Cloud Memorystore 대시보드에 해당 인스턴스가 표시됩니다.

c5a6948ec1c056ed.png

Compute Engine 가상 머신에서

Compute Engine 가상 머신 (VM)이 있는 경우 VM에서 Memorystore 인스턴스 직접 명령어를 전송하여 작동하는지 확인할 수도 있습니다. VM을 사용하면 이미 사용 중인 리소스와 무관하게 관련 비용이 발생할 수 있습니다.

서버리스 VPC 액세스 커넥터 만들기

Cloud Memorystore와 마찬가지로 Cloud 콘솔 또는 명령줄에서 서버리스 Cloud VPC 커넥터를 만들 수 있습니다. 마찬가지로 Cloud VPC에는 무료 등급이 없으므로 비용을 최소화하기 위해 Codelab 완료를 위해 최소한의 리소스를 할당하는 것이 좋습니다. 이러한 설정은 다음과 같습니다.

  • 가장 낮은 최대 인스턴스 수를 3개 (콘솔 및 gcloud 기본값: 10)로 선택하세요.
  • 가장 저렴한 머신 유형(f1-micro)을 선택하세요(콘솔 기본값: e2-micro, gcloud 기본값은 없음).

다음 섹션에서는 위의 Cloud VPC 설정을 사용하여 Cloud 콘솔에서 커넥터를 만드는 과정을 안내합니다. 명령줄에서 이 작업을 수행하려면 다음 섹션으로 건너뛰세요.

Cloud 콘솔에서

Cloud 네트워킹 '서버리스 VPC 액세스'로 이동합니다. 페이지에서 결제 정보를 확인할 수 있습니다 (결제 정보를 입력하라는 메시지가 표시될 수 있음). API를 아직 사용 설정하지 않은 경우 사용 설정하라는 메시지가 표시됩니다.

e3b9c0651de25e97.png

결제와 함께 API를 사용 설정하면 생성된 모든 VPC 커넥터가 표시된 대시보드가 표시됩니다. 아래 스크린샷에 사용된 프로젝트에는 프로젝트가 없으므로 '표시할 행 없음'이라는 메시지가 표시됩니다. 콘솔에서 상단의 커넥터 만들기를 클릭합니다.

b74b49b9d73b7dcf.png

원하는 설정으로 양식을 작성합니다.

6b26b2aafa719f73.png

자신의 애플리케이션에 적합한 설정을 선택합니다. 이 튜토리얼과 최소한의 요구가 있는 샘플 앱의 경우 비용을 최소화하는 것이 합리적이므로 앞에서 다룬 권장사항을 따르세요. 선택을 완료한 후 만들기를 클릭합니다. VPC 커넥터 요청을 완료하는 데 몇 분 정도 걸립니다.

명령줄에서

VPC 커넥터를 만들기 전에 먼저 Serverless VPC Access API를 사용 설정하세요. 다음 명령어를 실행하면 비슷한 출력이 표시됩니다.

$ gcloud services enable vpcaccess.googleapis.com
Operation "operations/acf.p2-aaa-bbb-ccc-ddd-eee-ffffff" finished successfully.

API가 사용 설정되면 다음과 같은 명령어로 VPC 커넥터가 생성됩니다.

gcloud compute networks vpc-access connectors create CONNECTOR_NAME \
    --range 10.8.0.0/28 --region REGION --project PROJECT_ID

커넥터 이름과 사용되지 않은 /28 CIDR 블록 시작 IP 주소를 선택하세요. 이 가이드에서는 다음과 같이 가정합니다.

  • 프로젝트 ID: my-project
  • VPC 커넥터 이름: demo-vpc
  • 최소 인스턴스: 2개 (기본값) 및 최대 인스턴스 수: 3개
  • 인스턴스 유형: f1-micro
  • 리전: us-central1
  • IPv4 CIDR 블록: 10.8.0.0/28 (Cloud Console에서 권장됨)

위의 가정을 염두에 두고 다음 명령어를 실행하면 아래와 비슷한 출력이 표시됩니다.

$ gcloud compute networks vpc-access connectors create demo-vpc \
    --max-instances 3 --range 10.8.0.0/28 --machine-type f1-micro \
    --region us-central1  --project my-project

Create request issued for: [demo-vpc]
Waiting for operation [projects/my-project/locations/us-central1/operations/xxx] to complete...done.
Created connector [demo-vpc].

위의 명령어는 최소 인스턴스 2 및 default라는 네트워크와 같은 기본값 지정을 생략합니다. VPC 커넥터를 만드는 데 몇 분 정도 걸립니다.

커넥터 생성 확인

프로세스가 완료되면 us-central1 리전이라고 가정하고 다음 gcloud 명령어를 실행하여 명령어가 생성되고 사용할 준비가 되었는지 확인합니다.

$ gcloud compute networks vpc-access connectors list --region us-central1
CONNECTOR_ID  REGION       NETWORK  IP_CIDR_RANGE  SUBNET  SUBNET_PROJECT  MIN_THROUGHPUT  MAX_THROUGHPUT  STATE
demo-vpc      us-central1  default  10.8.0.0/28                            200             300             READY

마찬가지로 대시보드에는 방금 만든 커넥터가 표시됩니다.

e03db2c8140ed014.png

Cloud 프로젝트 ID, VPC 커넥터 이름, 리전을 기록합니다.

이제 명령줄 또는 콘솔에서 필요한 추가 Cloud 리소스를 만들었으므로 사용을 지원하도록 애플리케이션 구성을 업데이트할 차례입니다.

5. 구성 파일 업데이트

첫 번째 단계는 구성 파일에 필요한 모든 업데이트를 수행하는 것입니다. Python 2 사용자의 이전을 돕는 것이 이 Codelab의 주요 목표이지만, 보통 이 내용에 이어 아래의 각 섹션에서 Python 3로의 추가 포팅에 관한 정보가 이어집니다.

requirements.txt

이 섹션에서는 Cloud Memorystore와 Cloud Memorystore를 지원하는 패키지를 추가합니다. Redis용 Cloud Memorystore의 경우 Cloud Memorystore 클라이언트 라이브러리 자체가 없으므로 Python용 표준 Redis 클라이언트 (redis)를 사용해도 됩니다. redisgoogle-cloud-ndb를 모두 requirements.txt에 추가하고 모듈 12의 flask를 조인합니다.

flask
redis
google-cloud-ndb

requirements.txt 파일에는 버전 번호가 없습니다. 즉, 최신 버전이 선택됩니다. 비호환성 문제가 발생하는 경우 버전 번호를 지정하여 작동하는 버전을 고정합니다.

app.yaml

추가할 새 섹션

Python 2 App Engine 런타임은 Cloud NBS와 같은 Cloud API를 사용할 때 grpciosetuptools라는 특정 서드 파티 패키지가 필요합니다. Python 2 사용자는 app.yaml에서 사용 가능한 버전과 함께 이러한 기본 제공 라이브러리를 나열해야 합니다. 아직 libraries 섹션이 없다면 다음과 같이 섹션을 만들고 두 라이브러리를 모두 추가합니다.

libraries:
- name: grpcio
  version: latest
- name: setuptools
  version: latest

앱을 이전할 때 이미 libraries 섹션이 있을 수 있습니다. 포함되어 있는데 grpciosetuptools가 누락되었다면 기존 libraries 섹션에 추가하기만 하면 됩니다.

다음으로 샘플 앱에는 Cloud Memorystore 인스턴스와 VPC 커넥터 정보가 필요하므로 사용 중인 Python 런타임과 관계없이 app.yaml에 다음 두 섹션을 새로 추가합니다.

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

필수 업데이트에 대한 설명은 여기까지입니다. 이제 업데이트된 app.yaml가 다음과 같이 표시됩니다.

runtime: python27
threadsafe: yes
api_version: 1

handlers:
- url: /.*
  script: main.app

libraries:
- name: grpcio
  version: 1.0.0
- name: setuptools
  version: 36.6.0

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

아래는 '이전과 이후'의 비교입니다 app.yaml에 적용해야 하는 업데이트 그림:

ec2bb027a67debb6.png

*Python 3의 차이점

이 섹션은 선택사항이며 Python 3로 포팅하는 경우에만 해당됩니다. 이를 위해 Python 2 구성을 여러 가지로 변경해야 합니다. 현재 업그레이드를 하지 않는 경우 이 섹션을 건너뛰세요.

Python 3 런타임에는 threadsafeapi_version가 모두 사용되지 않으므로 두 설정을 모두 삭제합니다. 최신 App Engine 런타임은 내장된 서드 파티 라이브러리 또는 비기본 제공 라이브러리의 복사를 지원하지 않습니다. 서드 파티 패키지의 유일한 요구사항은 이를 requirements.txt에 나열하는 것입니다. 따라서 app.yaml의 전체 libraries 섹션이 삭제될 수 있습니다.

다음으로 Python 3 런타임은 자체 라우팅을 수행하는 웹 프레임워크를 사용해야 하므로 모듈 1에서 webp2에서 Flask로 마이그레이션하는 방법을 개발자에게 보여드렸습니다. 따라서 모든 스크립트 핸들러는 auto로 변경되어야 합니다. 이 앱은 정적 파일을 제공하지 않으므로 무의미합니다. 핸들러가 모두 auto이므로 전체 handlers 섹션도 삭제될 수 있습니다. 따라서 Python 3에 맞게 조정된 새로운 축약된 app.yaml는 다음과 같이 축약되어야 합니다.

runtime: python39

env_variables:
    REDIS_HOST: 'YOUR_REDIS_HOST'
    REDIS_PORT: 'YOUR_REDIS_PORT'

vpc_access_connector:
    name: projects/PROJECT_ID/locations/REGION/connectors/CONNECTOR

Python 3로 포팅할 때 app.yaml의 차이점을 요약합니다.

  • threadsafeapi_version 설정 삭제
  • libraries 섹션 삭제
  • handlers 섹션 (또는 앱에서 정적 파일을 제공하는 경우 script 핸들러만 삭제) 삭제

값 바꾸기

Memorystore 및 VPC 커넥터의 새 섹션에 있는 값은 자리표시자일 뿐입니다. 대문자 값 (YOUR_REDIS_HOST, YOUR_REDIS_PORT, PROJECT_ID, REGION, CONNECTOR_NAME)을 이전에 리소스를 만들 때 저장된 값으로 바꿉니다. Memorystore 인스턴스와 관련하여 HOST (RESERVED_IP 아님) 및 PORT를 사용해야 합니다. 다음은 인스턴스 이름이 demo-ms이고 REGIONus-central1라고 가정하고 HOSTPORT를 가져오는 빠른 명령줄 방법입니다.

$ gcloud redis instances describe demo-ms --region us-central1 \
    --format "value(host,port)"
10.251.161.51   6379

예시 Redis 인스턴스 IP 주소가 VPC 커넥터 이름이 demo-vpcus-central1 리전에 있는 my-project 프로젝트에서 포트 6379을 사용하는 10.10.10.10이었다면 app.yaml의 해당 섹션은 다음과 같이 표시됩니다.

env_variables:
    REDIS_HOST: '10.10.10.10'
    REDIS_PORT: '6379'

vpc_access_connector:
    name: projects/my-project/locations/us-central1/connectors/demo-vpc

appengine_config.py 만들기 또는 업데이트

내장된 서드 파티 라이브러리 지원 추가

앞서 app.yaml로 한 것처럼 grpciosetuptools 라이브러리 사용법을 추가합니다. 내장된 서드 파티 라이브러리를 지원하도록 appengine_config.py를 수정합니다. 이 내용이 익숙해 보인다면 App Engine ndb에서 Cloud NBS로 마이그레이션할 때 모듈 2에서도 이 기능을 요구했기 때문입니다. 정확히 변경해야 하는 경우 lib 폴더를 setuptools.pkg_resources 작업 세트에 추가해야 합니다.

4140b3800694f77e.png

*Python 3의 차이점

이 섹션은 선택사항이며 Python 3로 포팅하는 경우에만 해당됩니다. App Engine 2세대 변경사항 중 하나는 내장되지 않은 서드 파티 패키지를 복사('벤더링'이라고도 함)하고 app.yaml에서 내장된 서드 파티 패키지를 참조하는 것이 더 이상 필요하지 않다는 것입니다. 즉, 전체 appengine_config.py 파일을 삭제할 수 있습니다.

6. 애플리케이션 파일 업데이트

애플리케이션 파일(main.py) 하나만 있으므로 이 섹션의 모든 변경사항은 해당 파일에만 영향을 미칩니다. 이 애플리케이션을 Cloud Memorystore로 마이그레이션하기 위해 수행할 변경사항을 그림으로 표현했습니다. 이 데이터는 설명을 위한 예시일 뿐이며 상세하게 분석하기 위한 것이 아닙니다. 모든 작업은 코드를 변경하는 데 있습니다.

5d043768ba7be742.png

상단부터 한 번에 한 섹션씩 처리해 보겠습니다.

가져오기 업데이트

모듈 12의 main.py에 있는 가져오기 섹션에서는 Cloud NBS와 Cloud Tasks를 사용합니다. 가져온 항목은 다음과 같습니다.

이전:

from flask import Flask, render_template, request
from google.appengine.api import memcache
from google.appengine.ext import ndb

Memorystore로 전환하려면 환경 변수를 읽어야 합니다. 즉, Python os 모듈과 Python Redis 클라이언트인 redis가 필요합니다. Redis는 Python 객체를 캐시할 수 없으므로 pickle를 사용하여 최근 방문 목록을 마샬링하므로 이 목록도 가져옵니다. Memcache의 장점 중 하나는 객체 직렬화가 자동으로 이루어지는 반면 Memorystore는 'DIY'에 더 가깝다는 것입니다. 마지막으로 google.appengine.ext.ndbgoogle.cloud.ndb로 바꿔 App Engine ndb에서 Cloud NFS로 업그레이드합니다. 이러한 변경사항을 적용하면 가져오기가 다음과 같이 표시됩니다.

변경 후:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

초기화 업데이트

모듈 12 초기화는 Flask 애플리케이션 객체 app를 인스턴스화하고 1시간 분량의 캐싱을 위한 상수를 설정하는 것으로 구성됩니다.

이전:

app = Flask(__name__)
HOUR = 3600

Cloud API를 사용하려면 클라이언트가 필요하므로 Flask 직후에 Cloud NBS 클라이언트를 인스턴스화합니다. 다음으로 app.yaml에 설정한 환경 변수에서 Memorystore 인스턴스의 IP 주소와 포트 번호를 가져옵니다. 이 정보로 무장하고 Redis 클라이언트를 인스턴스화합니다. 이 업데이트 후 코드는 다음과 같이 표시됩니다.

변경 후:

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

*Python 3 마이그레이션

이 섹션은 선택사항이며 모듈 12 앱의 Python 3 버전을 시작하는 경우에 적합합니다. 그렇다면 가져오기 및 초기화와 관련된 몇 가지 필수 변경사항이 있습니다.

첫째, Memcache는 App Engine 번들 서비스이므로 Python 3 앱에서 사용하려면 WSGI 애플리케이션을 래핑하는 App Engine SDK (및 기타 필수 구성)가 필요합니다.

이전:

from flask import Flask, render_template, request
from google.appengine.api import memcache, wrap_wsgi_app
from google.appengine.ext import ndb

app = Flask(__name__)
app.wsgi_app = wrap_wsgi_app(app.wsgi_app)
HOUR = 3600

Memcache와 같은 App Engine 번들 서비스가 아닌 Cloud Memorystore로 마이그레이션 중이므로 SDK 사용을 삭제해야 합니다. memcachewrap_wsgi_app를 모두 가져오는 전체 줄을 삭제하기만 하면 되므로 간단합니다. wrap_wsgi_app()를 호출하는 줄도 삭제합니다. 업데이트를 통해 앱의 이 부분 (실제로 전체 앱)이 Python 2 버전과 동일하게 유지됩니다.

변경 후:

import os
import pickle
from flask import Flask, render_template, request
from google.cloud import ndb
import redis

app = Flask(__name__)
ds_client = ndb.Client()
HOUR = 3600
REDIS_HOST = os.environ.get('REDIS_HOST', 'localhost')
REDIS_PORT = os.environ.get('REDIS_PORT', '6379')
REDIS = redis.Redis(host=REDIS_HOST, port=REDIS_PORT)

마지막으로 app.yaml (app_engine_apis: true 줄 삭제) 및 requirements.txt (appengine-python-standard 줄 삭제)에서 SDK 사용을 삭제합니다.

Cloud Memorystore (및 Cloud NBS)로 마이그레이션

Cloud NBS의 데이터 모델은 App Engine ndb의 데이터 모델과 호환되도록 되어 있습니다. 즉, Visit 객체의 정의가 동일하게 유지됩니다. 모듈 2에서 Cloud NBS로의 마이그레이션을 모방할 때 store_visit()fetch_visits()의 모든 Datastore 호출이 보강되고 새 with 블록에 삽입됩니다 (Cloud NFS 컨텍스트 관리자 사용이 필요하기 때문). 변경 전의 호출은 다음과 같습니다.

이전:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    return Visit.query().order(-Visit.timestamp).fetch(limit)

두 함수에 with ds_client.context() 블록을 추가하고 Datastore 호출을 내부에 삽입합니다. 이 경우 호출 자체를 변경할 필요가 없습니다.

변경 후:

def store_visit(remote_addr, user_agent):
    'create new Visit entity in Datastore'
    with ds_client.context():
        Visit(visitor='{}: {}'.format(remote_addr, user_agent)).put()

def fetch_visits(limit):
    'get most recent visits'
    with ds_client.context():
        return Visit.query().order(-Visit.timestamp).fetch(limit)

다음으로 캐싱 변경사항을 살펴보겠습니다. 다음은 모듈 12의 main() 함수입니다.

이전:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    visits = memcache.get('visits')

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        memcache.set('visits', visits, HOUR)  # set() not add()

    return render_template('index.html', visits=visits)

Redis의 'get' 및 'set' 일반적인 작업을 수행합니다 각 클라이언트 라이브러리를 교체하기만 하면 됩니다. 거의 정확합니다. 앞서 언급했듯이 Redis로 Python 목록을 캐시할 수 없습니다 (먼저 직렬화해야 하므로 Memcache가 자동으로 처리해야 하기 때문). 따라서 set() 호출에서 'pickle'을 사용합니다. pickle.dumps()를 사용하여 방문을 문자열로 변환합니다. 마찬가지로 캐시에서 방문을 가져올 때 get() 바로 뒤에 pickle.loads()를 사용하여 피클을 해제해야 합니다. 다음은 이러한 변경사항을 구현한 후의 기본 핸들러입니다.

변경 후:

@app.route('/')
def root():
    'main application (GET) handler'
    # check for (hour-)cached visits
    ip_addr, usr_agt = request.remote_addr, request.user_agent
    visitor = '{}: {}'.format(ip_addr, usr_agt)
    rsp = REDIS.get('visits')
    visits = pickle.loads(rsp) if rsp else None

    # register visit & run DB query if cache empty or new visitor
    if not visits or visits[0].visitor != visitor:
        store_visit(ip_addr, usr_agt)
        visits = list(fetch_visits(10))
        REDIS.set('visits', pickle.dumps(visits), ex=HOUR)

    return render_template('index.html', visits=visits)

이것으로 샘플 앱의 Memcache 사용을 Cloud Memorystore로 변환하는 main.py에 필요한 변경사항이 완료되었습니다. HTML 템플릿 및 Python 3로 포팅은 어떨까요?

HTML 템플릿 파일과 포트를 Python 3으로 업데이트하시겠습니까?

깜짝이야! 이 애플리케이션은 코드 변경이나 호환성 라이브러리 없이 Python 2와 3에서 모두 실행되도록 설계되었기 때문에 여기서는 수행할 작업이 없습니다. main.py를 찾을 수 있습니다. mod13a (2.x) 및 mod13b (3.x) 'FINISH'에서 동일함 폴더를 만들 수 있습니다 버전 번호의 차이 (사용된 경우)를 제외하고 requirements.txt도 마찬가지입니다. 사용자 인터페이스는 변경되지 않으므로 templates/index.html도 업데이트되지 않습니다.

Python 3 App Engine에서 이 앱을 실행하는 데 필요한 모든 내용은 구성 초기에 완료되었습니다. 불필요한 지시어는 app.yaml에서 삭제되었으며 appengine_config.pylib 폴더는 Python 3에서 사용되지 않으므로 삭제되었습니다.

7. 요약/삭제

이 섹션에서는 앱을 배포하고 의도한 대로 반영된 출력에서 작동하는지 확인하여 이 Codelab을 마무리합니다. 앱 유효성 검사 후 정리를 수행하고 다음 단계를 고려합니다.

애플리케이션 배포 및 확인

마지막 확인 단계는 항상 샘플 앱을 배포하는 것입니다. Python 2 개발자: 아래 명령어로 lib를 삭제하고 다시 설치합니다. Python 2와 3이 시스템에 모두 설치되어 있는 경우에는 대신 명시적으로 pip2를 실행해야 할 수 있습니다.

rm -rf ./lib
pip install -t lib -r requirements.txt

이제 Python 2 및 3 개발자 모두 다음을 사용하여 앱을 배포해야 합니다.

gcloud app deploy

완전히 다른 캐싱 서비스를 위해 내부에서 다시 연결만 하기 때문에 앱 자체는 모듈 12 앱과 동일하게 작동해야 합니다.

모듈 7 visitme 앱

이 단계로 Codelab이 완료되었습니다. 업데이트된 샘플 앱을 모듈 13 폴더 mod13a (Python 2) 또는 mod13b (Python 3) 중 하나와 비교해 보세요.

삭제

일반

이 작업이 완료되면 요금이 청구되지 않도록 App Engine 앱을 사용 중지하는 것이 좋습니다. 하지만 추가 테스트 또는 실험을 원하는 경우 App Engine 플랫폼에서 무료 할당량을 사용할 수 있으므로 이 사용 등급을 초과하지 않는 한 요금이 청구되지 않습니다. 이는 컴퓨팅을 위한 것이며, 관련 App Engine 서비스에 대한 요금이 부과될 수 있으므로 자세한 내용은 가격 책정 페이지를 확인하세요. 이 마이그레이션에 다른 Cloud 서비스가 포함된 경우 별도로 요금이 청구됩니다. 두 경우 모두 해당하는 경우 '이 Codelab과 관련된 내용'을 참고하세요. 섹션을 참조하세요.

자세히 알려드리자면 App Engine과 같은 Google Cloud 서버리스 컴퓨팅 플랫폼에 배포할 경우 약간의 빌드 및 스토리지 비용이 발생합니다. Cloud Build에는 Cloud Storage와 마찬가지로 자체 무료 할당량이 있습니다. 해당 이미지의 스토리지가 할당량 중 일부를 사용합니다. 하지만 이러한 무료 등급이 없는 지역에 거주할 수도 있으므로 잠재적인 비용을 최소화하려면 저장용량 사용량에 유의해야 합니다. 특정 Cloud Storage '폴더' 다음을 포함해야 합니다.

  • console.cloud.google.com/storage/browser/LOC.artifacts.PROJECT_ID.appspot.com/containers/images
  • console.cloud.google.com/storage/browser/staging.PROJECT_ID.appspot.com
  • 위의 스토리지 링크는 PROJECT_ID 및 *LOC*기호에 따라 다릅니다(예: 'us'). (앱이 미국에서 호스팅되는 경우)

반면 이 애플리케이션 또는 다른 관련 이전 Codelab을 계속 진행하지 않고 모든 항목을 완전히 삭제하려면 프로젝트를 종료합니다.

이 Codelab에만 해당

아래에 나열된 서비스는 이 Codelab의 고유한 서비스입니다. 자세한 내용은 각 제품의 문서를 참조하세요.

이 튜토리얼에서는 네 가지 Cloud 제품 사용법이 포함되어 있습니다.

  • App Engine
  • Cloud Datastore
  • Cloud Memorystore
  • Cloud VPC

다음은 이러한 리소스를 해제하고 요금이 청구되지 않도록 하는 방법입니다.

Memorystore 인스턴스 및 VPC 커넥터 종료

이러한 제품은 무료 등급없는 제품이므로 지금 요금이 청구됩니다. Cloud 프로젝트를 종료하지 않은 경우 (다음 섹션 참조) 청구를 중지하려면 Memorystore 인스턴스와 VPC 커넥터를 모두 삭제해야 합니다. 이러한 리소스를 만들 때와 마찬가지로 Cloud 콘솔 또는 명령줄에서 리소스를 해제할 수도 있습니다.

Cloud 콘솔에서

Memorystore 인스턴스를 삭제하려면 Memorystore 대시보드로 돌아가서 인스턴스 ID를 클릭합니다.

2b09baf1aa2e0a25.png

해당 인스턴스의 세부정보 페이지에서 '삭제'를 클릭합니다. 다음을 확인합니다.

f9d9eb1c1d4c6107.png

VPC 커넥터를 삭제하려면 해당 대시보드로 이동하여 삭제할 커넥터 옆의 체크박스를 선택한 후 '삭제'를 클릭하세요. 다음을 확인합니다.

ca5fbd9f4c7c9b60.png

명령줄에서

다음 gcloud 명령어 쌍은 각각 Memorystore 인스턴스와 VPC 커넥터를 모두 삭제합니다.

  • gcloud redis instances delete INSTANCE --region REGION
  • gcloud compute networks vpc-access connectors delete CONNECTOR --region REGION

gcloud config set project로 프로젝트 ID를 설정하지 않았다면 --project PROJECT_ID를 제공해야 할 수 있습니다. Memorystore 인스턴스 이름이 demo-ms이고 VPC 커넥터가 demo-vpc이고 둘 다 us-central1 리전에 있는 경우 다음 명령어 쌍을 실행하고 확인합니다.

$ gcloud redis instances delete demo-ms --region us-central1
You are about to delete instance [demo-ms] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-ms]
Waiting for operation [projects/PROJECT/locations/REGION/operations/operation-aaaaa-bbbbb-ccccc-ddddd] to complete...done.
Deleted instance [demo-ms].
$
$ gcloud compute networks vpc-access connectors delete demo-vpc --region us-central1
You are about to delete connector [demo-vpc] in [us-central1].
Any associated data will be lost.

Do you want to continue (Y/n)?

Delete request issued for: [demo-vpc]
Waiting for operation [projects/PROJECT/locations/REGION/operations/aaaaa-bbbb-cccc-dddd-eeeee] to complete...done.
Deleted connector [demo-vpc].

각 요청을 실행하는 데 몇 분 정도 걸립니다. 앞서 설명한 대로 전체 Cloud 프로젝트를 종료하는 경우 이 단계는 선택사항이지만 종료 프로세스가 완료될 때까지는 요금이 계속 청구됩니다.

다음 단계

이 튜토리얼 외에도 기존 번들 서비스에서 벗어나는 데 중점을 둔 다른 마이그레이션 모듈에는 다음이 포함됩니다.

  • 모듈 2: App Engine ndb에서 Cloud Dataplex로 마이그레이션
  • 모듈 7~9: App Engine 태스크 큐 푸시 태스크에서 Cloud Tasks로 마이그레이션
  • 모듈 12~13: App Engine Memcache에서 Cloud Memorystore로 마이그레이션
  • 모듈 15~16: App Engine blobstore에서 Cloud Storage로 이전
  • 모듈 18~19: App Engine 작업 대기열 (가져오기 작업)에서 Cloud Pub/Sub로 마이그레이션

Google Cloud의 서버리스 플랫폼은 더 이상 App Engine이 아닙니다. App Engine 앱이 작거나 기능이 제한적이며 독립형 마이크로서비스로 전환하려는 경우 또는 모놀리식 앱을 재사용 가능한 여러 구성요소로 분할하려는 경우 Cloud Functions로 이전하는 것이 좋습니다. 특히 CI/CD (지속적 통합/지속적 배포 또는 배포) 파이프라인으로 구성된 컨테이너화가 애플리케이션 개발 워크플로의 일부가 되었다면 Cloud Run으로 마이그레이션하는 것이 좋습니다. 이러한 시나리오는 다음 모듈에서 다룹니다.

  • App Engine에서 Cloud Functions로 마이그레이션: 모듈 11 참조
  • App Engine에서 Cloud Run으로 마이그레이션: Docker로 앱을 컨테이너화하려면 모듈 4를 참조하고, 컨테이너, Docker 지식 또는 Dockerfile 없이 마이그레이션하려면 모듈 5를 참조하세요.

다른 서버리스 플랫폼으로 전환하는 것은 선택사항이며 변경하기 전에 앱 및 사용 사례에 가장 적합한 옵션을 고려하는 것이 좋습니다.

다음으로 고려할 마이그레이션 모듈과 관계없이 모든 서버리스 마이그레이션 스테이션 콘텐츠 (Codelab, 동영상, 소스 코드[사용 가능한 경우])는 오픈소스 저장소에서 액세스할 수 있습니다. 저장소의 README는 고려할 이전 및 관련 '순서'에 관한 안내도 제공합니다. 오신 것을 환영합니다

8. 추가 리소스

아래에는 이 모듈이나 관련 이전 모듈 및 관련 제품을 자세히 살펴보는 개발자를 위한 추가 리소스가 나열되어 있습니다. 여기에는 이 콘텐츠에 대한 의견을 제공할 수 있는 곳, 코드 링크 및 도움이 될 만한 다양한 문서가 포함됩니다.

Codelabs 문제/의견

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

마이그레이션 리소스

모듈 12 (START)와 모듈 13 (FINISH)의 저장소 폴더 링크는 아래 표에서 찾을 수 있습니다. 또한 ZIP 파일을 클론하거나 다운로드할 수 있는 모든 App Engine Codelab 이전 저장소에서도 액세스할 수 있습니다.

Codelab

Python 2

Python 3

모듈 12

코드

코드

모듈 13 (본 Codelab)

코드

코드

온라인 참조

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

App Engine

App Engine Dataplex 및 Cloud Dataplex

App Engine Memcache 및 Cloud Memorystore

Cloud VPC

기타 클라우드 정보

라이선스

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