Google Kubernetes Engine을 사용한 분산 부하 테스트

Last reviewed 2024-08-13 UTC

이 문서에서는 단순한 REST 기반 API에 대한 트래픽을 생성하는 여러 컨테이너를 사용하는 분산 부하 테스트 프레임워크를 배포하기 위해 Google Kubernetes Engine(GKE)을 사용하는 방법을 설명합니다. 그리고 수신되는 HTTP POST 요청에 응답하기 위해 REST 스타일 엔드포인트를 노출하는 App Engine에 배포된 웹 애플리케이션의 부하 테스트를 수행합니다.

이와 동일한 패턴을 사용하여 메시징 시스템, 데이터 스트림 관리 시스템, 데이터베이스 시스템과 같은 다양한 시나리오 및 애플리케이션의 부하 테스트 프레임워크를 만들 수 있습니다.

목표

  • 배포 구성을 제어하는 환경 변수를 정의합니다.
  • GKE 클러스터를 만듭니다.
  • 부하 테스트를 수행합니다.
  • 선택적으로 사용자 수를 늘리거나 패턴을 다른 사용 사례로 확장합니다.

비용

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

  • App Engine
  • Artifact Registry
  • Cloud Build
  • Cloud Storage
  • Google Kubernetes Engine

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

시작하기 전에

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  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. Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.

    Enable the APIs

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

    Go to project selector

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

  7. Enable the App Engine, Artifact Registry, Cloud Build, Compute Engine, Resource Manager, Google Kubernetes Engine, and Identity and Access Management APIs.

    Enable the APIs

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

  9. Google 계정에 역할을 부여합니다. 다음 각 IAM 역할에 대해 다음 명령어를 한 번씩 실행합니다. roles/serviceusage.serviceUsageAdmin, roles/container.admin, roles/appengine.appAdmin, roles/appengine.appCreator, roles/artifactregistry.admin, roles/resourcemanager.projectIamAdmin, roles/compute.instanceAdmin.v1, roles/iam.serviceAccountUser, roles/cloudbuild.builds.builder, roles/iam.serviceAccountAdmin

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

예시 워크로드

다음 다이어그램은 요청이 클라이언트에서 애플리케이션으로 이동하는 워크로드의 예시를 보여줍니다.

클라이언트에서 애플리케이션으로 이동하는 요청

이 상호작용을 모델링하려면 요청을 여러 대상 경로에 분산할 수 있는 Python 기반의 분산형 부하 테스트 도구인 Locust를 사용합니다. 예를 들어 Locust는 /login/metrics 대상 경로로 요청을 분산할 수 있습니다. 워크로드는 Locust에서 일련의 태스크로 모델링됩니다.

아키텍처

이 아키텍처에는 두 개의 주요 구성요소가 포함됩니다.

  • Locust Docker 컨테이너 이미지
  • 컨테이너 조정 및 관리 메커니즘

Locust Docker 컨테이너 이미지에는 Locust 소프트웨어가 포함되어 있습니다. 이 문서에 포함된 GitHub 저장소를 클론할 때 얻는 Dockerfile은 기본 Python 이미지를 사용하며, Locust 서비스를 시작하고 태스크를 실행하는 스크립트를 포함합니다. 실제 클라이언트를 모방하기 위해 각 Locust 태스크에 가중치가 부여됩니다. 예를 들어 등록은 총 클라이언트 요청 1,000회당 한 번 발생합니다.

GKE는 컨테이너 조정 및 관리 기능을 제공합니다. GKE를 사용하면 부하 테스트 프레임워크의 기반을 제공하는 컨테이너 노드의 개수를 지정할 수 있습니다. 또한 부하 테스트 작업자를 포드로 구성하고, GKE에서 계속 실행할 포드의 수를 지정할 수 있습니다.

부하 테스트 작업을 배포하는 방법은 다음과 같습니다.

  1. Locust에서 마스터라고 하는 부하 테스트 기본을 배포합니다.
  2. 부하 테스트 작업자 그룹을 배포합니다. 이러한 부하 테스트 작업자를 통해 테스트 용도로 상당한 양의 트래픽을 생성할 수 있습니다.

다음 다이어그램은 샘플 애플리케이션을 사용한 부하 테스트를 보여주는 아키텍처입니다. 마스터 포드는 부하 테스트를 운영하고 모니터링하는 데 사용되는 웹 인터페이스를 제공합니다. 워커 포드는 테스트 대상 애플리케이션에 대한 REST 요청 트래픽을 생성하고 마스터에 측정항목을 전송합니다.

