1. 소개
Cloud Spanner는 수평 확장이 가능하며 전 세계에 분산된 완전 관리형 관계형 데이터베이스 서비스로, 성능과 고가용성을 그대로 유지하면서 ACID 트랜잭션과 SQL 시맨틱스를 제공합니다.
GKE Autopilot은 GKE에서 Google이 권장사항에 따라 노드, 확장, 보안, 기타 사전 구성된 설정을 관리하는 GKE의 작업 모드입니다. 예를 들어 GKE Autopilot은 워크로드 아이덴티티가 서비스 권한을 관리하도록 사용 설정합니다.
이 실습의 목표는 GKE Autopilot에서 실행되는 여러 백엔드 서비스를 Cloud Spanner 데이터베이스에 연결하는 프로세스를 설명하는 것입니다.
이 실습에서는 먼저 프로젝트를 설정하고 Cloud Shell을 실행합니다. 그런 다음 Terraform을 사용하여 인프라를 배포합니다.
이 작업이 완료되면 Cloud Build 및 Cloud Deploy와 상호작용하여 게임 데이터베이스의 초기 스키마 마이그레이션을 수행하고 백엔드 서비스를 배포한 다음 워크로드를 배포합니다.
이 Codelab의 서비스는 Cloud Spanner 게임 개발 시작하기 Codelab과 동일합니다. 서비스를 GKE에서 실행하고 Spanner에 연결하기 위해 이 Codelab을 반드시 진행할 필요는 없습니다. Spanner에서 작동하는 서비스의 세부사항에 대해 자세히 알고 싶으시다면 확인해 보세요.
워크로드 및 백엔드 서비스가 실행 중이면 부하 생성을 시작하고 두 서비스가 연동되는 방식을 관찰할 수 있습니다.
마지막으로 이 실습에서 만든 리소스를 삭제합니다.
빌드할 항목
이 실습에서 학습할 내용은 다음과 같습니다.
- Terraform을 사용하여 인프라 프로비저닝하기
- Cloud Build에서 스키마 마이그레이션 프로세스를 사용하여 데이터베이스 스키마 만들기
- 워크로드 아이덴티티를 활용하는 4개의 Golang 백엔드 서비스를 배포하여 Cloud Spanner에 연결합니다.
- 백엔드 서비스의 부하를 시뮬레이션하는 데 사용되는 4가지 워크로드 서비스를 배포합니다.
학습할 내용
- Terraform을 사용하여 GKE Autopilot, Cloud Spanner, Cloud Deploy 파이프라인을 프로비저닝하는 방법
- 워크로드 아이덴티티를 통해 GKE의 서비스가 서비스 계정을 가장하여 Cloud Spanner에서 작동하는 IAM 권한에 액세스할 수 있는 방법
- Locust.io를 사용하여 GKE 및 Cloud Spanner에서 프로덕션과 유사한 부하를 생성하는 방법
필요한 항목
2. 설정 및 요건
프로젝트 만들기
아직 Google 계정(Gmail 또는 Google Apps)이 없으면 계정을 만들어야 합니다. Google Cloud Platform 콘솔 ( console.cloud.google.com)에 로그인하여 새 프로젝트를 만듭니다.
프로젝트가 이미 있으면 Console 왼쪽 위에서 프로젝트 선택 풀다운 메뉴를 클릭합니다.
'새 프로젝트'를 클릭합니다. 버튼을 클릭하여 새 프로젝트를 만듭니다.
아직 프로젝트가 없으면 첫 번째 프로젝트를 만들기 위해 다음과 비슷한 대화상자가 표시됩니다.
이후의 프로젝트 만들기 대화상자에서 새 프로젝트의 세부정보를 입력할 수 있습니다.
모든 Google Cloud 프로젝트에서 고유한 이름인 프로젝트 ID를 기억하세요(위의 이름은 이미 사용되었으므로 사용할 수 없습니다). 이 ID는 나중에 이 Codelab에서 PROJECT_ID
라고 부릅니다.
그런 다음 Google Cloud 리소스를 사용하고 Cloud Spanner API를 사용 설정하기 위해서는 아직 완료하지 않은 경우 Developers Console에서 결제를 사용 설정해야 합니다.
이 codelab을 실행하는 과정에는 많은 비용이 들지 않지만 더 많은 리소스를 사용하려고 하거나 실행 중일 경우 비용이 더 들 수 있습니다(이 문서 마지막의 '삭제' 섹션 참조). Google Cloud Spanner 가격 책정은 여기에, GKE Autopilot 가격은 여기에 나와 있습니다.
Google Cloud Platform 신규 사용자는 $300 상당의 무료 체험판을 사용할 수 있으므로, 이 Codelab을 완전히 무료로 사용할 수 있습니다.
Cloud Shell 설정
Google Cloud 및 Spanner를 노트북에서 원격으로 실행할 수 있지만, 이 Codelab에서는 Cloud에서 실행되는 명령줄 환경인 Google Cloud Shell을 사용합니다.
이 Debian 기반 가상 머신에는 필요한 모든 개발 도구가 로드되어 있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 Google Cloud에서 실행되므로 네트워크 성능과 인증이 크게 개선됩니다. 즉, 이 Codelab에 필요한 것은 브라우저뿐입니다(Chromebook에서도 작동 가능).
- Cloud 콘솔에서 Cloud Shell을 활성화하려면 Cloud Shell 활성화 를 클릭하세요. 환경을 프로비저닝하고 연결하는 데 몇 분 정도 걸립니다.
Cloud Shell에 연결되면 사용자 인증이 이미 완료되었고 프로젝트가 내 PROJECT_ID
에 설정되어 있음을 확인할 수 있습니다.
gcloud auth list
명령어 결과
Credentialed accounts:
- <myaccount>@<mydomain>.com (active)
gcloud config list project
명령어 결과
[core]
project = <PROJECT_ID>
어떤 이유로든 프로젝트가 설정되지 않았으면 다음 명령어를 실행하면 됩니다.
gcloud config set project <PROJECT_ID>
PROJECT_ID
를 찾고 계신가요? 설정 단계에서 사용한 ID를 확인하거나 Cloud Console 대시보드에서 확인하세요.
또한 Cloud Shell은 기본적으로 이후 명령어를 실행할 때 유용할 수 있는 몇 가지 환경 변수를 설정합니다.
echo $GOOGLE_CLOUD_PROJECT
명령어 결과
<PROJECT_ID>
코드 다운로드
Cloud Shell에서 이 실습의 코드를 다운로드할 수 있습니다.
git clone https://github.com/cloudspannerecosystem/spanner-gaming-sample.git
명령어 결과
Cloning into 'spanner-gaming-sample'...
*snip*
이 Codelab은 v0.1.3 버전을 기반으로 하므로 다음 태그를 확인하세요.
cd spanner-gaming-sample
git fetch --all --tags
# Check out v0.1.3 release
git checkout tags/v0.1.3 -b v0.1.3-branch
명령어 결과
Switched to a new branch 'v0.1.3-branch'
이제 현재 작업 디렉터리를 DEMO_HOME 환경 변수로 설정합니다. 이렇게 하면 Codelab의 다양한 부분을 살펴볼 때 더 쉽게 탐색할 수 있습니다.
export DEMO_HOME=$(pwd)
요약
이 단계에서는 새 프로젝트를 설정하고, Cloud Shell을 활성화하고, 이 실습용 코드를 다운로드했습니다.
다음 단계
다음으로 Terraform을 사용하여 인프라를 프로비저닝합니다.
3. 인프라 프로비저닝하기
개요
프로젝트가 준비되었으면 인프라를 실행할 차례입니다. 여기에는 GKE에서 실행될 이미지를 저장하는 VPC 네트워킹, Cloud Spanner, GKE Autopilot, Artifact Registry, 백엔드 서비스 및 워크로드를 위한 Cloud Deploy 파이프라인, 마지막으로 이러한 서비스를 사용할 수 있는 서비스 계정과 IAM 권한이 포함됩니다.
엄청나게 많습니다. 다행히 Terraform은 이러한 설정을 간소화할 수 있습니다. Terraform은 '코드형 인프라' 일련의 '.tf'에서 이 프로젝트에 필요한 것을 지정할 수 있는 할 수 있습니다. 따라서 프로비저닝 인프라가 간단해집니다.
Terraform에 익숙하다고 해서 이 Codelab을 완료할 필요는 없습니다. 하지만 다음 몇 단계의 작업이 궁금하다면 Infrastructure 디렉터리에 있는 다음 파일에서 생성된 내용을 살펴보세요.
- vpc.tf
- backend_gke.tf
- spanner.tf
- artifact_registry.tf
- pipelines.tf
- iam.tf
Terraform 구성
Cloud Shell에서 infrastructure
디렉터리로 변경하고 Terraform을 초기화합니다.
cd $DEMO_HOME/infrastructure
terraform init
명령어 결과
Initializing the backend...
Initializing provider plugins...
*snip*
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
다음으로 terraform.tfvars.sample
를 복사하고 프로젝트 값을 수정하여 Terraform을 구성합니다. 다른 변수도 변경할 수 있지만 환경에서 작업하려면 프로젝트만 변경해야 합니다.
cp terraform.tfvars.sample terraform.tfvars
# edit gcp_project using the project environment variable
sed -i "s/PROJECT/$GOOGLE_CLOUD_PROJECT/" terraform.tfvars
인프라 프로비저닝
이제 인프라를 프로비저닝할 차례입니다.
terraform apply
# review the list of things to be created
# type 'yes' when asked
명령어 결과
Plan: 46 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
google_project_service.project["container.googleapis.com"]: Creating...
*snip*
Apply complete! Resources: 46 added, 0 changed, 0 destroyed.
생성된 항목 확인
생성된 제품을 확인하기 위해 Cloud 콘솔에서 제품을 확인하려고 합니다.
Cloud Spanner
먼저 햄버거 메뉴로 이동하여 Spanner
를 클릭하여 Cloud Spanner를 확인합니다. '제품 더보기'를 클릭해야 할 수도 있습니다 목록에서 찾을 수 있습니다.
Spanner 인스턴스 목록으로 이동합니다. 인스턴스를 클릭하면 데이터베이스가 표시됩니다. 예를 들면 다음과 같습니다.
GKE Autopilot
다음으로 햄버거 메뉴로 이동하여 Kubernetes Engine => Clusters
를 클릭하여 GKE를 확인합니다. 여기에 Autopilot 모드로 실행되는 sample-games-gke
클러스터가 표시됩니다.
Artifact Registry
이제 이미지가 저장되는 위치를 확인할 차례입니다. 햄버거 메뉴를 클릭하고 Artifact Registry=>Repositories
를 찾습니다. Artifact Registry는 메뉴의 CI/CD 섹션에 있습니다.
여기에 spanner-game-images
라는 Docker 레지스트리가 표시됩니다. 지금은 비어 있습니다.
Cloud Deploy
Cloud Deploy는 Cloud Build가 이미지를 빌드한 후 GKE 클러스터에 배포하는 단계를 제공할 수 있도록 파이프라인이 생성된 곳입니다.
햄버거 메뉴로 이동하여 메뉴의 CI/CD 섹션에도 있는 Cloud Deploy
를 찾습니다.
여기에서 두 개의 파이프라인을 확인할 수 있습니다. 하나는 백엔드 서비스용이고 다른 하나는 워크로드용입니다. 둘 다 동일한 GKE 클러스터에 이미지를 배포하지만 배포를 분리할 수 있습니다.
IAM
마지막으로 Cloud 콘솔의 IAM 페이지에서 생성된 서비스 계정을 확인합니다. 햄버거 메뉴로 이동하여 IAM and Admin=>Service accounts
을 찾습니다. 예를 들면 다음과 같습니다.
Terraform에서 생성되는 총 6개의 서비스 계정은 다음과 같습니다.
- 기본 컴퓨터 서비스 계정입니다. 이 Codelab에서는 사용되지 않습니다.
- cloudbuild-cicd 계정은 Cloud Build 및 Cloud Deploy 단계에 사용됩니다.
- 4가지 '앱' Google Cloud의 백엔드 서비스에서 Cloud Spanner와 상호작용하는 데 사용하는 계정입니다.
다음으로 GKE 클러스터와 상호작용하도록 kubectl
를 구성합니다.
kubectl 구성
# Name of GKE cluster from terraform.tfvars file
export GKE_CLUSTER=sample-game-gke
# get GKE credentials
gcloud container clusters get-credentials $GKE_CLUSTER --region us-central1
# Check that no errors occur
kubectl get serviceaccounts
명령어 결과
#export GKE_CLUSTER=sample-game-gke
# gcloud container clusters get-credentials $GKE_CLUSTER --region us-central1
Fetching cluster endpoint and auth data.
kubeconfig entry generated for sample-game-gke.
# kubectl get serviceaccounts
NAME SECRETS AGE
default 0 37m
item-app 0 35m
matchmaking-app 0 35m
profile-app 0 35m
tradepost-app 0 35m
요약
좋습니다. 비공개 네트워킹을 위한 VPC에서 Cloud Spanner 인스턴스, GKE Autopilot 클러스터를 모두 프로비저닝할 수 있었습니다.
또한 백엔드 서비스 및 워크로드를 위한 2개의 Cloud Deploy 파이프라인과 빌드된 이미지를 저장할 Artifact Registry 저장소가 생성되었습니다.
마지막으로, 백엔드 서비스가 Cloud Spanner를 사용할 수 있도록 워크로드 아이덴티티와 연동되도록 서비스 계정을 생성 및 구성했습니다.
또한 백엔드 서비스 및 워크로드를 배포한 후 Cloud Shell의 GKE 클러스터와 상호작용하도록 kubectl
가 구성되어 있습니다.
다음 단계
데이터베이스 스키마를 정의해야 서비스를 사용할 수 있습니다. 다음 단계에서 설정합니다.
4. 데이터베이스 스키마 만들기
개요
백엔드 서비스를 실행하려면 먼저 데이터베이스 스키마가 있는지 확인해야 합니다.
데모 저장소의 $DEMO_HOME/schema/migrations
디렉터리에 있는 파일을 보면 스키마를 정의하는 일련의 .sql
파일을 볼 수 있습니다. 이는 스키마 변경사항이 저장소 자체에서 추적되는 개발 주기를 모방하며 애플리케이션의 특정 기능에 연결될 수 있습니다.
이 샘플 환경의 경우 통합 도구는 Cloud Build를 사용해 스키마 이전을 적용하는 도구입니다.
Cloud Build
$DEMO_HOME/schema/cloudbuild.yaml
파일은 실행할 단계를 설명합니다.
serviceAccount: projects/${PROJECT_ID}/serviceAccounts/cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com
steps:
- name: gcr.io/cloud-builders/curl
id: fetch-wrench
args: ['-Lo', '/workspace/wrench.tar.gz', 'https://github.com/cloudspannerecosystem/wrench/releases/download/v1.4.1/wrench-1.4.1-linux-amd64.tar.gz' ]
- name: gcr.io/cloud-builders/gcloud
id: migrate-spanner-schema
entrypoint: sh
args:
- '-xe'
- '-c'
- |
tar -xzvf wrench.tar.gz
chmod +x /workspace/wrench
# Assumes only a single spanner instance and database. Fine for this demo in a dedicated project
export SPANNER_PROJECT_ID=${PROJECT_ID}
export SPANNER_INSTANCE_ID=$(gcloud spanner instances list | tail -n1 | awk '{print $1}')
export SPANNER_DATABASE_ID=$(gcloud spanner databases list --instance=$$SPANNER_INSTANCE_ID | tail -n1 | awk '{print $1}')
if [ -d ./migrations ]; then
/workspace/wrench migrate up --directory .
else
echo "[Error] Missing migrations directory"
fi
timeout: 600s
기본적으로 두 가지 단계가 있습니다.
- Cloud Build 작업공간에 렌치 다운로드
- 렌치 이전 실행
렌치가 쓰기 엔드포인트에 연결하려면 Spanner 프로젝트, 인스턴스, 데이터베이스 환경 변수가 필요합니다.
Cloud Build는 cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com
서비스 계정으로 실행되기 때문에 다음과 같이 변경할 수 있습니다.
serviceAccount: projects/${PROJECT_ID}/serviceAccounts/cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com
그리고 이 서비스 계정에는 Terraform에서 추가한 spanner.databaseUser
역할이 있어 서비스 계정이 DDL을 업데이트할 수 있습니다.
스키마 마이그레이션
$DEMO_HOME/schema/migrations
디렉터리에 있는 파일을 기반으로 5가지 이전 단계가 실행됩니다. 다음은 players
테이블과 색인을 만드는 000001.sql
파일의 예입니다.
CREATE TABLE players (
playerUUID STRING(36) NOT NULL,
player_name STRING(64) NOT NULL,
email STRING(MAX) NOT NULL,
password_hash BYTES(60) NOT NULL,
created TIMESTAMP,
updated TIMESTAMP,
stats JSON,
account_balance NUMERIC NOT NULL DEFAULT (0.00),
is_logged_in BOOL,
last_login TIMESTAMP,
valid_email BOOL,
current_game STRING(36)
) PRIMARY KEY (playerUUID);
CREATE UNIQUE INDEX PlayerAuthentication ON players(email) STORING(password_hash);
CREATE UNIQUE INDEX PlayerName ON players(player_name);
CREATE INDEX PlayerGame ON players(current_game);
스키마 마이그레이션 제출
스키마 이전을 수행하는 빌드를 제출하려면 schema
디렉터리로 전환하고 다음 gcloud 명령어를 실행합니다.
cd $DEMO_HOME/schema gcloud builds submit --config=cloudbuild.yaml
명령어 결과
Creating temporary tarball archive of 8 file(s) totalling 11.2 KiB before compression.
Uploading tarball of [.] to [gs://(project)_cloudbuild/source/(snip).tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/(project)/locations/global/builds/7defe982-(snip)].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds/7defe982-(snip)?project=(snip) ].
gcloud builds submit only displays logs from Cloud Storage. To view logs from Cloud Logging, run:
gcloud beta builds submit
ID: 7defe982-(snip)
CREATE_TIME: (created time)
DURATION: 3M11S
SOURCE: gs://(project)_cloudbuild/source/(snip).tgz
IMAGES: -
STATUS: SUCCESS
위의 출력에서 Created
Cloud Build 프로세스 링크를 확인할 수 있습니다. 이 버튼을 클릭하면 Cloud 콘솔의 빌드로 이동하여 빌드 진행 상황을 모니터링하고 진행 중인 작업을 확인할 수 있습니다.
요약
이 단계에서는 Cloud Build를 사용하여 5개의 서로 다른 DDL 작업을 적용한 초기 스키마 마이그레이션을 제출했습니다. 이러한 작업은 데이터베이스 스키마 변경이 필요한 특성이 추가된 시점을 나타냅니다.
일반적인 개발 시나리오에서는 서비스 중단을 피하기 위해 스키마 변경을 현재 애플리케이션과 하위 호환되도록 하는 것이 좋습니다.
이전 버전과 호환되지 않는 변경사항의 경우 중단이 발생하지 않도록 애플리케이션 및 스키마에 변경사항을 단계별로 배포하는 것이 좋습니다.
다음 단계
스키마가 준비되면 다음 단계는 백엔드 서비스를 배포하는 것입니다.
5. 백엔드 서비스 배포
개요
이 Codelab의 백엔드 서비스는 네 가지 서비스를 나타내는 golang REST API입니다.
- 프로필: 플레이어가 샘플 '게임'에 가입하고 인증할 수 있는 기능을 제공합니다.
- 랜덤 대결: 플레이어 데이터와 상호작용하여 랜덤 대결 기능을 지원하고, 생성된 게임에 관한 정보를 추적하고, 게임이 종료될 때 플레이어 통계를 업데이트합니다.
- 아이템: 플레이어가 게임을 플레이하는 동안 게임 아이템과 돈을 획득할 수 있게 해줍니다.
- Tradepost: 플레이어가 트레이드포스트에서 아이템을 사고팔 수 있습니다.
이러한 서비스에 대한 자세한 내용은 Cloud Spanner 게임 개발 시작하기 Codelab을 참조하세요. 여기서는 이러한 서비스를 GKE Autopilot 클러스터에서 실행하려고 합니다.
이러한 서비스는 Spanner 데이터를 수정할 수 있어야 합니다. 이를 위해 각 서비스에는 ‘databaseUser’ 권한을 부여하는 서비스 계정이 생성되어 있습니다. 역할을 수행합니다
워크로드 아이덴티티를 사용하면 Kubernetes 서비스 계정이 Google Cloud 서비스 계정을 사용하여 Google Cloud 서비스 계정에 연결할 수 있습니다.
- 서비스의 Google Cloud 서비스 계정 (
GSA
) 리소스 만들기 - 해당 서비스 계정에 databaseUser 역할을 할당합니다.
- 해당 서비스 계정에 workloadIdentityUser 역할을 할당합니다.
- GSA를 참조하는 Kubernetes 서비스 계정 (
KSA
) 만들기
대략적인 다이어그램은 다음과 같습니다.
Terraform이 서비스 계정과 Kubernetes 서비스 계정을 생성해 주었습니다. 그리고 kubectl
를 사용하여 Kubernetes 서비스 계정을 확인할 수 있습니다.
# kubectl get serviceaccounts
NAME SECRETS AGE
default 0 37m
item-app 0 35m
matchmaking-app 0 35m
profile-app 0 35m
tradepost-app 0 35m
빌드 작동 방식은 다음과 같습니다.
- Terraform은 다음과 같은
$DEMO_HOME/backend_services/cloudbuild.yaml
파일을 생성했습니다.
serviceAccount: projects/${PROJECT_ID}/serviceAccounts/cloudbuild-cicd@${PROJECT_ID}.iam.gserviceaccount.com
steps:
#
# Building of images
#
- name: gcr.io/cloud-builders/docker
id: profile
args: ["build", ".", "-t", "${_PROFILE_IMAGE}"]
dir: profile
waitFor: ['-']
- name: gcr.io/cloud-builders/docker
id: matchmaking
args: ["build", ".", "-t", "${_MATCHMAKING_IMAGE}"]
dir: matchmaking
waitFor: ['-']
- name: gcr.io/cloud-builders/docker
id: item
args: ["build", ".", "-t", "${_ITEM_IMAGE}"]
dir: item
waitFor: ['-']
- name: gcr.io/cloud-builders/docker
id: tradepost
args: ["build", ".", "-t", "${_TRADEPOST_IMAGE}"]
dir: tradepost
waitFor: ['-']
#
# Deployment
#
- name: gcr.io/google.com/cloudsdktool/cloud-sdk
id: cloud-deploy-release
entrypoint: gcloud
args:
[
"deploy", "releases", "create", "${_REL_NAME}",
"--delivery-pipeline", "sample-game-services",
"--skaffold-file", "skaffold.yaml",
"--skaffold-version", "1.39",
"--images", "profile=${_PROFILE_IMAGE},matchmaking=${_MATCHMAKING_IMAGE},item=${_ITEM_IMAGE},tradepost=${_TRADEPOST_IMAGE}",
"--region", "us-central1"
]
artifacts:
images:
- ${_REGISTRY}/profile
- ${_REGISTRY}/matchmaking
- ${_REGISTRY}/item
- ${_REGISTRY}/tradepost
substitutions:
_PROFILE_IMAGE: ${_REGISTRY}/profile:${BUILD_ID}
_MATCHMAKING_IMAGE: ${_REGISTRY}/matchmaking:${BUILD_ID}
_ITEM_IMAGE: ${_REGISTRY}/item:${BUILD_ID}
_TRADEPOST_IMAGE: ${_REGISTRY}/tradepost:${BUILD_ID}
_REGISTRY: us-docker.pkg.dev/${PROJECT_ID}/spanner-game-images
_REL_NAME: rel-${BUILD_ID:0:8}
options:
dynamic_substitutions: true
machineType: E2_HIGHCPU_8
logging: CLOUD_LOGGING_ONLY
- Cloud Build 명령어는 이 파일을 읽고 나열된 단계를 따릅니다. 먼저 서비스 이미지를 빌드합니다. 그런 다음
gcloud deploy create
명령어를 실행합니다. 각 배포 파일의 위치를 정의하는$DEMO_HOME/backend_services/skaffold.yaml
파일을 읽습니다.
apiVersion: skaffold/v2beta29
kind: Config
deploy:
kubectl:
manifests:
- spanner_config.yaml
- profile/deployment.yaml
- matchmaking/deployment.yaml
- item/deployment.yaml
- tradepost/deployment.yaml
- Cloud Deploy는 각 서비스의
deployment.yaml
파일에 대한 정의를 따릅니다. 서비스의 배포 파일에는 서비스를 만들기 위한 정보가 포함되어 있습니다. 이 경우에는 포트 80에서 실행되는 clusterIP입니다.
" ClusterIP" 유형은 백엔드 서비스 포드에 외부 IP를 허용하지 않으므로 내부 GKE 네트워크에 연결할 수 있는 항목만 백엔드 서비스에 액세스할 수 있습니다. 이러한 서비스는 플레이어가 Spanner 데이터에 액세스하고 수정하므로 직접 액세스할 수 있어서는 안 됩니다.
apiVersion: v1
kind: Service
metadata:
name: profile
spec:
type: ClusterIP
selector:
app: profile
ports:
- port: 80
targetPort: 80
Cloud Deploy는 Kubernetes 서비스를 만드는 것 외에 Kubernetes 배포도 만듭니다. profile
서비스의 배포 섹션을 살펴보겠습니다.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: profile
spec:
replicas: 2 # EDIT: Number of instances of deployment
selector:
matchLabels:
app: profile
template:
metadata:
labels:
app: profile
spec:
serviceAccountName: profile-app
containers:
- name: profile-service
image: profile
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: spanner-config
env:
- name: SERVICE_HOST
value: "0.0.0.0"
- name: SERVICE_PORT
value: "80"
resources:
requests:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "100Mi"
limits:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "100Mi"
상단 부분에서는 서비스에 대한 일부 메타데이터를 제공합니다. 여기서 가장 중요한 부분은 이 배포에서 생성될 복제본 수를 정의하는 것입니다.
replicas: 2 # EDIT: Number of instances of deployment
다음으로, 앱을 실행해야 하는 서비스 계정과 사용해야 하는 이미지를 확인합니다. 이는 Terraform에서 생성된 Kubernetes 서비스 계정 및 Cloud Build 단계 중에 생성된 이미지와 일치합니다.
spec:
serviceAccountName: profile-app
containers:
- name: profile-service
image: profile
그런 다음 네트워킹 및 환경 변수에 대한 몇 가지 정보를 지정합니다.
spanner_config
는 애플리케이션이 Spanner에 연결하는 데 필요한 프로젝트, 인스턴스, 데이터베이스 정보를 지정하는 Kubernetes ConfigMap입니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: spanner-config
data:
SPANNER_PROJECT_ID: ${project_id}
SPANNER_INSTANCE_ID: ${instance_id}
SPANNER_DATABASE_ID: ${database_id}
ports:
- containerPort: 80
envFrom:
- configMapRef:
name: spanner-config
env:
- name: SERVICE_HOST
value: "0.0.0.0"
- name: SERVICE_PORT
value: "80"
SERVICE_HOST
및 SERVICE_PORT
는 서비스에서 바인딩 위치를 파악하는 데 필요한 추가 환경 변수입니다.
마지막 섹션에서는 이 배포의 각 복제본에 허용할 리소스 수를 GKE에 알려줍니다. 이는 GKE Autopilot이 클러스터를 확장하기 위해 필요에 따라 사용하는 데도 사용됩니다.
resources:
requests:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "100Mi"
limits:
cpu: "1"
memory: "1Gi"
ephemeral-storage: "100Mi"
이 정보를 사용하여 백엔드 서비스를 배포하겠습니다.
백엔드 서비스 배포
앞서 언급했듯이 백엔드 서비스를 배포할 때는 Cloud Build가 사용됩니다. 스키마 이전과 마찬가지로 gcloud 명령줄을 사용하여 빌드 요청을 제출할 수 있습니다.
cd $DEMO_HOME/backend_services gcloud builds submit --config=cloudbuild.yaml
명령어 결과
Creating temporary tarball archive of 66 file(s) totalling 864.6 KiB before compression.
Uploading tarball of [.] to [gs://(project)_cloudbuild/source/(snip).tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/(project)/locations/global/builds/30207dd1-(snip)].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds/30207dd1-(snip)?project=(snip) ].
gcloud builds submit only displays logs from Cloud Storage. To view logs from Cloud Logging, run:
gcloud beta builds submit
ID: 30207dd1-(snip)
CREATE_TIME: (created time)
DURATION: 3M17S
SOURCE: gs://(project)_cloudbuild/source/(snip).tgz
IMAGES: us-docker.pkg.dev/(project)/spanner-game-images/profile:30207dd1-(snip) (+3 more)
STATUS: SUCCESS
schema migration
단계의 출력과 달리 이 빌드의 출력은 생성된 이미지가 있음을 나타냅니다. 파일은 Artifact Registry 저장소에 저장됩니다.
gcloud build
단계의 출력에 Cloud 콘솔 링크가 포함됩니다. 한번 살펴보세요.
Cloud Build에서 성공 알림을 받으면 Cloud Deploy, sample-game-services
파이프라인으로 이동하여 배포 진행 상황을 모니터링합니다.
서비스가 배포되면 kubectl
에서 포드를 확인할 수 있습니다. 상태:
kubectl get pods
명령어 결과
NAME READY STATUS RESTARTS AGE
item-6b9d5f678c-4tbk2 1/1 Running 0 83m
matchmaking-5bcf799b76-lg8zf 1/1 Running 0 80m
profile-565bbf4c65-kphdl 1/1 Running 0 83m
profile-565bbf4c65-xw74j 1/1 Running 0 83m
tradepost-68b87ccd44-gw55r 1/1 Running 0 79m
그런 다음 서비스에서 ClusterIP
가 작동하는지 확인합니다.
kubectl get services
명령어 결과
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
item ClusterIP 10.172.XXX.XXX <none> 80/TCP 84m
kubernetes ClusterIP 10.172.XXX.XXX <none> 443/TCP 137m
matchmaking ClusterIP 10.172.XXX.XXX <none> 80/TCP 84m
profile ClusterIP 10.172.XXX.XXX <none> 80/TCP 84m
tradepost ClusterIP 10.172.XXX.XXX <none> 80/TCP 84m
Cloud 콘솔에서 GKE UI로 이동하여 Workloads
, Services
, ConfigMaps
를 확인할 수도 있습니다.
워크로드
서비스
ConfigMaps
요약
이 단계에서는 GKE Autopilot에 4개의 백엔드 서비스를 배포했습니다. Cloud Build 단계를 실행하고 Cloud Deploy 및 Cloud 콘솔의 Kubernetes에서 진행 상황을 확인할 수 있었습니다.
또한 이러한 서비스가 워크로드 아이덴티티를 활용하여 Spanner 데이터베이스에서 데이터를 읽고 쓸 수 있는 적절한 권한이 있는 서비스 계정을 가장하는 방법도 배웠습니다.
다음 단계
다음 섹션에서는 워크로드를 배포합니다.
6. 워크로드 배포
개요
이제 백엔드 서비스가 클러스터에서 실행되므로 워크로드를 배포합니다.
워크로드는 외부에서 액세스할 수 있으며 이 Codelab에서는 각 백엔드 서비스별로 워크로드가 하나씩 있습니다.
이러한 워크로드는 샘플 서비스에서 예상되는 실제 액세스 패턴을 모방한 Locust 기반의 부하 생성 스크립트입니다.
Cloud Build 프로세스에는 다음과 같은 파일이 있습니다.
$DEMO_HOME/workloads/cloudbuild.yaml
(Terraform으로 생성됨)$DEMO_HOME/workloads/skaffold.yaml
- 각 워크로드의
deployment.yaml
파일
워크로드 deployment.yaml
파일은 백엔드 서비스 배포 파일과 약간 다르게 보입니다.
다음은 matchmaking-workload
의 예입니다.
apiVersion: v1
kind: Service
metadata:
name: matchmaking-workload
spec:
type: LoadBalancer
selector:
app: matchmaking-workload
ports:
- port: 8089
targetPort: 8089
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: matchmaking-workload
spec:
replicas: 1 # EDIT: Number of instances of deployment
selector:
matchLabels:
app: matchmaking-workload
template:
metadata:
labels:
app: matchmaking-workload
spec:
serviceAccountName: default
containers:
- name: matchmaking-workload
image: matchmaking-workload
ports:
- containerPort: 8089
resources:
requests:
cpu: "500m"
memory: "512Mi"
ephemeral-storage: "100Mi"
limits:
cpu: "500m"
memory: "512Mi"
ephemeral-storage: "100Mi"
파일 맨 위 부분은 서비스를 정의합니다. 여기에서는 LoadBalancer
가 생성되고 워크로드가 포트 8089
에서 실행됩니다.
LoadBalancer는 워크로드에 연결하는 데 사용할 수 있는 외부 IP를 제공합니다.
apiVersion: v1
kind: Service
metadata:
name: matchmaking-workload
spec:
type: LoadBalancer
selector:
app: matchmaking-workload
ports:
- port: 8089
targetPort: 8089
배포 섹션의 맨 위에는 워크로드에 대한 메타데이터가 있습니다. 이 경우 하나의 복제본만 배포됩니다.
replicas: 1
하지만 컨테이너 사양은 다릅니다. 우선 default
Kubernetes 서비스 계정을 사용하고 있습니다. GKE 클러스터에서 실행되는 백엔드 서비스를 제외하고 워크로드를 Google Cloud 리소스에 연결할 필요가 없으므로 이 계정에는 특별한 권한이 없습니다.
다른 차이점은 이러한 워크로드에는 필요한 환경 변수가 없다는 것입니다. 그 결과 배포 사양이 더 짧아집니다.
spec:
serviceAccountName: default
containers:
- name: matchmaking-workload
image: matchmaking-workload
ports:
- containerPort: 8089
리소스 설정은 백엔드 서비스와 유사합니다. 이는 GKE Autopilot이 클러스터에서 실행되는 모든 포드의 요청을 충족하는 데 필요한 리소스 수를 파악하는 방법입니다.
워크로드를 배포해 보세요.
워크로드 배포
이전과 마찬가지로 gcloud 명령줄을 사용하여 빌드 요청을 제출할 수 있습니다.
cd $DEMO_HOME/workloads gcloud builds submit --config=cloudbuild.yaml
명령어 결과
Creating temporary tarball archive of 18 file(s) totalling 26.2 KiB before compression.
Some files were not included in the source upload.
Check the gcloud log [/tmp/tmp.4Z9EqdPo6d/logs/(snip).log] to see which files and the contents of the
default gcloudignore file used (see `$ gcloud topic gcloudignore` to learn
more).
Uploading tarball of [.] to [gs://(project)_cloudbuild/source/(snip).tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/(project)/locations/global/builds/(snip)].
Logs are available at [ https://console.cloud.google.com/cloud-build/builds/0daf20f6-(snip)?project=(snip) ].
gcloud builds submit only displays logs from Cloud Storage. To view logs from Cloud Logging, run:
gcloud beta builds submit
ID: 0daf20f6-(snip)
CREATE_TIME: (created_time)
DURATION: 1M41S
SOURCE: gs://(project)_cloudbuild/source/(snip).tgz
IMAGES: us-docker.pkg.dev/(project)/spanner-game-images/profile-workload:0daf20f6-(snip) (+4 more)
STATUS: SUCCESS
Cloud 콘솔에서 Cloud Build 로그 및 Cloud Deploy 파이프라인을 확인하여 상태를 확인해야 합니다. 워크로드의 경우 Cloud Deploy 파이프라인은 sample-game-workloads
입니다.
배포가 완료되면 Cloud Shell에서 kubectl
를 사용하여 상태를 확인합니다.
kubectl get pods
명령어 결과
NAME READY STATUS RESTARTS AGE
game-workload-7ff44cb657-pxxq2 1/1 Running 0 12m
item-6b9d5f678c-cr29w 1/1 Running 0 9m6s
item-generator-7bb4f57cf8-5r85b 1/1 Running 0 12m
matchmaking-5bcf799b76-lg8zf 1/1 Running 0 117m
matchmaking-workload-76df69dbdf-jds9z 1/1 Running 0 12m
profile-565bbf4c65-kphdl 1/1 Running 0 121m
profile-565bbf4c65-xw74j 1/1 Running 0 121m
profile-workload-76d6db675b-kzwng 1/1 Running 0 12m
tradepost-68b87ccd44-gw55r 1/1 Running 0 116m
tradepost-workload-56c55445b5-b5822 1/1 Running 0 12m
그런 다음 워크로드 서비스에서 LoadBalancer
의 작동 방식을 확인합니다.
kubectl get services
명령어 결과
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
game-workload LoadBalancer *snip* 35.XX.XX.XX 8089:32483/TCP 12m
item ClusterIP *snip* <none> 80/TCP 121m
item-generator LoadBalancer *snip* 34.XX.XX.XX 8089:32581/TCP 12m
kubernetes ClusterIP *snip* <none> 443/TCP 174m
matchmaking ClusterIP *snip* <none> 80/TCP 121m
matchmaking-workload LoadBalancer *snip* 34.XX.XX.XX 8089:31735/TCP 12m
profile ClusterIP *snip* <none> 80/TCP 121m
profile-workload LoadBalancer *snip* 34.XX.XX.XX 8089:32532/TCP 12m
tradepost ClusterIP *snip* <none> 80/TCP 121m
tradepost-workload LoadBalancer *snip* 34.XX.XX.XX 8089:30002/TCP 12m
요약
이제 GKE 클러스터에 워크로드를 배포했습니다. 이러한 워크로드에는 추가 IAM 권한이 필요하지 않으며 LoadBalancer 서비스를 사용하여 포트 8089에서 외부에서 액세스할 수 있습니다.
다음 단계
백엔드 서비스와 워크로드가 실행 중이므로 이제 'play'합니다. 있습니다.
7. 게임 시작
개요
샘플 '게임'의 백엔드 서비스 '플레이어'를 생성할 수 있는 수단도 있습니다. 해당 서비스와 상호작용합니다
각 워크로드는 Locust를 사용하여 Google 서비스 API에 대한 실제 부하를 시뮬레이션합니다. 이 단계에서는 몇 가지 워크로드를 실행하여 GKE 클러스터와 Spanner에 부하를 생성하고 Spanner에 데이터를 저장합니다.
다음은 각 워크로드에 대한 설명입니다.
item-generator
워크로드는 플레이어가 '플레이' 과정에서 획득할 수 있는 game_items 목록을 생성하는 빠른 워크로드입니다. 있습니다.profile-workload
는 플레이어의 가입 및 로그인을 시뮬레이션합니다.matchmaking-workload
는 게임에 할당되기 위해 대기열에 등록하는 플레이어를 시뮬레이션합니다.game-workload
는 플레이어가 게임을 플레이하면서 game_items와 돈을 획득하는 것을 시뮬레이션합니다.tradepost-workload
는 플레이어가 거래 지점에서 아이템을 판매하고 구매할 수 있는 기능을 시뮬레이션합니다.
이 Codelab에서는 특히 item-generator
및 profile-workload
실행을 중점적으로 살펴봅니다.
항목 생성기 실행
item-generator
는 item
백엔드 서비스 엔드포인트를 사용하여 game_items
를 Spanner에 추가합니다. 이러한 항목은 game-workload
및 tradepost-workload
가 올바르게 작동하는 데 필요합니다.
첫 번째 단계는 item-generator
서비스의 외부 IP를 가져오는 것입니다. Cloud Shell에서 다음을 실행합니다.
# The external IP is the 4th column of the output
kubectl get services | grep item-generator | awk '{print $4}'
명령어 결과
{ITEMGENERATOR_EXTERNAL_IP}
이제 새 브라우저 탭을 열고 http://{ITEMGENERATOR_EXTERNAL_IP}:8089
을 가리킵니다. 다음과 같은 페이지가 표시됩니다.
users
와 spawn
를 기본값 1로 둡니다. host
, http://item
를 입력합니다. 고급 옵션을 클릭하고 실행 시간으로 10s
를 입력합니다.
구성은 다음과 같이 표시됩니다.
'모으기 시작'을 클릭하세요.
POST /items
엔드포인트에서 실행된 요청에 대한 통계가 표시되기 시작합니다. 10초 후에 로드가 중지됩니다.
Charts
을(를) 클릭하면 이러한 요청의 성능에 관한 그래프가 표시됩니다.
이제 데이터가 Spanner 데이터베이스에 입력되었는지 확인해 보겠습니다.
햄버거 메뉴를 클릭하고 'Spanner'로 이동합니다. 이 페이지에서 sample-instance
및 sample-database
로 이동합니다. 그런 다음 ‘Query
’을(를) 클릭하세요.
game_items
: 수를 선택합니다.
SELECT COUNT(*) FROM game_items;
하단에 결과가 표시됩니다.
많은 game_items
시드가 필요하지 않습니다. 하지만 이제 플레이어가 획득할 수 있습니다.
Profile-workload 실행
game_items
시드를 설정했다면 다음 단계는 플레이어가 게임을 플레이할 수 있도록 등록하는 것입니다.
profile-workload
는 Locust를 사용하여 플레이어가 계정 생성, 로그인, 프로필 정보 검색, 로그아웃을 시뮬레이션합니다. 이 모든 기능은 프로덕션과 유사한 일반적인 워크로드에서 profile
백엔드 서비스의 엔드포인트를 테스트합니다.
이를 실행하려면 profile-workload
외부 IP를 가져옵니다.
# The external IP is the 4th column of the output
kubectl get services | grep profile-workload | awk '{print $4}'
명령어 결과
{PROFILEWORKLOAD_EXTERNAL_IP}
이제 새 브라우저 탭을 열고 http://{PROFILEWORKLOAD_EXTERNAL_IP}:8089
을 가리킵니다. 이전 페이지와 유사한 Locust 페이지가 표시됩니다.
여기서는 호스트에 http://profile
를 사용합니다. 고급 옵션에는 런타임을 지정하지 않습니다. 또한 users
를 4로 지정하면 한 번에 사용자 요청 4개를 시뮬레이션합니다.
profile-workload
테스트는 다음과 같습니다.
'모으기 시작'을 클릭하세요.
이전과 마찬가지로 다양한 profile
REST 엔드포인트의 통계가 표시되기 시작합니다. 클릭하여 차트로 이동하면 모든 항목의 실적을 확인할 수 있습니다.
요약
이 단계에서는 game_items
를 생성한 후 Cloud 콘솔에서 Spanner 쿼리 UI를 사용하여 game_items
테이블을 쿼리했습니다.
또한 플레이어가 게임에 가입할 수 있도록 허용하여 Locust가 백엔드 서비스에 대해 프로덕션과 유사한 워크로드를 생성하는 방법을 확인했습니다.
다음 단계
워크로드를 실행한 후에는 GKE 클러스터 및 Spanner 인스턴스가 어떻게 작동하는지 확인하는 것이 좋습니다.
8. GKE 및 Spanner 사용량 검토
프로필 서비스가 실행 중인 상태에서 GKE Autopilot 클러스터와 Cloud Spanner가 어떻게 작동하는지 살펴볼 차례입니다.
GKE 클러스터 확인
Kubernetes 클러스터로 이동합니다. 워크로드 및 서비스를 배포했으므로 이제 클러스터에 총 vCPU 및 메모리에 대한 일부 세부정보가 추가되었습니다. 클러스터에 워크로드가 없을 때 이 정보를 사용할 수 없었습니다.
이제 sample-game-gke
클러스터를 클릭하고 관측 가능성 탭으로 전환합니다.
워크로드 및 백엔드 서비스가 default
에서 실행되므로 default
Kubernetes 네임스페이스가 CPU 사용률의 kube-system
네임스페이스를 초과했을 것입니다. 시작되지 않으면 profile workload
가 여전히 실행 중인지 확인하고 차트가 업데이트될 때까지 몇 분 정도 기다립니다.
리소스를 가장 많이 사용하는 워크로드를 확인하려면 Workloads
대시보드로 이동하세요.
각 워크로드를 개별적으로 탐색하는 대신 대시보드의 관측 가능성 탭으로 바로 이동합니다. profile
및 profile-workload
CPU가 증가한 것을 확인할 수 있습니다.
이제 Cloud Spanner를 확인해 보겠습니다.
Cloud Spanner 인스턴스 확인
Cloud Spanner의 성능을 확인하려면 Spanner로 이동하여 sample-instance
인스턴스와 sample-game
데이터베이스를 클릭합니다.
그러면 왼쪽 메뉴에 시스템 통계 탭이 표시됩니다.
여기에는 CPU utilization
, transaction latency and locking
, query throughput
등 Spanner 인스턴스의 일반적인 성능을 이해하는 데 도움이 되는 여러 차트가 있습니다.
시스템 통계 외에도 관측 가능성 섹션의 다른 링크를 확인하여 쿼리 워크로드에 대한 자세한 정보를 확인할 수 있습니다.
- 쿼리 통계는 Spanner의 리소스를 활용하는 상위 N개 쿼리를 식별하는 데 도움이 됩니다.
- 트랜잭션 및 잠금 통계는 지연 시간이 긴 트랜잭션을 식별하는 데 도움이 됩니다.
- Key Visualizer는 액세스 패턴을 시각화하고 데이터의 핫스팟을 추적하는 데 도움이 됩니다.
요약
이 단계에서는 GKE Autopilot과 Spanner의 몇 가지 기본 성능 측정항목을 확인하는 방법을 알아봤습니다.
예를 들어 프로필 워크로드를 실행 중인 상태에서 players 테이블을 쿼리하여 여기에 저장되는 데이터에 대한 추가 정보를 가져옵니다.
다음 단계
이제 정리할 시간입니다.
9. 삭제
정리하기 전에 다루지 않은 다른 워크로드를 살펴보세요. 특히 matchmaking-workload
, game-workload
, tradepost-workload
입니다.
'재생'을 마치면 플레이그라운드를 정리할 수 있습니다. 다행히 이 작업은 매우 간단합니다.
먼저 profile-workload
이 브라우저에서 여전히 실행 중인 경우 다음과 같이 이동하여 중지합니다.
테스트한 각 워크로드에 대해 동일한 작업을 수행합니다.
그런 다음 Cloud Shell에서 인프라 폴더로 이동합니다. terraform을 사용하여 인프라를 destroy
합니다.
cd $DEMO_HOME/infrastructure
terraform destroy
# type 'yes' when asked
명령어 결과
Plan: 0 to add, 0 to change, 46 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
*snip*
Destroy complete! Resources: 46 destroyed.
Cloud 콘솔에서 Spanner
, Kubernetes Cluster
, Artifact Registry
, Cloud Deploy
, IAM
로 이동하여 모든 리소스가 삭제되었는지 확인합니다.
10. 축하합니다.
수고하셨습니다. GKE Autopilot에 샘플 golang 애플리케이션을 배포하고 워크로드 아이덴티티를 사용하여 Cloud Spanner에 애플리케이션을 연결했습니다.
또한 Terraform을 사용하여 반복 가능한 방식으로 이 인프라를 쉽게 설정하고 제거할 수 있었습니다.
이 Codelab에서 상호작용한 Google Cloud 서비스에 대한 자세한 내용을 확인할 수 있습니다.
다음 단계
지금까지 GKE Autopilot과 Cloud Spanner가 함께 작동하는 방식에 대해 기본적인 내용을 알아봤습니다. 다음 단계로 넘어가 자체 애플리케이션을 빌드해 이러한 서비스를 사용해 보세요.