온프레미스 하드웨어에서 Google Cloud로 리소스 매핑

이 문서에서는 온프레미스 하드웨어에서 Google Cloud로 리소스를 올바르게 매핑하는 방법을 보여줍니다. 애플리케이션이 베어 메탈 서버에서 실행 중이고 Google Cloud로 마이그레이션하려는 경우 다음과 같은 질문을 고려해 볼 수 있습니다.

  • 물리적 코어(pCPU)는 Google Cloud의 가상 CPU(vCPU)에 어떻게 매핑되나요? 예를 들어 베어 메탈 Xeon E5의 물리적 코어 4개는 Google Cloud의 vCPU에 어떻게 매핑되나요?
  • CPU 플랫폼과 프로세서 세대 간의 성능 차이를 어떻게 설명하나요? 예를 들어 2.0GHz Skylake보다 3.0GHz Sandy Bridge 속도가 1.5배 더 빠른가요?
  • 워크로드에 따라 리소스의 크기를 어떻게 조정하나요? 예를 들어 멀티코어 서버에서 실행되는 메모리 집약적인 단일 스레드 애플리케이션을 어떻게 최적화할 수 있나요?

소켓, CPU, 코어, 스레드

소켓, CPU, 코어, 스레드라는 용어는 종종 서로 바꿔서 사용되기도 하지만 다른 환경 간에 마이그레이션하는 경우 혼란을 야기할 수 있습니다.

간단히 말해 서버에 하나 이상의 소켓이 있을 수 있습니다. 소켓(CPU 소켓 또는 CPU 슬롯이라고도 함)은 CPU 칩이 있는 마더보드의 커넥터이며 CPU와 회로 보드를 물리적으로 연결합니다.

CPU는 실제 통합 회로(IC)를 나타냅니다. CPU의 기본 작업은 일련의 저장된 명령을 실행하는 것입니다. 상위 수준에서 CPU는 명령 주기라고 알려진 가져오기, 디코딩, 실행 단계를 따릅니다. 더 복잡한 CPU에서는 여러 명령을 동시에 가져와 디코딩하고 실행할 수 있습니다.

각 CPU 칩에는 하나 이상의 코어가 있을 수 있습니다. 코어는 명령을 수신하고 수신한 명령에 따라 작업을 수행하는 실행 단위로 구성됩니다. 하이퍼 스레드 시스템에서 물리적 프로세서 코어를 통해 리소스를 여러 논리 프로세서로 할당할 수 있습니다. 즉, 각 실제 프로세서 코어는 두 개의 가상 또는 논리 코어로 운영체제에 제공됩니다.

다음 다이어그램은 하이퍼 스레딩을 사용하는 쿼드 코어 CPU의 대략적인 보기를 보여줍니다.

하이퍼 스레딩을 사용하는 쿼드 코어 CPU

Google Cloud에서 각 vCPU는 사용 가능한 CPU 플랫폼 중 하나에서 단일 하이퍼 스레드로 구현됩니다.

시스템의 총 vCPU(논리 CPU) 수를 찾으려면 다음 수식을 사용하세요.

vCPU = 물리적 코어당 스레드 수 × 소켓당 물리적 코어 수 × 소켓 수

lscpu 명령어는 소켓, CPU, 코어, 스레드 등의 수를 포함하는 정보를 수집합니다. 또한 CPU 캐시 및 캐시 공유, 제품군, 모델, BogoMips에 대한 정보도 포함됩니다. 다음은 몇 가지 일반적인 출력입니다.

...
Architecture:           x86_64
CPU(s):                 1
On-line CPU(s) list:    0
Thread(s) per core:     1
Core(s) per socket:     1
Socket(s):              1
CPU MHz:                2200.000
BogoMIPS:               4400.00
...

기존 환경과 Google Cloud 간에 CPU 리소스를 매핑할 때는 서버의 물리적 또는 가상 코어 수를 알아야 합니다. 자세한 내용은 매핑 리소스 섹션을 참조하세요.

CPU 클록 속도

프로그램을 실행하려면 프로세서가 이해할 수 있는 명령 세트로 나눠야 합니다. 두 개의 숫자를 추가하고 결과를 표시하는 다음 C 프로그램을 살펴보세요.

#include <stdio.h>
int main()
{
        int a = 11, b = 8;
        printf("%d \n", a+b);
}

컴파일 시 프로그램은 다음 어셈블리 코드로 변환됩니다.

...
main:
.LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $16, %rsp
        movl    $11, -8(%rbp)
        movl    $8, -4(%rbp)
        movl    -8(%rbp), %edx
        movl    -4(%rbp), %eax
        addl    %edx, %eax
        movl    %eax, %esi
        movl    $.LC0, %edi
        movl    $0, %eax
        call    printf
        movl    $0, %eax
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
...