기본 포드는 부하 테스트를 운영하고 모니터링하는 데 사용되는 웹 인터페이스를 제공합니다. 워커 포드는 테스트 대상 애플리케이션에 대한 REST 요청 트래픽을 생성합니다.

부하 테스트 마스터 정보

Locust 마스터는 부하 테스트 태스크를 실행하기 위한 진입점입니다. Locust 마스터 구성은 컨테이너에 사용되는 기본 포트를 포함하여 여러 요소를 지정합니다.

  • 8089: 웹 인터페이스용
  • 55575558: 작업자와의 통신용

이 정보는 나중에 Locust 작업자를 구성하는 데 사용됩니다.

클러스터 내의 다른 포드가 필요한 포트에 hostname:port를 통해 액세스할 수 있도록 하는 서비스를 배포합니다. 설명적인 포트 이름을 통해 이러한 포트를 참조할 수도 있습니다.

이 서비스를 사용하면 마스터가 장애를 일으켜 배포를 통해 새로운 포드로 교체되더라도 Locust 워커가 마스터를 쉽게 발견하고 마스터와 안정적으로 통신할 수 있습니다.

두 번째 서비스는 필요한 주석과 함께 배포되어 내부 패스 스루 네트워크 부하 분산기를 만들며, 이 부하 분산기를 통해 클러스터 외부에 있으면서 클러스터와 동일한 VPC 네트워크를 사용하고 동일한 Google Cloud 리전에 위치하는 클라이언트에서 Locust 웹 애플리케이션 서비스에 액세스할 수 있게 됩니다.

Locust 마스터를 배포한 후에는 내부 패스 스루 네트워크 부하 분산기로 프로비저닝된 내부 IP 주소를 사용하여 웹 인터페이스를 열 수 있습니다. Locust 작업자가 배포된 후에는 시뮬레이션을 시작하여 Locust 웹 인터페이스를 통해 집계 통계를 확인할 수 있습니다.

부하 테스트 작업자 정보

Locust 작업자는 부하 테스트 태스크를 실행합니다. 단일 배포를 사용하여 여러 포드를 생성할 수 있습니다. 포드는 Kubernetes 클러스터 전체에 분산됩니다. 각 포드는 환경 변수를 사용하여 테스트 대상 시스템의 호스트 이름, Locust 마스터의 호스트 이름과 같은 구성 정보를 제어합니다.

아래 다이어그램은 Locust 마스터와 Locust 작업자 사이의 관계를 보여줍니다.

Locust 마스터는 여러 작업자가 속한 계층 구조의 맨 위에 있습니다.

공통 변수 초기화

인프라 요소가 배치되는 위치를 제어하는 여러 변수를 정의해야 합니다.

  1. Cloud Shell을 엽니다.

    Cloud Shell 열기

    이 문서의 모든 터미널 명령어는 Cloud Shell에서 실행합니다.

  2. 맞춤설정이 필요한 환경 변수를 설정합니다.

    export GKE_CLUSTER=GKE_CLUSTER
    export AR_REPO=AR_REPO
    export REGION=REGION
    export ZONE=ZONE
    export SAMPLE_APP_LOCATION=SAMPLE_APP_LOCATION
    

    다음을 바꿉니다.

    • GKE_CLUSTER: GKE 클러스터의 이름입니다.
    • AR_REPO: Artifact Registry 저장소의 이름입니다.
    • REGION: GKE 클러스터 및 Artifact Registry 저장소가 생성될 리전입니다.
    • ZONE: Compute Engine 인스턴스가 생성될 리전의 영역입니다.
    • SAMPLE_APP_LOCATION: 샘플 App Engine 애플리케이션이 배포될 (리전) 위치입니다.

    명령어가 다음 예시와 비슷하게 표시됩니다.

    export GKE_CLUSTER=gke-lt-cluster
    export AR_REPO=dist-lt-repo
    export REGION=us-central1
    export ZONE=us-central1-b
    export SAMPLE_APP_LOCATION=us-central
    
  3. 다음 추가 환경 변수를 설정합니다.

    export GKE_NODE_TYPE=e2-standard-4
    export GKE_SCOPE="https://www.googleapis.com/auth/cloud-platform"
    export PROJECT=$(gcloud config get-value project)
    export SAMPLE_APP_TARGET=${PROJECT}.appspot.com
    
  4. 후속 명령어에서 해당 값을 지정할 필요가 없도록 기본 영역을 설정합니다.

    gcloud config set compute/zone ${ZONE}
    

