GKE Autopilot 및 Spanner를 사용하여 앱 배포


이 튜토리얼에서는 컨테이너화된 웹 애플리케이션을 Google Kubernetes Engine(GKE) Autopilot 클러스터에 배포하고 백엔드에서 Google Spanner 데이터베이스를 사용하여 데이터를 저장하는 방법을 설명합니다. 샘플 애플리케이션은 게임 플레이어의 테이블을 관리합니다. 앱의 그래픽 사용자 인터페이스(GUI)를 통해 플레이어를 추가하고 삭제할 수 있습니다.

Spanner는 성능 및 고가용성을 희생하지 않고도 ACID 트랜잭션 및 SQL 시맨틱스를 제공하는 수평 확장이 가능하고, 전역으로 분산되는 완전 관리형의 관계형 데이터베이스 서비스입니다.

이 튜토리얼에서는 사용자가 Kubernetes를 기본적으로 이해하고 있다고 가정합니다.

GKE와 Spanner를 사용해야 하는 이유

개발자로서 애플리케이션에 필요한 스토리지 및 컴퓨팅 리소스 양을 확인하거나 수요가 변동하는 기간 동안 RAM 및 CPU 소비를 예측하거나 최대 부하 시 애플리케이션 오류를 걱정하는 데 시간을 낭비하고 싶지 않을 것입니다.

GKE Autopilot을 완전 관리형 Kubernetes 서비스로, Spanner를 완전 관리형 데이터베이스 서비스로 사용하면 리소스 구성 및 관리를 간소화하는 안정적인 인프라에서 앱을 더 빠르게 개발하고 배포할 수 있습니다. GKE Autopilot은 런타임의 요구사항에 따라 클러스터에서 노드를 추가하거나 삭제하여 앱 호스팅을 위한 인프라 구성 및 확장을 처리합니다. 마찬가지로 Spanner는 스토리지 또는 컴퓨팅 요구사항이 변경되면 최소한의 수동 개입으로 동적으로 수평 확장할 수 있습니다.

예를 들어 입소문을 탈 것으로 예상되는 블록버스터 게임을 출시한다고 가정하면 출시 주간에 많은 웹 트래픽이 유입됩니다. Spanner는 GKE Autopilot으로 최대 애플리케이션 가용성을 유지하면서 컴퓨팅 리소스를 즉시 늘리거나 줄이거나 재할당할 수 있는 기능을 제공하여 이러한 갑작스러운 처리량을 수용하는 데 도움이 될 수 있습니다.

목표

이 튜토리얼에서는 다음을 수행하는 방법을 알아봅니다.

  • 플레이어 레지스트리를 저장하는 Spanner 데이터베이스를 만듭니다.

  • hello-app-cloud-spanner라는 샘플 웹 앱을 그래픽 사용자 인터페이스로 배포합니다.

다음 표에서는 사용자가 만들거나 사용하는 Google Cloud 리소스, 식별된 변수, 이 튜토리얼의 목적에 따라 정의된 값을 설명합니다.

리소스 변수
Google Cloud 프로젝트 ID PROJECT_ID

프로젝트를 만들 때 생성된 프로젝트 ID입니다.

예: my-gcp-project

컴퓨팅 리전 COMPUTE_REGION

Spanner 인스턴스와 GKE 클러스터를 만들 Compute Engine 리전입니다. 고객의 지리적 위치와 가장 가까운 리전을 선택하는 것이 좋지만 이 튜토리얼에서는 us-west1을 사용합니다.

Spanner 인스턴스 - hello-instance
Spanner 데이터베이스 - hello-database
GKE Autopilot 클러스터 CLUSTER_NAME hello-cluster
Kubernetes 네임스페이스 NAMESPACE hello-namespace
Kubernetes 서비스 계정 KSA_NAME ksa-helloapp
IAM 서비스 계정 GSA_NAME gsa-helloapp
IAM 서비스 계정의 프로젝트 ID GSA_PROJECT 사용자의 Google Cloud PROJECT_ID

이 튜토리얼에서는 새 리소스를 만들어 샘플 앱을 배포한 후에 쉽고 간편하게 삭제하는 것을 권장합니다. 하지만 기존 네임스페이스, IAM 서비스 계정, Kubernetes 서비스 계정이 있으면 해당 계정을 사용하면 됩니다.