위 출력에서 각 어셈블러 명령은 단일 머신 명령에 해당합니다. 예를 들어 pushq 명령은 RBP 등록의 콘텐츠를 프로그램 스택으로 푸시해야 함을 나타냅니다. 각 CPU 주기 동안 CPU는 명령 가져오기, 등록 콘텐츠 액세스, 데이터 쓰기와 같은 기본 작업을 수행할 수 있습니다. 두 숫자를 더하기 위해 주기를 단계별로 수행하려면 이 CPU 시뮬레이터를 참조하세요.

각 CPU 명령을 실행하려면 여러 클록 주기가 필요할 수 있습니다. 프로그램에 대한 명령당 필요한 평균 클록 주기 수는 다음과 같이 명령당 주기(CPI)로 정의됩니다.

명령당 주기=사용된 CPU 주기 수/실행된 명령 수

대부분의 최신 CPU는 명령 파이프라인을 통해 클록 주기당 여러 명령을 실행할 수 있습니다. 주기당 실행된 평균 명령 수는 다음과 같이 주기당 명령(IPC)으로 정의됩니다.

주기당 명령=실행된 명령 수/사용된 CPU 주기 수

CPU 클록 속도는 프로세서가 초당 실행할 수 있는 클록 주기 수를 정의합니다. 예를 들어 3.0GHz 프로세서는 초당 30억 클록 주기를 실행할 수 있습니다. 즉, 모든 클록 주기를 실행하는 데 약 0.3나노초가 걸립니다. 각 클록 주기 동안 CPU는 IPC에서 정의한 대로 하나 이상의 명령을 수행할 수 있습니다.

클록 속도는 일반적으로 프로세서 성능을 비교하는 데 사용됩니다. 문자 그대로의 정의(초당 실행된 주기 수)에 따라 클록 주기 수가 많을수록 CPU가 더 많은 작업을 수행하여 더 나은 성능을 발휘할 수 있다는 결론을 내릴 수 있습니다. 이 결론은 동일한 프로세서 세대의 CPU를 비교할 때 유효할 수 있습니다. 하지만 다른 프로세서 제품군의 CPU를 비교할 때 클록 속도를 유일한 성능 지표로 사용해서는 안 됩니다. 차세대 CPU는 이전 세대 CPU보다 낮은 클록 속도로 실행되는 경우에도 더 나은 성능을 제공할 수 있습니다.

클록 속도 및 시스템 성능

프로세서의 성능을 더 잘 이해하려면 클록 주기뿐만 아니라 CPU가 주기당 수행할 수 있는 작업도 고려해야 합니다. CPU의 제한을 받은 프로그램의 총 실행 시간은 클록 속도뿐 아니라 실행할 명령 수, 명령당 주기 또는 주기당 명령, 명령 집합 아키텍처, 예약디스패치 알고리즘, 사용된 프로그래밍 언어와 같은 다른 요소에 따라 달라집니다. 이러한 요소는 프로세서 세대마다 크게 다를 수 있습니다.

두 가지 다른 구현에서 CPU 실행이 어떻게 다른지 이해하려면 간단한 계승 프로그램 예시를 살펴보세요. 다음 프로그램 중 하나는 C로, 다른 프로그램은 Python으로 작성됩니다. Perf(Linux용 프로파일링 도구)는 일부 CPU 및 커널 측정항목을 캡처하는 데 사용됩니다.

C 프로그램

#include <stdio.h>
int main()
{
    int n=7, i;
    unsigned int factorial = 1;
    for(i=1; i<=n; ++i){
            factorial *= i;
    }

    printf("Factorial of %d = %d", n, factorial);
}

Performance counter stats for './factorial':

...
0             context-switches       #    0.000 K/sec
0             cpu-migrations         #    0.000 K/sec
45            page-faults            #    0.065 M/sec
1,562,075     cycles                 #    1.28 GHz
1,764,632     instructions           #    1.13  insns per cycle
314,855       branches               #    257.907 M/sec
8,144         branch-misses          #    2.59% of all branches
...

0.001835982 seconds time elapsed

Python 프로그램

num = 7
factorial = 1
for i in range(1,num + 1):
  factorial = factorial*i
print("The factorial of",num,"is",factorial)

Performance counter stats for 'python3 factorial.py':