GKE 클러스터 만들기

  1. 클러스터에 필요한 최소 권한을 사용하여 서비스 계정을 만듭니다.

    gcloud iam service-accounts create dist-lt-svc-acc
    gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/artifactregistry.reader
    gcloud projects add-iam-policy-binding  ${PROJECT} --member=serviceAccount:dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com --role=roles/container.nodeServiceAccount
    
  2. GKE 클러스터를 만듭니다.

    gcloud container clusters create ${GKE_CLUSTER} \
    --service-account=dist-lt-svc-acc@${PROJECT}.iam.gserviceaccount.com \
    --region ${REGION} \
    --machine-type ${GKE_NODE_TYPE} \
    --enable-autoscaling \
    --num-nodes 3 \
    --min-nodes 3 \
    --max-nodes 10 \
    --scopes "${GKE_SCOPE}"
    
  3. GKE 클러스터에 연결합니다.

    gcloud container clusters get-credentials ${GKE_CLUSTER} \
       --region ${REGION} \
       --project ${PROJECT}
    

환경 설정

  1. GitHub에서 샘플 저장소를 클론합니다.

    git clone https://github.com/GoogleCloudPlatform/distributed-load-testing-using-kubernetes
    
  2. 작업 디렉터리를 다음의 클론된 저장소로 변경합니다.

    cd distributed-load-testing-using-kubernetes
    

컨테이너 이미지 빌드

  1. Artifact Registry 저장소를 만듭니다.

    gcloud artifacts repositories create ${AR_REPO} \
        --repository-format=docker  \
        --location=${REGION} \
        --description="Distributed load testing with GKE and Locust"
    
  2. 컨테이너 이미지를 빌드하고 이를 Artifact Registry 저장소에 저장합니다.

    export LOCUST_IMAGE_NAME=locust-tasks
    export LOCUST_IMAGE_TAG=latest
    gcloud builds submit \
        --tag ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO}/${LOCUST_IMAGE_NAME}:${LOCUST_IMAGE_TAG} \
        docker-image
    

    동반된 Locust Docker 이미지는 샘플 애플리케이션에서 /login/metrics 엔드포인트를 호출하는 테스트 작업을 삽입합니다. 이 예시 테스트 작업 세트에서 이러한 두 엔드포인트에 요청이 제출되는 비율은 각각 1~999입니다.

    
    class MetricsTaskSet(TaskSet):
        _deviceid = None
    
        def on_start(self):
            self._deviceid = str(uuid.uuid4())
    
        @task(1)
        def login(self):
            self.client.post(
                '/login', {"deviceid": self._deviceid})
    
        @task(999)
        def post_metrics(self):
            self.client.post(
                "/metrics", {"deviceid": self._deviceid, "timestamp": datetime.now()})
    
    
    class MetricsLocust(FastHttpUser):
        tasks = {MetricsTaskSet}
    

  3. Docker 이미지가 Artifact Registry 저장소에 있는지 확인합니다.

    gcloud artifacts docker images list ${REGION}-docker.pkg.dev/${PROJECT}/${AR_REPO} | \
        grep ${LOCUST_IMAGE_NAME}
    

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

    Listing items under project PROJECT, location REGION, repository AR_REPO
    
    REGION-docker.pkg.dev/PROJECT/AR_REPO/locust-tasks  sha256:796d4be067eae7c82d41824791289045789182958913e57c0ef40e8d5ddcf283  2022-04-13T01:55:02  2022-04-13T01:55:02
    