비용

이 문서에서는 비용이 청구될 수 있는 다음과 같은 Google Cloud 구성요소를 사용합니다.

프로젝트 사용량을 기준으로 예상 비용을 산출하려면 가격 계산기를 사용하세요. Google Cloud를 처음 사용하는 사용자는 무료 체험판을 사용할 수 있습니다.

이 문서에 설명된 태스크를 완료했으면 만든 리소스를 삭제하여 청구가 계속되는 것을 방지할 수 있습니다. 자세한 내용은 삭제를 참조하세요.

시작하기 전에

다음 기본 요건을 완료해야 합니다.

프로젝트 선택 또는 생성

기존 프로젝트를 사용하거나 이 튜토리얼용으로 새 프로젝트를 만들 수 있습니다.

  1. Google Cloud 계정에 로그인합니다. Google Cloud를 처음 사용하는 경우 계정을 만들고 Google 제품의 실제 성능을 평가해 보세요. 신규 고객에게는 워크로드를 실행, 테스트, 배포하는 데 사용할 수 있는 $300의 무료 크레딧이 제공됩니다.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Google Cloud 프로젝트에 결제가 사용 설정되어 있는지 확인합니다.

API 사용 설정

API Artifact Registry, Compute Engine, GKE, and IAM Service Account Credentials 사용 설정

API 사용 설정

Cloud Shell 설정

이 튜토리얼에서는 Cloud Shell을 사용하여 gcloudkubectl 명령어를 실행합니다. Cloud Shell은 Google Cloud에서 호스팅되는 리소스를 관리하는 데 사용되는 셸 환경입니다. Google Cloud CLIkubectl 명령줄 도구가 사전 설치되어 있습니다.

Google Cloud 콘솔에서 Cloud Shell을 활성화합니다.

Cloud Shell 활성화

콘솔 하단의 프레임에서 Cloud Shell 세션이 열립니다.

이 튜토리얼에서 명령어를 실행하기 전에 기본 프로젝트가 샘플 앱을 배포할 프로젝트 ID로 설정되어 있는지 확인합니다. 아직 설정되지 않았으면 Cloud Shell에서 다음 명령어를 실행합니다.

gcloud config set project PROJECT_ID

PROJECT_ID프로젝트 ID로 바꿉니다.

IAM 역할 부여

Google Cloud 계정에 이 튜토리얼에 필요한 IAM 역할이 있는지 확인합니다.

Google 계정에 역할을 부여합니다. 다음 각 IAM 역할에 대해 다음 명령어를 한 번씩 실행합니다. roles/iam.serviceAccountAdmin, roles/serviceusage.serviceUsageConsumer, roles/iam.serviceAccountUser, roles/iam.securityAdmin, roles/spanner.admin, roles/container.admin

$ gcloud projects add-iam-policy-binding PROJECT_ID --member="user:EMAIL_ADDRESS" --role=ROLE
  • PROJECT_ID를 프로젝트 ID로 바꿉니다.
  • EMAIL_ADDRESS를 이메일 주소로 바꿉니다.
  • ROLE을 각 개별 역할로 바꿉니다.

Spanner 구성

Spanner를 구성하려면 Spanner 인스턴스와 Spanner 데이터베이스를 만들어야 합니다.

Spanner 인스턴스 만들기

Spanner 인스턴스는 해당 인스턴스에서 만든 Spanner 데이터베이스에서 사용하는 리소스를 할당한 것입니다.

리전 구성, 100 처리 단위의 컴퓨팅 용량으로 hello-instance라는 Spanner 인스턴스를 만듭니다.

gcloud spanner instances create hello-instance \
    --config=regional-COMPUTE_REGION \
    --description="Spanner sample instance" \
    --processing-units=100

이 튜토리얼의 COMPUTE_REGIONus-west1로 바꿉니다.

Spanner 데이터베이스 만들기

Spanner 데이터베이스에는 테이블, 뷰, 색인이 포함됩니다. 데이터베이스는 구성(리전 또는 멀티 리전), 사용 가능한 컴퓨팅 용량, 스토리지와 같은 상위 인스턴스의 속성을 상속합니다.