...
7              context-switches      #    0.249 K/sec
0              cpu-migrations        #    0.000 K/sec
908            page-faults           #    0.032 M/sec
144,404,306    cycles                #    2.816 GHz
158,878,795    instructions          #    1.10  insns per cycle
38,254,589     branches              #    746.125 M/sec
945,615        branch-misses         #    2.47% of all branches
...

0.029577164 seconds time elapsed

강조표시된 출력에 각 프로그램을 실행하는 데 걸린 총 시간이 표시됩니다. C로 작성된 프로그램은 Python으로 작성된 프로그램보다 15배 빠릅니다(각각 1.8밀리초와 30밀리초). 다음은 몇 가지 추가 비교 항목입니다.

  • 컨텍스트 전환 시스템 스케줄러가 다른 프로그램을 실행해야 하거나 인터럽트가 진행 중인 실행을 트리거하면 운영체제는 실행 중인 프로그램의 CPU 등록 콘텐츠를 저장하고 새 프로그램 실행을 위해 설정합니다. C 프로그램 실행 중에 컨텍스트 전환이 발생하지 않았지만 Python 프로그램 실행 중에 7건의 컨텍스트 전환이 발생했습니다.

  • CPU 마이그레이션 운영체제는 멀티 프로세서 시스템에서 사용 가능한 CPU 간에 워크로드 분산을 유지하려고 합니다. 이러한 분산은 CPU 실행 큐가 비어있을 때마다 주기적으로 수행됩니다. 테스트 중에는 CPU 마이그레이션이 관찰되지 않았습니다.

  • 안내. C 프로그램은 150만 개의 CPU 주기(IPC=1.13, CPI=0.88)로 실행된 170만 개의 명령을 생성한 반면, Python 프로그램은 1억 4,400만 개의 주기(IPC=1.10, CPI=0.91)로 실행된 1억 5,800만 개의 명령을 생성했습니다. 두 프로그램 모두 파이프라인을 채웠기 때문에 CPU가 주기당 둘 이상의 명령을 실행할 수 있습니다. 하지만 C에 비해 Python에서 생성되는 명령의 수는 90배 더 큽니다.

  • 페이지 오류. 각 프로그램에는 가상 메모리 슬라이스가 있으며 모든 명령과 데이터가 포함되어 있습니다. 일반적으로 이러한 모든 명령을 기본 메모리에 한 번에 복사하는 것은 효율적이지 않습니다. 페이지 오류는 프로그램이 가상 메모리의 콘텐츠 일부를 기본 메모리에 복사해야 할 때마다 발생합니다. 페이지 오류는 CPU에서 인터럽트를 통해 알립니다.

    Python의 인터프리터 실행 파일은 C보다 훨씬 크므로 추가 오버헤드는 CPU 주기(C의 경우 150만, Python의 경우 1억 4,400만)와 페이지 오류(C의 경우 45, Python의 경우 908)의 측면에서 분명합니다.

  • 분기 및 분기 누락. 조건부 명령의 경우 CPU는 분기 조건을 평가하기 전에 실행 경로를 예측하려고 시도합니다. 이러한 단계는 명령 파이프라인을 채우는 데 유용합니다. 이 프로세스를 예측 실행이라고 합니다. 예측 실행은 이전 실행에서 상당히 성공적이었습니다. 분기 예측자는 C의 프로그램 시간의 2.59%와 Python의 프로그램 시간의 2.47%만 잘못되었습니다.

CPU 이외의 요인

지금까지 CPU의 다양한 측면과 성능에 미치는 영향을 살펴보았습니다. 하지만 애플리케이션이 100% CPU 지속 실행을 유지하는 경우는 거의 없습니다. 간단한 예시로 Linux의 사용자 home 디렉터리에서 보관 파일을 만드는 다음 tar 명령어를 살펴보세요.

$ time tar cf archive.tar /home/"$(whoami)"

출력 형식은 다음과 같습니다.

real  0m35.798s
user  0m1.146s
sys   0m6.256s

이러한 출력 값은 다음과 같이 정의됩니다.

실시간
실시간(real)은 시작부터 끝날 때까지 걸리는 실행 시간입니다. 이 경과 시간에는 다른 프로세스에서 사용하는 시간 구획과 프로세스가 차단된 시간(예: I/O 작업이 완료되기를 기다리는 시간)이 포함됩니다.
사용자 시간
사용자 시간(user)은 프로세스에서 사용자 공간 코드를 실행하는 데 소비한 CPU 시간입니다.
시스템 시간
시스템 시간(sys)은 프로세스에서 커널 공간 코드를 실행하는 데 소요된 CPU 시간입니다.

이전 예시에서 사용자 시간은 1.0초이고 시스템 시간은 6.3초입니다. real 시간과 user+sys 시간 간의 최대 28초 차이는 tar 명령어가 소비한 CPU 종료 시간을 가리킵니다.