샘플 애플리케이션 배포

  1. 샘플 웹 앱을 만들고 App Engine으로 배포합니다.

    gcloud app create --region=${SAMPLE_APP_LOCATION}
    gcloud app deploy sample-webapp/app.yaml \
    --project=${PROJECT}
    
  2. 메시지가 표시되면 y를 입력하여 배포를 진행합니다.

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

    File upload done.
    Updating service [default]...done.
    Setting traffic split for service [default]...done.
    Deployed service [default] to [https://PROJECT.appspot.com]
    

    샘플 App Engine 애플리케이션이 /login/metrics 엔드포인트를 구현합니다.

    @app.route('/login',  methods=['GET', 'POST'])
    def login():
        deviceid = request.values.get('deviceid')
        return '/login - device: {}\n'.format(deviceid)
    
    @app.route('/metrics',  methods=['GET', 'POST'])
    def metrics():
        deviceid = request.values.get('deviceid')
        timestamp = request.values.get('timestamp')
    
        return '/metrics - device: {}, timestamp: {}\n'.format(deviceid, timestamp)

Locust 마스터 및 워커 포드 배포

  1. locust-master-controller.yamllocust-worker-controller.yaml 파일에서 대상 호스트, 프로젝트, 이미지 매개변수에 대한 환경 변수 값을 바꾸고 Locust 마스터 및 워커 배포를 만듭니다.

    envsubst < kubernetes-config/locust-master-controller.yaml.tpl | kubectl apply -f -
    envsubst < kubernetes-config/locust-worker-controller.yaml.tpl | kubectl apply -f -
    envsubst < kubernetes-config/locust-master-service.yaml.tpl | kubectl apply -f -
    
  2. Locust 배포를 확인합니다.

    kubectl get pods -o wide
    

    출력은 다음과 같습니다.

    NAME                             READY   STATUS    RESTARTS   AGE   IP           NODE
    locust-master-87f8ffd56-pxmsk    1/1     Running   0          1m    10.32.2.6    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-279q9   1/1     Running   0          1m    10.32.1.5    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-9frbw   1/1     Running   0          1m    10.32.2.8    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-dppmz   1/1     Running   0          1m    10.32.2.7    gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-g8tzf   1/1     Running   0          1m    10.32.0.11   gke-gke-load-test-default-pool-96a3f394
    locust-worker-58879b475c-qcscq   1/1     Running   0          1m    10.32.1.4    gke-gke-load-test-default-pool-96a3f394
    
  3. 서비스를 확인합니다.

    kubectl get services
    

    출력은 다음과 같습니다.

    NAME                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)             AGE
    kubernetes          ClusterIP      10.87.240.1     <none>        443/TCP             12m
    locust-master       ClusterIP      10.87.245.22    <none>        5557/TCP,5558/TCP    1m
    locust-master-web   LoadBalancer   10.87.246.225   <pending>     8089:31454/TCP       1m
    
  4. Locust 마스터 웹 애플리케이션 서비스에 대해 내부 패스 스루 네트워크 부하 분산기의 내부 IP 주소(GKE 외부 IP 주소)를 프로비저닝하는 동안 감시 루프를 실행합니다.

    kubectl get svc locust-master-web --watch
    
  5. EXTERNAL-IP 주소가 프로비저닝된 후 Ctrl+C를 눌러 감시 루프를 종료합니다.

Locust 웹 프런트엔드에 연결

Locust 마스터 웹 인터페이스를 사용하여 테스트 중인 시스템을 대상으로 부하 테스트 태스크를 실행할 수 있습니다.

  1. 웹 호스트 서비스의 내부 부하 분산기 IP 주소를 기록해 둡니다.

    export INTERNAL_LB_IP=$(kubectl get svc locust-master-web  \
                                   -o jsonpath="{.status.loadBalancer.ingress[0].ip}") && \
                                   echo $INTERNAL_LB_IP
    
  2. 네트워크 구성에 따라 프로비저닝된 IP 주소를 통해 Locust 웹 애플리케이션에 연결할 수 있는 두 가지 방법이 있습니다.

    • 네트워크 라우팅. 워크스테이션에서 프로젝트 VPC 네트워크로 라우팅할 수 있도록 네트워크가 구성된 경우 워크스테이션에서 내부 패스 스루 네트워크 부하 분산기 IP 주소에 직접 액세스할 수 있습니다.

    • 프록시 및 SSH 터널. 워크스테이션과 VPC 네트워크 사이에 네트워크 경로가 없으면 nginx 프록시와 워크스테이션 및 인스턴스 사이의 SSH 터널을 사용하여 Compute Engine 인스턴스를 만들어서 트래픽을 내부 패스 스루 네트워크 부하 분산기의 IP 주소로 라우팅할 수 있습니다.

네트워크 라우팅

워크스테이션과 Google Cloud 프로젝트 VPC 네트워크 사이에 네트워크 트래픽 경로가 있으면 브라우저를 열고 Locust 마스터 웹 인터페이스를 엽니다. Locust 인터페이스를 열려면 다음 URL로 이동합니다.

http://INTERNAL_LB_IP:8089

INTERNAL_LB_IP를 이전 단계에서 기록한 URL과 IP 주소로 바꿉니다.