GoogleSQL 언어를 사용하여 Players라는 테이블로 hello-database라는 Spanner 데이터베이스를 만듭니다. Cloud Shell에서 다음 쿼리를 실행합니다.

gcloud spanner databases create hello-database \
    --instance=hello-instance \
    --database-dialect=GOOGLE_STANDARD_SQL \
    --ddl="CREATE TABLE Players (
        PlayerUuid STRING(36) NOT NULL,
        FirstName STRING(1024),
        LastName STRING(1024),
        BirthDate DATE) PRIMARY KEY(PlayerUuid)"

GKE Autopilot 클러스터 만들기

Spanner를 구성한 후 Autopilot 클러스터를 만들고 GKE용 워크로드 아이덴티티 제휴를 사용하여 안전하고 관리 가능한 방식으로 데이터베이스에 액세스합니다.

hello-cluster라는 Autopilot 클러스터를 만듭니다. Autopilot 클러스터에는 기본적으로 GKE용 워크로드 아이덴티티 제휴가 사용 설정되어 있습니다.

gcloud container clusters create-auto CLUSTER_NAME \
  --region=COMPUTE_REGION

다음을 바꿉니다.

  • CLUSTER_NAME: hello-cluster
  • COMPUTE_REGION: 클러스터의 Compute Engine 리전입니다. 이 튜토리얼에서는 Spanner 인스턴스를 만든 리전과 동일한 리전인 us-west1을 사용합니다. 지연 시간을 줄이려면 Spanner 인스턴스와 GKE Autopilot 클러스터를 동일한 리전 내에 만드는 것이 좋습니다.

클러스터를 만드는 데 최대 8~10분이 걸릴 수 있습니다.

출력은 다음과 비슷합니다.

NAME: hello-cluster
LOCATION: us-west1
MASTER_VERSION: 1.26.5-gke.1200
MASTER_IP: 192.0.2.1
MACHINE_TYPE: e2-medium
NODE_VERSION: 1.26.5-gke.1200
NUM_NODES: 3
STATUS: RUNNING

GKE에서 워크로드 아이덴티티 제휴를 사용하도록 클러스터 구성