CPU 사용량이 많지 않은 시간은 프로세스가 CPU의 제한을 받지 않음을 나타냅니다. 리소스가 예상 성능을 달성하기 위한 병목 현상인 경우 계산이 무언가에 의해 제약을 받습니다. 마이그레이션을 계획할 때는 애플리케이션을 전체적으로 살펴보고 성능에 중대한 영향을 미칠 수 있는 모든 요소를 고려해야 합니다.

마이그레이션 시 대상 워크로드의 역할

마이그레이션의 적절한 시작점을 찾으려면 기본 리소스를 벤치마킹해야 합니다. 다양한 방법으로 성능 벤치마킹을 수행할 수 있습니다.

  • 실제 대상 워크로드: 대상 환경에 애플리케이션을 배포하고 핵심성과지표(KPI)의 성능을 벤치마킹합니다. 예를 들어 웹 애플리케이션의 KPI에는 다음이 포함될 수 있습니다.

    • 애플리케이션 로드 시간
    • 엔드 투 엔드 트랜잭션의 최종 사용자 지연 시간
    • 연결 끊김
    • 낮은 트래픽, 평균 트래픽, 최대 트래픽의 제공 인스턴스 수
    • 제공 인스턴스의 리소스(CPU, RAM, 디스크, 네트워크) 사용률

    그러나 대상 애플리케이션의 전체 또는 일부를 배포하는 작업은 복잡하고 시간이 많이 소요될 수 있습니다. 예비 벤치마킹의 경우 일반적으로 프로그램 기반 벤치마크가 선호됩니다.

  • 프로그램 기반 벤치마크: 프로그램 기반 벤치마크는 엔드 투 엔드 애플리케이션 흐름이 아닌 애플리케이션의 개별 구성요소에 중점을 둡니다. 이러한 벤치마크는 테스트 프로필을 혼합하여 실행하며 각 프로필은 애플리케이션의 한 구성요소를 대상으로 합니다. 예를 들어 LAMP 스택 배포용 테스트 프로필에는 웹 서버 성능을 벤치마크하는 데 사용되는 Apache Bench 및 MySQL을 벤치마크하는 데 사용되는 Sysbench가 포함될 수 있습니다. 이러한 테스트는 일반적으로 실제 대상 워크로드보다 설정하기 쉽고 여러 운영체제 및 환경에서 이식성이 뛰어납니다.

  • 커널 또는 합성 벤치마크: 실제 프로그램에서 컴퓨팅 중심의 주요 측면을 테스트하기 위해 행렬 분해 또는 FFT와 같은 합성 벤치마크를 사용할 수 있습니다. 일반적으로 이러한 테스트는 초기 애플리케이션 설계 단계에서 실행됩니다. VM 및 드라이브 부하, I/O 동기화, 캐시 스래싱과 같은 머신의 특정 측면만 벤치마킹하는 데 가장 적합합니다.

애플리케이션 이해하기

많은 애플리케이션이 CPU, 메모리, 디스크 I/O, 네트워크 I/O 또는 이러한 요소의 조합에 따라 제한됩니다. 예를 들어 디스크의 경합으로 인해 애플리케이션의 속도가 느린 경우 서버에 코어를 추가하면 성능이 향상되지 않을 수 있습니다.

크고 복잡한 환경에서 애플리케이션의 관측 가능성을 유지하기는 쉽지 않습니다. 분산된 시스템 전체 리소스를 추적할 수 있는 전문 모니터링 시스템이 있습니다. 예를 들어 Google Cloud에서는 Cloud Monitoring을 사용하여 코드, 애플리케이션, 인프라를 완벽하게 파악할 수 있습니다. Cloud Monitoring 예시는 이 섹션의 뒷부분에서 설명하지만 먼저 독립형 서버의 일반적인 시스템 리소스 모니터링을 이해하는 것이 좋습니다.

top, IOStat, VMStat, iPerf와 같은 많은 유틸리티는 시스템 리소스의 대략적인 보기를 보여줍니다. 예를 들어 Linux 시스템에서 top을 실행하면 다음과 같은 출력이 생성됩니다.

top - 13:20:42 up 22 days,  5:25,         18 users,        load average: 3.93 2.77,3.37
Tasks:  818 total,        1 running,      760 sleeping,    0 stopped,       0 zombie
Cpu(s): 88.2%us,          0.0%sy,         0.0%ni,          0.3%id,          0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem:    49375504k total,  6675048k used,  42700456k free,  276332k buffers
Swap:   68157432k total,  0k used,        68157432k free,  5163564k cached