프록시 및 SSH 터널

  1. 환경 변수를 인스턴스의 이름으로 설정합니다.

    export PROXY_VM=locust-nginx-proxy
    
  2. 내부 패스 스루 네트워크 부하 분산기에서 Locust 웹 애플리케이션 포트 8089를 프록시하도록 구성된 ngnix Docker 컨테이너를 사용하여 인스턴스를 시작합니다.

    gcloud compute instances create-with-container ${PROXY_VM} \
       --zone ${ZONE} \
       --container-image gcr.io/cloud-marketplace/google/nginx1:latest \
       --container-mount-host-path=host-path=/tmp/server.conf,mount-path=/etc/nginx/conf.d/default.conf \
       --metadata=startup-script="#! /bin/bash
         cat <<EOF  > /tmp/server.conf
         server {
             listen 8089;
             location / {
                 proxy_pass http://${INTERNAL_LB_IP}:8089;
             }
         }
    EOF"
    
  3. Cloud Shel에서 프록시 인스턴스로 SSH 터널을 엽니다.

    gcloud compute ssh --zone ${ZONE} ${PROXY_VM} \
                     -- -N -L 8089:localhost:8089
    
  4. 웹 미리보기 아이콘(Cloud Shell 웹 미리보기 아이콘)을 클릭하고 나열된 옵션에서 포트 변경을 선택합니다.

  5. 미리보기 포트 변경 대화상자의 포트 번호 필드에 8089를 입력하고 변경 및 미리보기를 선택합니다.

    잠시 후 Locust 웹 인터페이스와 함께 브라우저 탭이 열립니다.

샘플 애플리케이션에서 기본 부하 테스트 실행

  1. 브라우저에서 Locust 프런트엔드를 연 후 새 부하 테스트를 시작하는 데 사용할 수 있는 대화상자가 표시됩니다.

    Locust 마스터 웹 인터페이스는 새로운 생성을 시작하고 사용자 수와 생성 속도를 지정하는 대화상자를 제공합니다.

  2. Number of users(peak concurrency)(사용자 수, 최대 동시 실행)를 10으로, Spawn rate(users started/second)(생성 속도, 초당 시작 사용자 수)를 초당 사용자 5명으로 지정합니다.

  3. 그런 다음 Start swarming(생성 시작)을 클릭하여 시뮬레이션을 시작합니다.

    요청이 생성되기 시작하면 다음 이미지처럼 요청 수 및 초당 요청 수와 같은 시뮬레이션 측정항목의 통계가 집계되기 시작합니다.

    Locust 웹 인터페이스는 통계가 집계되기 시작함을 보여줍니다.

  4. Google Cloud 콘솔에서 배포된 서비스 및 기타 측정항목을 확인합니다.

    App Engine 대시보드에는 한 시간 동안의 요청 그래프가 유형별로 표시됩니다.

  5. 테스트 중인 애플리케이션의 동작을 확인했으면 Stop(중지)를 클릭하여 테스트를 종료합니다.

사용자 수 확장(선택사항)

애플리케이션의 부하 증가를 테스트하려면 시뮬레이션된 사용자를 추가합니다. 시뮬레이션된 사용자를 추가하기 전에 먼저 부하 증가를 지원하기에 충분한 리소스가 있는지 확인해야 합니다. Google Cloud를 사용할 경우 증가된 수의 포드를 지원할 기본 VM 리소스가 있는 기존 포드를 재배포하지 않고 Locust 작업자 포드를 배포에 추가할 수 있습니다. 초기 GKE 클러스터는 3개의 노드로 시작하여 최대 10개의 노드로 자동 확장할 수 있습니다.

  • Locust 워커 포드의 풀을 20으로 확장합니다.

    kubectl scale deployment/locust-worker --replicas=20
    

    새로운 포드를 배포하고 시작하는 데 몇 분이 걸립니다.

예약할 수 없는 포드 오류가 표시되면 클러스터에 노드를 추가해야 합니다. 자세한 내용은 GKE 클러스터 크기 조정을 참조하세요.

포드가 시작되면 Locust 마스터 웹 인터페이스로 돌아가서 부하 테스트를 다시 시작하세요.

패턴 확장

이 패턴을 확장하려면 새로운 Locust 태스크를 생성하거나 다른 부하 테스트 프레임워크로 전환합니다.

수집하는 측정항목을 맞춤설정할 수 있습니다. 예를 들어 초당 요청을 측정하거나, 부하 증가에 따른 응답 지연 시간을 모니터링하거나, 응답 실패율 및 오류 유형을 확인할 수 있습니다.

자세한 내용은 Cloud Monitoring 문서를 참조하세요.

삭제

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

프로젝트 삭제

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

GKE 클러스터 삭제

전체 프로젝트를 삭제하지 않으려면 다음 명령어를 실행하여 GKE 클러스터를 삭제하세요.

   gcloud container clusters delete ${GKE_CLUSTER} --region ${REGION}
   

다음 단계