앱을 배포하기 전에 GKE용 워크로드 아이덴티티 제휴를 사용하여 Google Cloud에 인증하도록 클러스터를 구성합니다.

  1. 클러스터에 액세스하기 위해 사용자 인증 정보를 가져옵니다.

    gcloud container clusters get-credentials CLUSTER_NAME \
      --region=COMPUTE_REGION
    

    다음을 바꿉니다.

    • CLUSTER_NAME: hello-cluster
    • COMPUTE_REGION: us-west1

    이렇게 하면 클러스터에서 kubectl을 가리키도록 적절한 사용자 인증 정보 및 엔드포인트 정보로 kubeconfig 파일이 업데이트됩니다.

  2. Kubernetes 서비스 계정에 사용할 네임스페이스를 만듭니다. 기본 네임스페이스 또는 기존 네임스페이스를 사용할 수도 있습니다.

    kubectl create namespace NAMESPACE
    

    NAMESPACE를 만들려는 새 네임스페이스의 이름인 hello-namespace로 바꿉니다.

  3. 애플리케이션이 사용할 Kubernetes 서비스 계정을 만듭니다.

    kubectl create serviceaccount KSA_NAME \
      --namespace NAMESPACE
    

    다음을 바꿉니다.

    • KSA_NAME: ksa-helloapp, 만들려는 새 Kubernetes 서비스 계정의 이름입니다.
    • NAMESPACE: hello-namespace
  4. 애플리케이션의 IAM 서비스 계정을 만듭니다.

    gcloud iam service-accounts create GSA_NAME \
      --project=GSA_PROJECT
    

    다음을 바꿉니다.

    • GSA_NAME: gsa-helloapp, 만들려는 새 IAM 서비스 계정의 이름입니다.
    • GSA_PROJECT: Google Cloud 프로젝트 ID입니다. 이 튜토리얼에서는 샘플 앱을 배포하는 동일한 Google Cloud 프로젝트에 IAM 서비스 계정을 만듭니다. 따라서 GSA_PROJECTPROJECT_ID가 동일합니다.
  5. IAM 서비스 계정이 Spanner에서 읽고 쓸 수 있도록 IAM 정책 바인딩을 추가합니다.

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member "serviceAccount:GSA_NAME@PROJECT_ID.iam.gserviceaccount.com" \
      --role "roles/spanner.admin"
    

    다음을 바꿉니다.

    • PROJECT_ID: Google Cloud 프로젝트 ID
    • GSA_NAME: gsa-helloapp

    예:

    gcloud projects add-iam-policy-binding my-gcp-project \
      --member "serviceAccount:gsa-helloapp@my-gcp-project.iam.gserviceaccount.com" \
      --role "roles/spanner.admin"
  6. Kubernetes 서비스 계정과 IAM 서비스 계정 사이에 IAM 정책 바인딩을 추가하여 Kubernetes 서비스 계정이 IAM 서비스 계정을 가장하도록 허용합니다. 이 바인딩을 통해 Kubernetes 서비스 계정이 IAM 서비스 계정 역할을 하므로 Kubernetes 서비스 계정이 Spanner에서 읽고 쓸 수 있습니다.

    gcloud iam service-accounts add-iam-policy-binding GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
    

    다음을 바꿉니다.

    • GSA_NAME: gsa-helloapp
    • GSA_PROJECT: Google Cloud 프로젝트 ID
    • PROJECT_ID: Google Cloud 프로젝트 ID
    • NAMESPACE: hello-namespace
    • KSA_NAME: ksa-helloapp

    예:

    gcloud iam service-accounts add-iam-policy-binding gsa-helloapp@my-gcp-project.iam.gserviceaccount.com \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:my-gcp-project.svc.id.goog[hello-namespace/ksa-helloapp]"
  7. Kubernetes 서비스 계정에 IAM 서비스 계정의 이메일 주소를 주석으로 추가합니다. 이를 통해 샘플 앱은 Google Cloud 서비스에 액세스하는 데 사용할 서비스 계정을 알 수 있습니다. 따라서 앱이 표준 Google API 클라이언트 라이브러리를 사용하여 Google Cloud 서비스에 액세스하면 해당 IAM 서비스 계정을 사용합니다.

    kubectl annotate serviceaccount KSA_NAME \
      --namespace NAMESPACE \
      iam.gke.io/gcp-service-account=GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com
    

    다음을 바꿉니다.

    • KSA_NAME: ksa-helloapp
    • NAMESPACE: hello-namespace
    • GSA_NAME: gsa-helloapp
    • GSA_PROJECT: Google Cloud 프로젝트 ID

    예:

    kubectl annotate serviceaccount ksa-helloapp \
      --namespace hello-namespace \
      iam.gke.io/gcp-service-account=gsa-helloapp@my-gcp-project.iam.gserviceaccount.com

샘플 앱을 클러스터에 배포

이제 필요한 서비스 및 인증을 사용하여 GKE 및 Spanner를 설정했으므로 샘플 앱 hello-app-cloud-spanner를 배포할 수 있습니다.

  1. GitHub 저장소에서 Cloud Shell에 샘플 앱을 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples.git
    
  2. 터미널 창의 툴바에서 코드 편집기 버튼 편집기 열기를 클릭하여 Cloud Shell 편집기를 시작합니다.

    자세한 내용은 Cloud Shell 편집기 인터페이스 개요를 참조하세요.

  3. Cloud Shell 편집기의 탐색기 창을 열고 kubernetes-engine-samples/databases/hello-app-cloud-spanner/k8s 디렉터리로 이동합니다.

  4. deployment.yaml 파일을 열고 <KSA_NAME>을 Kubernetes 서비스 계정의 이름인 ksa-helloapp으로 바꿔 serviceAccountName 필드를 업데이트합니다.

    yaml을 수정하여 KSA_NAME을 업데이트합니다.
    그림 1. 배포 파일에서 Kubernetes 서비스 계정 이름을 업데이트합니다.
  5. Cloud Shell 편집기를 닫고 Cloud Shell 터미널로 돌아갑니다.

  6. Cloud Shell 터미널에서 hello-app-cloud-spanner 디렉터리로 이동합니다.

    cd kubernetes-engine-samples/databases/hello-app-cloud-spanner
    
  7. 애플리케이션 배포:

    kubectl apply -f k8s/deployment.yaml -n=NAMESPACE
    

    NAMESPACEhello-namespace로 바꿉니다.

  8. 애플리케이션에서 STATUSRunning으로 배포될 때까지 기다립니다.

    kubectl get pods -n=NAMESPACE --watch
    

    NAMESPACEhello-namespace로 바꿉니다.

    출력은 다음과 비슷합니다.

    NAME                                       READY   STATUS              RESTARTS   AGE
    hello-app-cloud-spanner-765c9b8779-lfcrc   0/1     ContainerCreating   0          87s
    hello-app-cloud-spanner-765c9b8779-lfcrc   1/1     Running             0          3m15s
    
  9. 키보드의 Ctrl+C를 눌러 명령 프롬프트로 돌아가 추가 명령어를 실행합니다.