시스템의 로드가 높고 대기 시간 비율이 높으면 I/O 바운드 애플리케이션이 있을 수 있습니다. 사용자 백분율 시간 또는 시스템 백분율 시간 중 하나 또는 둘 다 매우 높으면 CPU 바운드 애플리케이션이 있을 가능성이 높습니다.

이전 예시에서 마지막 5분, 10분, 15분 동안의 로드 평균(4개의 vCPU VM)은 각각 3.93, 2.77, 3.37입니다. 이러한 평균을 높은 사용자 시간 비율(88.2%), 낮은 유휴 시간(0.3%), 대기 시간 없음(0.0%)과 결합하면 시스템이 CPU의 제한을 받는 상태라고 결론 지을 수 있습니다.

이러한 도구는 독립형 시스템에서 잘 작동하지만 일반적으로 대규모 분산 환경을 모니터링하도록 설계되지 않았습니다. 프로덕션 시스템을 모니터링하기 위해 Cloud Monitoring, Nagios, Prometheus, Sysdig 같은 도구를 사용하면 애플리케이션에 대한 리소스 소비에 대한 심층 분석을 제공할 수 있습니다.

일정 시간 동안 애플리케이션을 성능 모니터링하면 CPU 사용률, 메모리 사용량, 디스크 I/O, 네트워크 I/O, 왕복 시간, 지연 시간, 오류 발생률, 처리량 등 여러 측정항목에서 데이터를 수집할 수 있습니다. 예를 들어 다음 Cloud Monitoring 그래프는 Google Cloud 관리형 인스턴스 그룹에서 실행되는 모든 서버의 메모리 및 디스크 사용량과 함께 CPU 로드 및 사용률 수준을 보여줍니다. 이 설정에 대한 자세한 내용은 Cloud Monitoring 에이전트 개요를 참조하세요.

관리형 인스턴스 그룹에서 실행되는 모든 서버의 CPU 로드, 사용률 수준, 메모리 및 디스크 사용량

분석을 위해 데이터 수집 기간은 리소스의 최고 및 최저 활용률을 표시할 만큼 충분히 길어야 합니다. 그런 다음 수집된 데이터를 분석하여 새 대상 환경에서 용량 계획의 시작점을 제공할 수 있습니다.

지도 리소스

이 섹션에서는 Google Cloud에서 리소스 크기를 설정하는 방법을 살펴봅니다. 먼저 기존 리소스 활용률 수준을 기준으로 초기 크기 조정 평가를 수행합니다. 그런 다음 애플리케이션별 성능 벤치마킹 테스트를 실행합니다.

사용량 기반 크기 조정

서버의 기존 코어 수를 Google Cloud의 vCPU에 매핑하려면 다음 단계를 따르세요.

  1. 현재 코어 수를 찾습니다. 이전 섹션lscpu 명령어 참조

  2. 서버의 CPU 사용률을 찾습니다. CPU 사용량은 CPU가 사용자 모드(%us) 또는 커널 모드(%sy)일 때 걸리는 시간을 나타냅니다. Nice 프로세스(%ni)도 사용자 모드에 속하지만 소프트웨어 인터럽트(%si) 및 하드웨어 인터럽트(%hi)는 커널 모드에서 처리됩니다. CPU가 이러한 작업을 수행하지 않으면 유휴 상태이거나 I/O가 완료되기를 기다리는 중입니다. 프로세스가 I/O 완료 대기 중인 경우 CPU 주기에 영향을 주지 않습니다.

    서버의 현재 CPU 사용량을 계산하려면 다음 top 명령어를 실행합니다.

    ...
    Cpu(s): 88.2%us,  0.0%sy,  0.0%ni,  0.3%id,  0.0%wa,  0.0%hi,  0.0%si, 0.0%st
    ...
    

    CPU 사용량은 다음과 같이 정의됩니다.

    CPU Usage = %us + %sy + %ni + %hi + %si
    

    Cloud Monitoring과 같은 모니터링 도구를 사용하여 필요한 CPU 인벤토리 및 사용률을 수집할 수도 있습니다. 자동 확장이 아닌 애플리케이션 배포(즉, 하나 이상의 고정 서버에서 실행)의 경우 CPU 크기 조정에 최대 사용률을 사용하는 것이 좋습니다. 이 접근 방식은 워크로드가 최대 사용량일 때 애플리케이션 리소스를 중단으로부터 보호합니다. 자동 확장 배포(CPU 사용량 기준)의 경우 평균 CPU 사용률은 크기를 고려할 때 안전한 기준입니다. 이 경우 트래픽이 급증하는 기간에 서버 수를 확장하여 트래픽 급증을 처리합니다.

  3. 모든 급증을 처리하기에 충분한 버퍼를 할당합니다. CPU 크기를 조정하는 경우 예기치 않은 급증을 유발할 수도 있는 예약되지 않은 처리를 수용하기에 충분한 버퍼를 고려합니다. 예를 들어 예상 최대 사용량에 대해 10~15%의 추가 여유 공간이 있고 전체 최대 CPU 사용률이 70%를 초과하지 않도록 CPU 용량을 계획할 수 있습니다.

  4. 다음 수식을 사용하여 GCP의 예상 코어 수를 계산합니다.

    Google Cloud의 vCPU=2×CEILING[(코어 수×사용률(%))/(2×임곗값(%))]

    이러한 값은 다음과 같이 정의됩니다.

    • 코어 수: 1단계에서 계산된 기존 코어 수입니다.
    • 사용률(%): 2단계에서 계산된 서버의 CPU 사용률입니다.
    • 임곗값(%): 3단계의 계산에 따라 충분한 여유 공간을 고려한 후 서버에서 허용되는 최대 CPU 사용량입니다.

구체적인 예를 들어 온프레미스로 실행되는 베어 메탈 4 코어 Xeon E5640 서버의 코어 수를 Google Cloud의 vCPU에 매핑한다고 가정해 보겠습니다. Xeon E5640 사양은 공개적으로 제공되지만 시스템에서 lscpu와 같은 명령어를 실행하여 이를 확인할 수도 있습니다. 숫자는 다음과 같습니다.

  • 기존 코어 수 온프레미스=소켓(1)×코어(4)×코어당 스레드 수(2)=8
  • 최대 트래픽 중에 관찰된 CPU 사용률(사용률(%))이 40%라고 가정합니다.
  • 30%의 추가 버퍼를 프로비저닝합니다. 즉, 최대 CPU 사용률(임곗값(%))은 70%를 초과할 수 없습니다.
  • Google Cloud의 vCPU=2×CEILING[(8×0.4)/(2×0.7)]=vCPU 6개
    (즉, 2×CEILING[3.2/1.4]=2×CEILING[2.28]=2×3=6)

RAM, 디스크, 네트워크 I/O, 기타 시스템 리소스에 대해 유사한 평가를 수행할 수 있습니다.

성능 기반 크기 조정

이전 섹션에서는 CPU 사용량의 현재 및 예상 수준에 따라 pCPU를 vCPU에 매핑하는 방법을 자세히 설명했습니다. 이 섹션에서는 서버에서 실행 중인 애플리케이션을 고려합니다.

이 섹션에서는 성능을 벤치마킹하기 위해 표준 기반 테스트 세트(프로그램 기반 벤치마크)를 실행합니다. 예시 시나리오를 계속 진행하면 Xeon E5 머신에서 MySQL 서버를 실행하는 것이 좋습니다. 이 경우 Sysbench OLTP를 사용하여 데이터베이스 성능을 벤치마킹할 수 있습니다.

Sysbench를 사용하여 MySQL에 대한 간단한 읽기-쓰기 테스트를 수행하면 다음과 같은 출력을 생성합니다.

OLTP test statistics:
  queries performed:
    read:              520982
    write:             186058
    other:             74424
    total:             781464
  transactions:        37211 (620.12 per sec.)
  deadlocks:           2 (0.03 per sec.)
  read/write requests: 707040 (11782.80 per sec.)
  other operations:    74424 (1240.27 per sec.)

Test execution summary:
  total time:          60.0061s
  total number of events: 37211
  total time taken by event execution: 359.8158
  per-request statistics:
    min:            2.77ms
    avg:            9.67ms
    max:            50.81ms
    approx. 95 percentile: 14.63ms

Thread fairness:
  events (avg/stddev):         6201.8333/31.78
  execution time (avg/stddev): 59.9693/0.00

이 벤치마크를 실행하면 초당 트랜잭션 수, 초당 총 읽기/쓰기 수, 현재 환경과 Google Cloud 간의 엔드 투 엔드 실행 시간을 기준으로 성능을 비교할 수 있습니다. 이상점을 제외하기 위해 이러한 테스트를 여러 번 반복하는 것이 좋습니다. 다양한 로드 및 트래픽 패턴에서 성능 차이를 관찰하려면 동시 실행 수준, 테스트 기간, 시뮬레이션된 사용자 수 또는 다양한 해치 비율과 같은 다양한 매개변수를 사용하여 테스트를 반복할 수도 있습니다.