샘플 앱을 인터넷에 노출

클러스터 외부에서 Kubernetes 서비스를 노출하려면 LoadBalancer 유형의 서비스를 만듭니다. 이 유형의 서비스는 인터넷을 통해 연결할 수 있는 포드의 외부 부하 분산기 IP 주소를 생성합니다.

  1. 부하 분산기를 배포합니다.

    kubectl apply -f k8s/service.yaml -n=NAMESPACE
    

    NAMESPACEhello-namespace로 바꿉니다.

  2. 외부 IP 주소가 할당되는지 확인합니다.

    kubectl get service -n=NAMESPACE --watch
    

    NAMESPACEhello-namespace로 바꿉니다.

  3. 할당되면 EXTERNAL-IP(예: 203.0.113.0)를 복사하여 브라우저에서 엽니다. 플레이어의 데이터베이스를 표시하고 관리하는 웹 인터페이스가 열립니다.

  4. 앱 GUI를 사용하여 플레이어 레코드를 만들거나 삭제할 수 있으며 Spanner 데이터베이스에 저장됩니다.

    플레이어를 추가하거나 삭제합니다.
    그림 2. 레지스트리에서 플레이어를 만들거나 삭제합니다.

    다음 쿼리를 실행하여 Spanner 데이터베이스가 항목으로 업데이트되었는지 확인합니다.

    gcloud spanner databases execute-sql hello-database \
      --instance=hello-instance \
      --sql="SELECT * FROM Players LIMIT 10"
    

    출력은 다음과 비슷합니다.

    PlayerUuid: a1f34bbf-929c-498d-8b16-39bbb29d70e3
    FirstName: John
    LastName: Smith
    BirthDate: 1997-07-12
    
    PlayerUuid: d634e157-96ea-45f2-be3f-fb907ced188e
    FirstName: Jane
    LastName: Doe
    BirthDate: 2013-07-12
    

삭제

이 튜토리얼에서 사용된 리소스 비용이 Google Cloud 계정에 청구되지 않도록 하려면 리소스가 포함된 프로젝트를 삭제하거나 프로젝트를 유지하고 개별 리소스를 삭제하세요.

프로젝트 삭제

청구되지 않도록 하는 가장 쉬운 방법은 튜토리얼에서 만든 프로젝트를 삭제하는 것입니다.

Google Cloud 프로젝트를 삭제합니다.

gcloud projects delete PROJECT_ID

프로젝트를 삭제하면 정리가 완료됩니다. 프로젝트를 삭제하지 않은 경우 GKE 및 Spanner 리소스 삭제를 진행합니다.

GKE 리소스 삭제

  1. 서비스 삭제: 서비스용으로 생성된 Google Cloud 부하 분산기를 할당 해제합니다.

    kubectl delete service hello-app-cloud-spanner -n=NAMESPACE
    

    NAMESPACEhello-namespace로 바꿉니다.

  2. GKE 클러스터를 삭제합니다. 이렇게 하면 컴퓨팅 인스턴스, 디스크, 네트워크 리소스와 같이 클러스터를 구성하는 리소스가 삭제됩니다.

    gcloud container clusters delete CLUSTER_NAME --region=COMPUTE_REGION
    

    다음을 바꿉니다.

    • CLUSTER_NAME: hello-cluster
    • COMPUTE_REGION: us-west1

Spanner 리소스 삭제

  1. Spanner 데이터베이스를 삭제합니다.

    gcloud spanner databases delete hello-database --instance=hello-instance
    
  2. Spanner 인스턴스를 삭제합니다.

    gcloud spanner instances delete hello-instance
    

다음 단계