현재 환경과 Google Cloud 사이의 성능 수치는 초기 용량 평가의 합리화에 도움이 됩니다. Google Cloud의 벤치마킹 테스트가 기존 환경과 비슷하거나 더 나은 결과를 얻는 경우 성능 향상을 기반으로 리소스의 규모를 더 조정할 수 있습니다. 반면 기존 환경의 벤치마크가 Google Cloud보다 나은 경우 다음을 수행해야 합니다.

  • 초기 용량 평가를 다시 확인합니다.
  • 시스템 리소스를 모니터링합니다.
  • 가능한 경합 영역(예: CPU 및 RAM에서 발견된 병목 지점)을 찾습니다.
  • 리소스 크기를 적절하게 조정합니다.

작업이 완료되면 애플리케이션별 벤치마크 테스트를 다시 실행합니다.

엔드 투 엔드 성능 벤치마킹

지금까지 온프레미스와 Google Cloud 간의 MySQL 성능만 비교한 단순한 시나리오를 살펴보았습니다. 이 섹션에서는 다음과 같은 분산된 3계층 애플리케이션을 고려합니다.

분산형 3계층 애플리케이션

다이어그램에 나와 있듯이 현재 환경과 Google Cloud를 합리적으로 평가하기 위해 여러 벤치마크를 실행하는 경우가 많습니다. 하지만 애플리케이션 성능을 가장 정확하게 예측할 수 있는 벤치마크 하위 집합을 파악하기란 쉽지 않습니다. 또한 종속 항목 관리에서 여러 클라우드 또는 비클라우드 환경의 테스트 설치, 실행, 결과 집계에 이르기까지 테스트 프로세스를 관리하는 것은 지루한 작업일 수 있습니다. 이러한 시나리오에서는 PerfKitBenchmarker를 사용할 수 있습니다. PerfKit에는 여러 클라우드의 서로 다른 제품을 측정하고 비교하는 다양한 벤치마크 세트가 포함되어 있습니다. 정적 머신을 통해 특정 벤치마크를 온프레미스로 실행할 수도 있습니다.

위 다이어그램의 3계층 애플리케이션의 경우 Google Cloud에서 VM의 클러스터 부팅 시간, CPU, 네트워크 성능을 벤치마킹하기 위한 테스트를 실행한다고 가정해 보겠습니다. PerfKitBenchmarker를 사용하면 관련 테스트 프로필을 여러 번 반복 실행하여 다음과 같은 결과를 얻을 수 있습니다.

  • 클러스터 부팅 시간: VM 부팅 시간 뷰를 제공합니다. 이는 애플리케이션이 탄력적이며 자동 확장의 일부로 인스턴스가 추가되거나 삭제될 것으로 예상되는 경우 특히 중요합니다. 다음 그래프는 n1-standard-4 Compute Engine 인스턴스의 부팅 시간이 40~45초로 상당히 일관성이 있음(최대 99번째 백분위수)을 보여줍니다.

    n1-standard-4 Compute Engine 인스턴스의 부팅 시간입니다.

  • Stress-ng: 시스템의 프로세서, 메모리 하위 시스템, 컴파일러를 강조하여 컴퓨팅 집약적 성능을 측정하고 비교합니다. 다음 예시에서 stress-ngn1-standard-4 Compute Engine 인스턴스에서 bsearch, malloc, matrix mergesort, zlib 등 여러 부하 테스트를 실행합니다. Stress-ng초당 가짜 연산(bogo ops) 수를 사용하여 부하 테스트를 수행합니다. 다양한 부하 테스트 결과에서 가짜 연산을 정규화하면 초당 실행되는 연산의 기하 평균을 보여주는 다음 출력이 표시됩니다. 이 예시에서 가짜 연산의 범위는 50번째 백분위 수에서 초당 ~8,000개이며 95번째 백분위 수에서 초당 ~10,000개입니다. 가짜 연산은 일반적으로 독립형 CPU 성능만 벤치마킹하는 데 사용됩니다. 이러한 연산은 애플리케이션을 대표하지 않을 수 있습니다.

    초당 실행되는 연산의 기하 평균입니다.

  • Netperf: 요청 및 응답 테스트로 지연 시간을 측정합니다. 요청 및 응답 테스트는 네트워크 스택의 애플리케이션 레이어에서 실행됩니다. 이 지연 시간 테스트 방법은 스택의 모든 레이어를 포함하며 VM-VM 지연 시간을 측정하는 데 핑 테스트보다 선호됩니다. 다음 그래프는 동일한 Google Cloud 영역에서 실행 중인 클라이언트와 서버 간의 TCP 요청 및 응답(TCP_RR) 지연 시간을 보여줍니다. TCP_RR 값의 범위는 50번째 백분위 수에서 ~70마이크로초부터 90번째 백분위 수에서 ~130마이크로초입니다.

    동일한 Google Cloud 영역에서 실행되는 클라이언트와 서버 간의 TCP 요청 및 응답 지연 시간

대상 워크로드의 특성상 PerfKit을 사용하여 다른 테스트 프로필을 실행할 수 있습니다. 자세한 내용은 PerfKit에서 지원되는 벤치마크를 참조하세요.

Google Cloud의 권장사항

Google Cloud에서 마이그레이션 계획을 설정하고 실행하기 전에 마이그레이션 권장사항을 따르는 것이 좋습니다. 이러한 권장사항은 시작에 불과합니다. 종속 항목 분리, 내결함성 도입, 구성요소 워크로드에 따른 수직 확장 및 축소 등 애플리케이션의 여러 다른 측면과 이러한 각 측면이 Google Cloud에 매핑되는 방식을 고려해야 합니다.

  1. Google Cloud 한도 및 할당량을 파악합니다. 용량 평가를 공식적으로 시작하기 전에 Google Cloud의 리소스 계획을 위한 몇 가지 중요한 고려사항을 알아보세요. 예를 들면 다음과 같습니다.

    마이그레이션 중에 필요한 Infrastructure as a Service(IaaS) 및 Platform as a Service(PaaS) 구성요소를 나열하고 각 서비스에서 사용할 수 있는 할당량, 한도, 세부 조정을 명확하게 이해합니다.

  2. 지속적으로 리소스를 모니터링합니다. 지속적인 리소스 모니터링은 시스템 및 애플리케이션 성능의 패턴과 추세를 파악하는 데 도움이 됩니다. 모니터링은 기준 성능을 설정하는 데 도움이 될 뿐만 아니라 시간이 지남에 따라 하드웨어 업그레이드 및 다운그레이드가 필요한지 보여줍니다. Google Cloud는 엔드 투 엔드 모니터링 솔루션을 배포하는 데 다양한 옵션을 제공합니다.

  3. VM의 크기를 적절하게 조절합니다. VM이 과소 프로비저닝되거나 과다 프로비저닝되었는지 확인합니다. 기본 모니터링을 앞에서 설명한 대로 설정하면 이러한 통계를 쉽게 파악할 수 있습니다. 또한 Google Cloud는 인스턴스의 이전 사용량을 기준으로 적합한 크기 권장사항을 제공합니다. 또한 워크로드의 특성에 따라 사전 정의된 머신 유형이 필요에 맞지 않는 경우 커스텀 가상 하드웨어 설정으로 인스턴스를 만들 수 있습니다.

  4. 올바른 도구를 사용합니다. 대규모 환경의 경우 자동화된 도구를 배포하여 수동 작업을 최소화합니다. 예를 들면 다음과 같습니다.

핵심사항

한 환경에서 다른 환경으로 리소스를 마이그레이션하려면 신중한 계획이 필요합니다. 하드웨어 리소스를 따로 살펴 보지 말고 애플리케이션을 전체적으로 살펴보는 것이 중요합니다. 예를 들어 3.0GHz Sandy Bridge 프로세서가 1.5GHz Skylake 프로세서보다 2배 더 빠른 속도에 집중하는 대신 애플리케이션 플랫폼의 핵심성능지표가 컴퓨팅 플랫폼별로 어떻게 변하는지를 살펴보겠습니다.

여러 환경에서 리소스 매핑 요구사항을 평가할 때는 다음을 고려하세요.

  • 애플리케이션이 제약을 받는 시스템 리소스(예: CPU, 메모리, 디스크 또는 네트워크)
  • 기본 인프라의 영향(예: 프로세서 생성, 클록 속도, HDD 또는 SSD)이 애플리케이션 성능에 미치는 영향
  • 소프트웨어 또는 아키텍처 디자인 선택의 영향(예: 단일 또는 멀티 스레드 워크로드, 고정 또는 자동 확장 배포)이 애플리케이션의 성능에 미치는 영향
  • 컴퓨팅, 스토리지, 네트워크 리소스의 현재 및 예상 사용률 수준
  • 애플리케이션을 대표하는 가장 적합한 성능 테스트

지속적인 모니터링을 통해 이러한 측정항목에 대한 데이터를 수집하면 초기 용량 계획을 결정할 수 있습니다. 적절한 성능 벤치마킹을 수행하여 초기 크기 추정치를 세부 조정하여 후속 조치를 수행할 수 있습니다.

다음 단계